Advertisement
RaWRCoder

parse expression as value

Jun 24th, 2014
233
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 14.33 KB | None | 0 0
  1. private BaseValue parseAsValue(Expression e, DataType type, out bool err, bool forceByRef = false)
  2. {
  3.     //Пока все супер :)
  4.     err = false;
  5.  
  6.     //Вместо хвостовой рекурсии в одном месте.
  7.     //Для опускания лишних скобок без забития стека вызовов (ну бывают же маньяки)
  8.     while (true)
  9.     {
  10.         //Временная перменная, сюда мы запишем интересующий заказчика тип
  11.         //и будем с помощью этой переменной пытаться получит некоторые виды значений
  12.         var var = new Variable {DescribedType = type};
  13.  
  14.         //Первое слово. (Обязательно должно быть)
  15.         var w0 = e.Blocks[0];
  16.  
  17.         //Разобьем наше выражение на аргументы бинарных операторов. Если они есть.
  18.         for (var j = 0; j < 3; j++)//цикл по приоритетам
  19.             for (var i = e.Blocks.Count - 2; i > 0; i--)//цикл по словам
  20.             {
  21.                 var b = e.Blocks[i];//очередное слово
  22.                 var opKind = b.IsBinaryOperator0;
  23.                 if (j > 0)
  24.                     opKind = j > 1 ? b.IsBinaryOperator2 : b.IsBinaryOperator1;
  25.  
  26.                 //Очередное слово - бинарный оператор максимального приритета?
  27.                 if (!opKind) continue;//нет - продолжим поиски
  28.  
  29.                 var op1 = new Expression();
  30.                 var op2 = new Expression();
  31.                 op1.Blocks.AddRange(e.Blocks.GetRange(0, i));//выражение слева
  32.                 op2.Blocks.AddRange(e.Blocks.GetRange(i + 1, e.Blocks.Count - i - 1));//выражение справа
  33.  
  34.                 //Посчитаем значение оператора, если это возможно
  35.                 var result = handleBinaryOperator(op1, op2, b.Content, out err);
  36.  
  37.                 //Ашипка???
  38.                 if (err)
  39.                     return null; //Жри, пидар
  40.  
  41.                 //Колышит ли нас, какой тип мы должны вернуть?
  42.                 if (type == null)
  43.                     return result; //по-барабану - вернем что насчитали
  44.  
  45.                 //А иначе. будем заниматься приведением типов
  46.                 if (result.ActualType.CanCastTo(type))
  47.                 {
  48.                     var castedResult = result.ActualType.GetCasterTo(type)(result);
  49.                     if (castedResult != null || type.IsForm || type.SimpleType == ESimpleType.Object)
  50.                         return castedResult;
  51.                 }
  52.                 //Нам не удалось привести значение к нужному типу. Пусть пользователь соснет хуйцов
  53.                 Error.PostSyntax(
  54.                     Error.SX_TYPE_MISMATCH,
  55.                     Error.Make_SX_TYPE_MISMATCH(result.ActualType.ToString(), type.ToString()),
  56.                     CurrentFile);
  57.                 return null;
  58.             }
  59.         //А если бинарных нет, тогда продолжим
  60.         //Первое слово - унарный оператор?
  61.         if (w0.IsUnaryOperator)
  62.         {
  63.             //есть аргумент?
  64.             if (e.Blocks.Count == 1)
  65.             {
  66.                 err = true;//нет :(
  67.                 return null;//бля..
  68.             }
  69.             var op1 = new Expression();
  70.             op1.Blocks.AddRange(e.Blocks.GetRange(1, e.Blocks.Count - 1));
  71.  
  72.             //Посчитаем значение оператора, если это возможно
  73.             var result = handleUnaryOperator(op1, w0.Content, out err);
  74.  
  75.             //Ошиблись?
  76.             if (err)
  77.                 return null; //Извольте получить null
  78.  
  79.             //Заказчику интересен тип?
  80.             if (type == null)
  81.                 return result; //нит, отдаем, что имеем
  82.  
  83.             //А иначе будем заниматься приведением типов
  84.             if (result.ActualType.CanCastTo(type))
  85.             {
  86.                 var castedResult = result.ActualType.GetCasterTo(type)(result);
  87.                 if (castedResult != null || type.IsForm || type.SimpleType == ESimpleType.Object)
  88.                     return castedResult;
  89.             }
  90.  
  91.             //Нам не удалось привести значение к нужному типу (или получили какую-то хуйню).
  92.             //Предложим юзеру лососнуть тунцов
  93.             Error.PostSyntax(
  94.                 Error.SX_TYPE_MISMATCH,
  95.                 Error.Make_SX_TYPE_MISMATCH(result.ActualType.ToString(), type.ToString()),
  96.                 CurrentFile);
  97.             return null;
  98.         }
  99.         //Первое слово НЕ унарный оператор, идем дальше
  100.  
  101.         //Первое слово имеет непонятные скобки?
  102.         if (w0.Braces != EBraces.NoBraces && w0.Braces != EBraces.Braces && w0.Braces != EBraces.StringLiteral)
  103.         {
  104.             //Для нас это нежданчик, ибо синтаксисом не предусмотрены [] и {} в начале синтаксического блока
  105.             if (type != null)
  106.             Error.PostSyntax(Error.SX_TYPE_MISMATCH, Error.Make_SX_TYPE_MISMATCH(w0.ToString(), type.Name),
  107.                 CurrentFile);
  108.             err = true;
  109.             return null;
  110.         }
  111.         //Итак, первое слово - не унарный оператор и вероятно вполне понятное слово
  112.  
  113.         //Единственное ли оно?
  114.         if (e.Blocks.Count == 1)
  115.         {
  116.             //Наше слово - строковой литерал?
  117.             if (w0.Braces == EBraces.StringLiteral)
  118.             {
  119.                 //Прочитаем его и попытаемся записать в перменную заданного типа
  120.                 if (var.SetValueFromLiteral(w0.Content, true))
  121.                     return var.Value;
  122.  
  123.                 //Упс, не получилось Оо. Следующий код практический недостижим, но перестрахуемся
  124.                 if (type != null)
  125.                     Error.PostSyntax(Error.SX_TYPE_MISMATCH, Error.Make_SX_TYPE_MISMATCH("string", type.Name), CurrentFile);
  126.                 err = true;
  127.                 return null;
  128.             }
  129.  
  130.             //Нет ли скобок?
  131.             if (w0.Braces == EBraces.NoBraces)
  132.             {//Нет стало быть...
  133.                 //Константа и она подходит под тип?
  134.                 if (var.SetValueFromLiteral(w0.Content))
  135.                     return var.Value;//Отлично
  136.  
  137.                 //Иначе перед нами вероятнее всего имя некого объекта, будь то перменная или тип
  138.                 Variable v;
  139.  
  140.                 //Сущетвует ли перменная с таким именем?
  141.                 if (CurrentScope.ResolveName(w0.Content, out v))
  142.                 {
  143.                     //Существует, тогда не побито ли значение?
  144.                     if (v.Value == null)
  145.                     {
  146.                         //Нулевое значение вполне устроит переменные типа object и формы
  147.                         if (var.DescribedType == TypeObject || var.DescribedType.IsForm)
  148.                             return null;
  149.  
  150.                         //Другим перменным null не понравится, если нам не без разницы тип
  151.                         if (type != null)
  152.                         {
  153.                             Error.PostSyntax(
  154.                                 Error.SX_WRONG_VALUE,
  155.                                 Error.Make_SX_WRONG_VALUE("<undefined>", type.ToString()),
  156.                                 CurrentFile);
  157.                             err = true;
  158.                         }
  159.  
  160.                         //Пусть наслаждаются нулем
  161.                         return null;
  162.                     }
  163.                     //Итак полученое значение - некое значение, а не нуль
  164.  
  165.                     //Заказчика не волнует тип?
  166.                     if (type == null)
  167.                         //тогда если его интересует ссылка, дадим ссылку, иначе - дадим копию
  168.                         return forceByRef ? v.Value : v.Value.GetCopy();
  169.  
  170.                     //(ниже внешней среде важно соответсвие типов)
  171.  
  172.                     //Приводимо ли значение к нужному типу?
  173.                     if (v.Value.ActualType.CanCastTo(type))
  174.                     {
  175.                         //Приводимо, тогда попытаемся привести
  176.                         var nval = v.Value.ActualType.GetCasterTo(type)(v.Value);
  177.  
  178.                         //Получился null?
  179.                         if (nval == null)
  180.                         {
  181.                             //Нулевое значение вполне устроит переменные типа object и формы
  182.                             if (var.DescribedType == TypeObject || var.DescribedType.IsForm)
  183.                                 return null;
  184.  
  185.                             //Другим перменным null не понравится
  186.                             Error.PostSyntax(
  187.                                 Error.SX_TYPE_MISMATCH,
  188.                                 Error.Make_SX_TYPE_MISMATCH(v.Value.ActualType.ToString(), type.ToString()),
  189.                                 CurrentFile);
  190.                             err = true;
  191.                             return null;
  192.                         }
  193.  
  194.                         //Если заказчику нужна ссылка на значение, он получит ссылку
  195.                         if (forceByRef) return nval;
  196.  
  197.                         //Иначе мы либо даем ссылку, либо копию, в зависимости от типа данных
  198.                         return var.CanBeFormReference ? nval : nval.GetCopy();
  199.                     }
  200.  
  201.                     //Полученое значение неверного/неприводимого типа
  202.                     Error.PostSyntax(
  203.                         Error.SX_TYPE_MISMATCH,
  204.                         Error.Make_SX_TYPE_MISMATCH(v.Value.ActualType.ToString(), type.ToString()),
  205.                         CurrentFile);
  206.                     err = true;
  207.                     return v.Value;
  208.                 }
  209.  
  210.                 //Переменная с таким именем не найдена. Ничего другого я искать больше не буду
  211.                 Error.PostSyntax(Error.RT_UNDEFINED_NAME, Error.Make_RT_UNDEFINED_NAME(w0.Content), CurrentFile);
  212.                 err = true;
  213.                 return null;
  214.             }
  215.             //Наше слово в скобках?
  216.             if (w0.Braces == EBraces.Braces)
  217.             {
  218.                 //Раз так, тогда расмотрим выражение в скобках отдельно
  219.                 var = null;
  220.                 e = w0;
  221.                 continue;//типа хвостовая рекурсия. но цикл
  222.             }
  223.         }
  224.  
  225.         //Слов несколько значит?
  226.         if (e.Blocks.Count >= 2)
  227.         {
  228.             //Начинается со слова в скобках?
  229.             if (w0.Braces == EBraces.Braces)
  230.             {
  231.                 //Похоже пользователь собрался явно приводить типы
  232.                 //Попробуем узнать тип...
  233.                 var dtval = parseAsValue(w0, TypeType, out err);
  234.                 //Не тип? бля ну хз тогда, че эт за хуйня такая
  235.                 if (err) return null;
  236.                 //Выковыряем сам тип из оболочки
  237.                 var dt = ((TypeValue) dtval).Value;
  238.                
  239.                 //Составим выражение из оставшися слов...
  240.                 var exp2 = new Expression();
  241.                 for (var i = 1; i < e.Blocks.Count; i++)
  242.                 {
  243.                     exp2.Blocks.Add(e.Blocks[i]);
  244.                 }
  245.  
  246.                 //И запарсим значение этого выражения. Конкретный тип назвать сложно, скорее всего не возможно
  247.                 var val = parseAsValue(exp2, null, out err);
  248.                 if (err)
  249.                 {
  250.                     //При парсинге произошла ошибка. Уведомим юзера о его кривых паьлцах
  251.                     Error.PostWierdExpression(exp2, CurrentFile);
  252.                     return null;
  253.                 }
  254.  
  255.                 //Получилось выражение с непонятным типом? (КАК?)
  256.                 if (val.ActualType == null)
  257.                 {
  258.                     err = true;
  259.                     //Браво, вы сломали систему
  260.                     Error.PostWierdExpression(exp2, CurrentFile);
  261.                     return null;
  262.                 }
  263.  
  264.                 //Можно ли привести к указанному в первом слове типу?
  265.                 if (!val.ActualType.CanCastTo(dt))
  266.                 {
  267.                     //Ага бля! нихуя!
  268.                     err = true;
  269.                     Error.PostSyntax(
  270.                         Error.SX_TYPE_MISMATCH,
  271.                         Error.Make_SX_TYPE_MISMATCH(val.ActualType.ToString(), dt.ToString()),
  272.                         CurrentFile);
  273.                     return null;
  274.                 }
  275.  
  276.                 //Можно, тады пробуем...
  277.                 var nval = val.ActualType.GetCasterTo(dt)(val);
  278.  
  279.                 //Че, неполучилось?
  280.                 if (nval == null && (val.ActualType.IsSimpleType || dt.IsSimpleType))
  281.                 {
  282.                     //И вправду, гавно подсунули, пидрилы
  283.                     err = true;
  284.                     Error.PostSyntax(
  285.                         Error.SX_TYPE_MISMATCH,
  286.                         Error.Make_SX_TYPE_MISMATCH(val.ActualType.ToString(), dt.ToString()),
  287.                         CurrentFile);
  288.                     return null;
  289.                 }
  290.                 //Раз мы тут значит все хорошо. Первое приведение типов, указанное пользователем явно мы сделали
  291.  
  292.                 //Ебет ли заказчика тип данных?
  293.                 if (type == null)
  294.                     //Не сильно, отдадим, что имеем, прямо сейчас
  295.                     return nval;
  296.                 //Ну а раз ебет, тогда снова приводим к новому типу
  297.  
  298.                 //Стоп, а есть чо приводить то?
  299.                 if (nval == null)
  300.                 {
  301.                     //Бля, нуль. Месье устроит нуль?
  302.                     if ((type.IsSimpleType && type.SimpleType == ESimpleType.Object) || (type.IsForm))
  303.                     {}
  304.                     else
  305.                     {
  306.                         //нет? вах, абыдно
  307.                         Error.PostSyntax(
  308.                             Error.SX_TYPE_MISMATCH,
  309.                             Error.Make_SX_TYPE_MISMATCH("<undefined>", type.ToString()),
  310.                             CurrentFile);
  311.                         err = true;
  312.                     }
  313.                     //В любом случае, извольте засосать это прямо сейчас!
  314.                     return null;
  315.                 }
  316.  
  317.                 //ок, значение приличное. Можно приводить?
  318.                 if (!nval.ActualType.CanCastTo(type))
  319.                 {
  320.                     //Ептваюмать, ара, ты чооо?!...
  321.                     Error.PostSyntax(
  322.                         Error.SX_TYPE_MISMATCH,
  323.                         Error.Make_SX_TYPE_MISMATCH(nval.ActualType.ToString(), type.ToString()),
  324.                         CurrentFile);
  325.                     //... ты чо делаишь ептаааа?!
  326.                     err = true;
  327.                     return null;
  328.                 }
  329.  
  330.                 //Можно! А раз можно - пробуем!
  331.                 var eval = nval.ActualType.GetCasterTo(type)(nval);
  332.  
  333.                 //Все хорошо?
  334.                 if (eval == null)
  335.                 {
  336.                     //Упс, нулик получился
  337.                     if (!type.IsForm && type.SimpleType != ESimpleType.Object)
  338.                     {
  339.                         //и нас он, блять, не устраивает!
  340.                         Error.PostSyntax(
  341.                             Error.SX_TYPE_MISMATCH,
  342.                             Error.Make_SX_TYPE_MISMATCH(nval.ActualType.ToString(), type.ToString()),
  343.                             CurrentFile);
  344.                         err = true;
  345.                     }
  346.                     return null;
  347.                 }
  348.  
  349.                 //Все супер, вернем полученное значение
  350.                 return eval;
  351.  
  352.             }
  353.             //Скобок нет.
  354.             else
  355.             {
  356.                 //Значит вызов функции ...
  357.                 //TODO: Function call
  358.                 //... либо нам опять кидают какое то дермецо
  359.             }
  360.         }
  361.         err = true;
  362.         return null;
  363.     }
  364. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement