Exemple #1
0
 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());
                            };
 }
Exemple #3
0
        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);
            }
        }
Exemple #4
0
        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;
 }
Exemple #6
0
        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;
        }
Exemple #7
0
        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) - если функция возвращает значение
        }
Exemple #10
0
        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;
        }
Exemple #11
0
        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);
        }
Exemple #12
0
        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);
        }