Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- private BaseValue parseAsValue(Expression e, DataType type, out bool err, bool forceByRef = false)
- {
- //Пока все супер :)
- err = false;
- //Вместо хвостовой рекурсии в одном месте.
- //Для опускания лишних скобок без забития стека вызовов (ну бывают же маньяки)
- while (true)
- {
- //Временная перменная, сюда мы запишем интересующий заказчика тип
- //и будем с помощью этой переменной пытаться получит некоторые виды значений
- var var = new Variable {DescribedType = type};
- //Первое слово. (Обязательно должно быть)
- var w0 = e.Blocks[0];
- //Разобьем наше выражение на аргументы бинарных операторов. Если они есть.
- for (var j = 0; j < 3; j++)//цикл по приоритетам
- for (var i = e.Blocks.Count - 2; i > 0; i--)//цикл по словам
- {
- var b = e.Blocks[i];//очередное слово
- var opKind = b.IsBinaryOperator0;
- if (j > 0)
- opKind = j > 1 ? b.IsBinaryOperator2 : b.IsBinaryOperator1;
- //Очередное слово - бинарный оператор максимального приритета?
- if (!opKind) continue;//нет - продолжим поиски
- var op1 = new Expression();
- var op2 = new Expression();
- op1.Blocks.AddRange(e.Blocks.GetRange(0, i));//выражение слева
- op2.Blocks.AddRange(e.Blocks.GetRange(i + 1, e.Blocks.Count - i - 1));//выражение справа
- //Посчитаем значение оператора, если это возможно
- var result = handleBinaryOperator(op1, op2, b.Content, out err);
- //Ашипка???
- if (err)
- return null; //Жри, пидар
- //Колышит ли нас, какой тип мы должны вернуть?
- if (type == null)
- return result; //по-барабану - вернем что насчитали
- //А иначе. будем заниматься приведением типов
- if (result.ActualType.CanCastTo(type))
- {
- var castedResult = result.ActualType.GetCasterTo(type)(result);
- if (castedResult != null || type.IsForm || type.SimpleType == ESimpleType.Object)
- return castedResult;
- }
- //Нам не удалось привести значение к нужному типу. Пусть пользователь соснет хуйцов
- Error.PostSyntax(
- Error.SX_TYPE_MISMATCH,
- Error.Make_SX_TYPE_MISMATCH(result.ActualType.ToString(), type.ToString()),
- CurrentFile);
- return null;
- }
- //А если бинарных нет, тогда продолжим
- //Первое слово - унарный оператор?
- if (w0.IsUnaryOperator)
- {
- //есть аргумент?
- if (e.Blocks.Count == 1)
- {
- err = true;//нет :(
- return null;//бля..
- }
- var op1 = new Expression();
- op1.Blocks.AddRange(e.Blocks.GetRange(1, e.Blocks.Count - 1));
- //Посчитаем значение оператора, если это возможно
- var result = handleUnaryOperator(op1, w0.Content, out err);
- //Ошиблись?
- if (err)
- return null; //Извольте получить null
- //Заказчику интересен тип?
- if (type == null)
- return result; //нит, отдаем, что имеем
- //А иначе будем заниматься приведением типов
- if (result.ActualType.CanCastTo(type))
- {
- var castedResult = result.ActualType.GetCasterTo(type)(result);
- if (castedResult != null || type.IsForm || type.SimpleType == ESimpleType.Object)
- return castedResult;
- }
- //Нам не удалось привести значение к нужному типу (или получили какую-то хуйню).
- //Предложим юзеру лососнуть тунцов
- Error.PostSyntax(
- Error.SX_TYPE_MISMATCH,
- Error.Make_SX_TYPE_MISMATCH(result.ActualType.ToString(), type.ToString()),
- CurrentFile);
- return null;
- }
- //Первое слово НЕ унарный оператор, идем дальше
- //Первое слово имеет непонятные скобки?
- if (w0.Braces != EBraces.NoBraces && w0.Braces != EBraces.Braces && w0.Braces != EBraces.StringLiteral)
- {
- //Для нас это нежданчик, ибо синтаксисом не предусмотрены [] и {} в начале синтаксического блока
- if (type != null)
- Error.PostSyntax(Error.SX_TYPE_MISMATCH, Error.Make_SX_TYPE_MISMATCH(w0.ToString(), type.Name),
- CurrentFile);
- err = true;
- return null;
- }
- //Итак, первое слово - не унарный оператор и вероятно вполне понятное слово
- //Единственное ли оно?
- if (e.Blocks.Count == 1)
- {
- //Наше слово - строковой литерал?
- if (w0.Braces == EBraces.StringLiteral)
- {
- //Прочитаем его и попытаемся записать в перменную заданного типа
- if (var.SetValueFromLiteral(w0.Content, true))
- return var.Value;
- //Упс, не получилось Оо. Следующий код практический недостижим, но перестрахуемся
- if (type != null)
- Error.PostSyntax(Error.SX_TYPE_MISMATCH, Error.Make_SX_TYPE_MISMATCH("string", type.Name), CurrentFile);
- err = true;
- return null;
- }
- //Нет ли скобок?
- if (w0.Braces == EBraces.NoBraces)
- {//Нет стало быть...
- //Константа и она подходит под тип?
- if (var.SetValueFromLiteral(w0.Content))
- return var.Value;//Отлично
- //Иначе перед нами вероятнее всего имя некого объекта, будь то перменная или тип
- Variable v;
- //Сущетвует ли перменная с таким именем?
- if (CurrentScope.ResolveName(w0.Content, out v))
- {
- //Существует, тогда не побито ли значение?
- if (v.Value == null)
- {
- //Нулевое значение вполне устроит переменные типа object и формы
- if (var.DescribedType == TypeObject || var.DescribedType.IsForm)
- return null;
- //Другим перменным null не понравится, если нам не без разницы тип
- if (type != null)
- {
- Error.PostSyntax(
- Error.SX_WRONG_VALUE,
- Error.Make_SX_WRONG_VALUE("<undefined>", type.ToString()),
- CurrentFile);
- err = true;
- }
- //Пусть наслаждаются нулем
- return null;
- }
- //Итак полученое значение - некое значение, а не нуль
- //Заказчика не волнует тип?
- if (type == null)
- //тогда если его интересует ссылка, дадим ссылку, иначе - дадим копию
- return forceByRef ? v.Value : v.Value.GetCopy();
- //(ниже внешней среде важно соответсвие типов)
- //Приводимо ли значение к нужному типу?
- if (v.Value.ActualType.CanCastTo(type))
- {
- //Приводимо, тогда попытаемся привести
- var nval = v.Value.ActualType.GetCasterTo(type)(v.Value);
- //Получился null?
- if (nval == null)
- {
- //Нулевое значение вполне устроит переменные типа object и формы
- if (var.DescribedType == TypeObject || var.DescribedType.IsForm)
- return null;
- //Другим перменным null не понравится
- Error.PostSyntax(
- Error.SX_TYPE_MISMATCH,
- Error.Make_SX_TYPE_MISMATCH(v.Value.ActualType.ToString(), type.ToString()),
- CurrentFile);
- err = true;
- return null;
- }
- //Если заказчику нужна ссылка на значение, он получит ссылку
- if (forceByRef) return nval;
- //Иначе мы либо даем ссылку, либо копию, в зависимости от типа данных
- return var.CanBeFormReference ? nval : nval.GetCopy();
- }
- //Полученое значение неверного/неприводимого типа
- Error.PostSyntax(
- Error.SX_TYPE_MISMATCH,
- Error.Make_SX_TYPE_MISMATCH(v.Value.ActualType.ToString(), type.ToString()),
- CurrentFile);
- err = true;
- return v.Value;
- }
- //Переменная с таким именем не найдена. Ничего другого я искать больше не буду
- Error.PostSyntax(Error.RT_UNDEFINED_NAME, Error.Make_RT_UNDEFINED_NAME(w0.Content), CurrentFile);
- err = true;
- return null;
- }
- //Наше слово в скобках?
- if (w0.Braces == EBraces.Braces)
- {
- //Раз так, тогда расмотрим выражение в скобках отдельно
- var = null;
- e = w0;
- continue;//типа хвостовая рекурсия. но цикл
- }
- }
- //Слов несколько значит?
- if (e.Blocks.Count >= 2)
- {
- //Начинается со слова в скобках?
- if (w0.Braces == EBraces.Braces)
- {
- //Похоже пользователь собрался явно приводить типы
- //Попробуем узнать тип...
- var dtval = parseAsValue(w0, TypeType, out err);
- //Не тип? бля ну хз тогда, че эт за хуйня такая
- if (err) return null;
- //Выковыряем сам тип из оболочки
- var dt = ((TypeValue) dtval).Value;
- //Составим выражение из оставшися слов...
- var exp2 = new Expression();
- for (var i = 1; i < e.Blocks.Count; i++)
- {
- exp2.Blocks.Add(e.Blocks[i]);
- }
- //И запарсим значение этого выражения. Конкретный тип назвать сложно, скорее всего не возможно
- var val = parseAsValue(exp2, null, out err);
- if (err)
- {
- //При парсинге произошла ошибка. Уведомим юзера о его кривых паьлцах
- Error.PostWierdExpression(exp2, CurrentFile);
- return null;
- }
- //Получилось выражение с непонятным типом? (КАК?)
- if (val.ActualType == null)
- {
- err = true;
- //Браво, вы сломали систему
- Error.PostWierdExpression(exp2, CurrentFile);
- return null;
- }
- //Можно ли привести к указанному в первом слове типу?
- if (!val.ActualType.CanCastTo(dt))
- {
- //Ага бля! нихуя!
- err = true;
- Error.PostSyntax(
- Error.SX_TYPE_MISMATCH,
- Error.Make_SX_TYPE_MISMATCH(val.ActualType.ToString(), dt.ToString()),
- CurrentFile);
- return null;
- }
- //Можно, тады пробуем...
- var nval = val.ActualType.GetCasterTo(dt)(val);
- //Че, неполучилось?
- if (nval == null && (val.ActualType.IsSimpleType || dt.IsSimpleType))
- {
- //И вправду, гавно подсунули, пидрилы
- err = true;
- Error.PostSyntax(
- Error.SX_TYPE_MISMATCH,
- Error.Make_SX_TYPE_MISMATCH(val.ActualType.ToString(), dt.ToString()),
- CurrentFile);
- return null;
- }
- //Раз мы тут значит все хорошо. Первое приведение типов, указанное пользователем явно мы сделали
- //Ебет ли заказчика тип данных?
- if (type == null)
- //Не сильно, отдадим, что имеем, прямо сейчас
- return nval;
- //Ну а раз ебет, тогда снова приводим к новому типу
- //Стоп, а есть чо приводить то?
- if (nval == null)
- {
- //Бля, нуль. Месье устроит нуль?
- if ((type.IsSimpleType && type.SimpleType == ESimpleType.Object) || (type.IsForm))
- {}
- else
- {
- //нет? вах, абыдно
- Error.PostSyntax(
- Error.SX_TYPE_MISMATCH,
- Error.Make_SX_TYPE_MISMATCH("<undefined>", type.ToString()),
- CurrentFile);
- err = true;
- }
- //В любом случае, извольте засосать это прямо сейчас!
- return null;
- }
- //ок, значение приличное. Можно приводить?
- if (!nval.ActualType.CanCastTo(type))
- {
- //Ептваюмать, ара, ты чооо?!...
- Error.PostSyntax(
- Error.SX_TYPE_MISMATCH,
- Error.Make_SX_TYPE_MISMATCH(nval.ActualType.ToString(), type.ToString()),
- CurrentFile);
- //... ты чо делаишь ептаааа?!
- err = true;
- return null;
- }
- //Можно! А раз можно - пробуем!
- var eval = nval.ActualType.GetCasterTo(type)(nval);
- //Все хорошо?
- if (eval == null)
- {
- //Упс, нулик получился
- if (!type.IsForm && type.SimpleType != ESimpleType.Object)
- {
- //и нас он, блять, не устраивает!
- Error.PostSyntax(
- Error.SX_TYPE_MISMATCH,
- Error.Make_SX_TYPE_MISMATCH(nval.ActualType.ToString(), type.ToString()),
- CurrentFile);
- err = true;
- }
- return null;
- }
- //Все супер, вернем полученное значение
- return eval;
- }
- //Скобок нет.
- else
- {
- //Значит вызов функции ...
- //TODO: Function call
- //... либо нам опять кидают какое то дермецо
- }
- }
- err = true;
- return null;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement