public static void AddVariable(Lexem nameIn, object value) { var name = nameIn.Content.ToString(); if (Variables.Any(x => x.Name == name)) throw new SyntaxException("Переменная с таким именем уже существует", nameIn); var variable = new Variable(name, value); Variables.Add(variable); }
public InputWindow(Lexem lexem) { InitializeComponent(); DataContext = lexem; lblInfo.Content = "Введите значение переменной \"" + lexem.Content + "\":"; tbInput.Focus(); tbInput.KeyDown += (sender, args) => { if (args.Key == Key.Enter) ButtonClickConfirm(this, new RoutedEventArgs()); }; }
public static void AddArrayVariable(Lexem nameIn, Lexem size) { var name = nameIn.Content.ToString(); try { var arrSize = Convert.ToInt32(size.ToDouble()); var array = new Array(arrSize, name); AddVariable(nameIn, array); } catch (Exception) { throw new SyntaxException("Размерность массива должна быть целочисленной", size); } }
public static Variable GetVariable(object nameIn, Lexem pos = null) { var name = nameIn.ToString(); if (pos == null) { return Variables.Single(x => x.Name == name); } var position = Convert.ToInt32(pos.ToDouble()); try { return (Variables.Single(x => x.Name == name).Value as Array).GetElement(position); } catch (Exception ex) { throw new SyntaxException(ex.Message, pos); } }
public SyntaxException(string message, Lexem lexem) : base(message) { Lexem = lexem; }
public List<Lexem> ToLexems() { _result = new List<Lexem>(); int index = 0; LexemType customLexem; while (currentPosition < _input.Length) { customLexem = LexemType.None; current = String.Empty; index = currentPosition; if (index >= _input.Length) break; if (Char.IsDigit(_input[index])) // числа 12345 { while (Char.IsLetterOrDigit(_input[index]) || _input[index] == '.') { if (Char.IsLetter(_input[index])) { var errLexem = new Lexem(current + _input[index], LexemType.None, currentPosition); throw new SyntaxException("Введено некорректное число", errLexem); } current += _input[index++]; } if (!_lexemStrings.Contains(_input[index].ToString()) && _input[index] != '\r' && _input[index] != '\n' && _input[index] != ' ') { var errLex = new Lexem(current + _input[index], LexemType.None, currentPosition); throw new SyntaxException("Введено некорректное число", errLex); } current = current.Replace('.', ','); if (current.Count(x => x == ',') > 1) { var errLexem = new Lexem(current, LexemType.None, currentPosition); throw new SyntaxException("Введено некорректное число", errLexem); } } else if (Char.IsLetter(_input[index]) || _input[index] == '_') // служебные слова, VAR, print { while (Char.IsLetterOrDigit(_input[index]) || _input[index] == '_') { current += _input[index++]; } if (!_lexemStrings.Contains(_input[index].ToString()) && _input[index] != '\r' && _input[index] != '\n' && _input[index] != ' ') { var errLex = new Lexem(_input[index].ToString(), LexemType.None, index); throw new SyntaxException("Неверная лексема", errLex); } } else if (_lexemStrings.Contains(_input[index].ToString())) // операторы { current += _input[index++]; if (current == "\"") { current = string.Empty; while (_input[index] != '\"') { current += _input[index++]; } index++; customLexem = LexemType.String; } else if (current == "/" && _input[index] == '/') // комментарий { while (_input[index] != '\n') { index++; } currentPosition = index; continue; } else if (((current == "=" || current == ">" || current == "<" || current == "!") && _input[index] == '=') || (current == "|" && _input[index] == '|') || (current == "&" && _input[index] == '&') || (current == "+" && _input[index] == '+') || (current == "-" && _input[index] == '-')) { current += _input[index++]; } var next = _input[index]; if (current == "!" || current == "|" || current == "&" || !_lexemStrings.Contains(next.ToString()) && next != '\r' && next != '\n' && !Char.IsLetterOrDigit(next) && next != ' ' && (current != "=" || current != ">" || current != "<" || current != "+" || current != "-")) { var errLex = new Lexem(current + next, LexemType.None, currentPosition); throw new SyntaxException("Введён некорректный оператор", errLex); } } else // ненужные символы { currentPosition = ++index; continue; } _curLexem = customLexem != LexemType.None ? new Lexem(current, customLexem, index - current.Length) : new Lexem(current, TypeOfToken(current), index - current.Length); // Fix "," = "var" if (_curLexem.Content.Equals(",") && _curLexem.LexemType == LexemType.Operator) { _curLexem.Content = "var"; } _result.Add(_curLexem); _prevLexem = _curLexem; currentPosition = index; if (_prevLexem.LexemType == LexemType.EndOfExpr || _prevLexem.LexemType == LexemType.Brace) break; _curLexem = null; } // HACK: -(2+3) for (int i = 0; i < _result.Count; i++) { if (_result[i].Content.Equals("-")) { if (i == 0 || (_result[i + 1].LexemType == LexemType.LeftBracket)) { _result.Remove(_result[i]); _result.Insert(i, new Lexem("-1", LexemType.Number, i-2)); _result.Insert(i, new Lexem("*", LexemType.Operator, i)); } } } return _result; }
private LexemType TypeOfToken(string lexem) { double tmpNum; if (double.TryParse(lexem, out tmpNum)) return LexemType.Number; if (_operators.Contains(lexem)) return LexemType.Operator; if (lexem.Equals(",") && _result.Any(x => x.Content.ToString() == "var" && x.LexemType == LexemType.Operator)) { lexem = "var"; } if (lexem.Equals("(")) return LexemType.LeftBracket; if (lexem.Equals("[")) return LexemType.LeftBrace; if (lexem.Equals(")")) return LexemType.RightBracket; if (lexem.Equals(";")) return LexemType.EndOfExpr; if (lexem.Equals("{") || lexem.Equals("}")) return LexemType.Brace; if (lexem.Equals("const")) return LexemType.ModificatorCandidate; if (lexem.Equals("var")) { if (_prevLexem.LexemType == LexemType.ModificatorCandidate) { _result.Last().LexemType = LexemType.Modificator; } return LexemType.Operator; } if (lexem.Equals("true") || lexem.Equals("false")) return LexemType.Boolean; if (_specWords.Contains(lexem)) return LexemType.SpecialWord; if (_functions.Contains(lexem)) return LexemType.Function; if (_prevLexem.Content.ToString() == "var" || Storage.VariableExists(lexem)) return LexemType.Variable; if (_curLexem == null) _curLexem = new Lexem(current, LexemType.None, currentPosition); throw new SyntaxException("Незнакомая лексема", _curLexem); }
private object ProcessOperator(Lexem oper, Lexem leftValue, Lexem rightValue, ref LexemType lt) { if (oper.Content.ToString() == "]") { lt = LexemType.Variable; return Storage.GetVariable(leftValue.Content.ToString(), rightValue); } return Helper.Calculate(oper, leftValue, rightValue, ref lt); }
private void ProcessFunction(Lexem lex) { var args = new List<Lexem>(); switch (lex.Content.ToString()) { case "print": while (Stack.Count > 0) { var arg = Stack.Pop(); args.Insert(0, arg); } Storage.AddToOutput(args, false); break; case "println": while (Stack.Count > 0) { var arg = Stack.Pop(); args.Insert(0, arg); } Storage.AddToOutput(args, true); break; case "scan": case "read": while (Stack.Count > 0) { var arg = Stack.Pop(); args.Insert(0, arg); } foreach (var lexem in args.Where(x => x.LexemType == LexemType.Variable)) { var window = new Editor.InputWindow(lexem); window.ShowDialog(); } break; case "rand": var rand = _rand.Next(Convert.ToInt32(Stack.Pop().ToDouble())); Stack.Push(new Lexem(rand, LexemType.Number, lex.Position)); break; } // Stack.Push(result) - если функция возвращает значение }
public static void SetVariableValue(Lexem nameIn, object value) { if (nameIn.Content is Variable) { var concrVar = nameIn.Content as Variable; if (concrVar.IsConst) { throw new SyntaxException("Нельзя изменить значение константы", nameIn); } concrVar.Value = value; return; } var name = nameIn.Content.ToString(); var variable = Variables.Single(x => x.Name == name); if (variable.IsConst) { throw new SyntaxException("Невозможно изменить значение константы", nameIn); } variable.Value = value; }
public static object Calculate(Lexem oper, Lexem leftValue, Lexem rightValue, ref LexemType lt) { var t = PickCorrectType(leftValue, rightValue); switch (t) { case TypeCode.Double: lt = LexemType.Number; switch (oper.Content.ToString()) { case "*": return leftValue.ToDouble() * rightValue.ToDouble(); case "/": return leftValue.ToDouble() / rightValue.ToDouble(); case "+": return leftValue.ToDouble() + rightValue.ToDouble(); case "-": return leftValue.ToDouble() - rightValue.ToDouble(); case ">": lt = LexemType.Boolean; return leftValue.ToDouble() > rightValue.ToDouble(); case "<": lt = LexemType.Boolean; return leftValue.ToDouble() < rightValue.ToDouble(); case "!=": lt = LexemType.Boolean; return leftValue.ToDouble() != rightValue.ToDouble(); case "==": lt = LexemType.Boolean; return leftValue.ToDouble() == rightValue.ToDouble(); case ">=": lt = LexemType.Boolean; return leftValue.ToDouble() >= rightValue.ToDouble(); case "<=": lt = LexemType.Boolean; return leftValue.ToDouble() <= rightValue.ToDouble(); case "=": Storage.SetVariableValue(leftValue, rightValue.ToDouble()); if (leftValue.Content is Variable) return (leftValue.Content as Variable).Value; return Storage.GetVariable(leftValue.Content.ToString()); } break; case TypeCode.String: lt = LexemType.String; switch (oper.Content.ToString()) { case "+": return leftValue.ToString() + rightValue.ToString(); case "!=": lt = LexemType.Boolean; return leftValue.ToString() != rightValue.ToString(); case "==": lt = LexemType.Boolean; return leftValue.ToString() == rightValue.ToString(); case "=": Storage.SetVariableValue(leftValue, rightValue.ToString()); if (leftValue.Content is Variable) return (leftValue.Content as Variable).Value; return Storage.GetVariable(leftValue.Content.ToString()); default: throw new SyntaxException("Неверная операция", oper); } case TypeCode.Boolean: lt = LexemType.Boolean; switch (oper.Content.ToString()) { case "||": return leftValue.ToBoolean() || rightValue.ToBoolean(); case "&&": return leftValue.ToBoolean() && rightValue.ToBoolean(); case "==": return leftValue.ToBoolean() == rightValue.ToBoolean(); case "!=": return leftValue.ToBoolean() != rightValue.ToBoolean(); case "=": Storage.SetVariableValue(leftValue, rightValue.ToBoolean()); if (leftValue.Content is Variable) return (leftValue.Content as Variable).Value; return Storage.GetVariable(leftValue.Content.ToString()); default: throw new SyntaxException("Неверная операция", oper); } } throw new SyntaxException("Ошибка вычисления оператора", oper); }
private static TypeCode PickCorrectType(Lexem leftValue, Lexem rightValue) { LexemType lType = leftValue.LexemType, rType = rightValue.LexemType; if (lType == LexemType.Number && rType == LexemType.Number) { return TypeCode.Double; } if (lType == LexemType.String && rType == LexemType.String) { return TypeCode.String; } if (lType == LexemType.Variable && rType == LexemType.Number || lType == LexemType.String && rType == LexemType.Number) { try { leftValue.ToDouble(); return TypeCode.Double; } catch (Exception) { return TypeCode.String; } } if (lType == LexemType.Number && rType == LexemType.Variable || lType == LexemType.Number && rType == LexemType.String) { try { rightValue.ToDouble(); return TypeCode.Double; } catch (Exception) { return TypeCode.String; } } if (lType == LexemType.Variable && rType == LexemType.String || lType == LexemType.String && rType == LexemType.Variable) { return TypeCode.String; } if (lType == LexemType.Variable && rType == LexemType.Boolean || lType == LexemType.Boolean && rType == LexemType.Variable) { return TypeCode.Boolean; } if (lType == LexemType.Boolean && rType == LexemType.Boolean) { return TypeCode.Boolean; } if (lType == LexemType.Variable && rType == LexemType.Variable) { try { leftValue.ToDouble(); return TypeCode.Double; } catch (Exception) { try { leftValue.ToBoolean(); return TypeCode.Boolean; } catch (Exception) { return TypeCode.String; } } } throw new SyntaxException("Не удалось определить общий тип", leftValue); }