예제 #1
0
파일: Parser.cs 프로젝트: RoboLOGO/IDE
        Expr ParseExpr()
        {
            var OpStack = new Stack<Operator>();
            var CStack = new Stack<Expr>();
            ExprNext NextCanBe = ExprNext.UExpr | ExprNext.BExpr | ExprNext.Literal | ExprNext.Bracket;
            while (Index < Tokens.Count)
            {
                // token is literal (double, int, bool, string, function call)
                if (NextCanBe.HasFlag(ExprNext.Literal))
                {
                    if (Tokens[Index].isSB)
                    {
                        var stringLiteral = new StringLiteral();
                        stringLiteral.Value = ((StringBuilder)Tokens[Index]).ToString();
                        Index++;
                        CStack.Push(stringLiteral);
                        NextCanBe = ExprNext.BExpr;
                        continue;
                    }
                    else if (Tokens[Index].isInt)
                    {
                        var intLiteral = new IntLiteral();
                        intLiteral.Value = (int)Tokens[Index];
                        Index++;
                        CStack.Push(intLiteral);
                        NextCanBe = ExprNext.BExpr;
                        continue;
                    }
                    else if (Tokens[Index].isDbl)
                    {
                        var dblLiteral = new DblLiteral();
                        dblLiteral.Value = (double)Tokens[Index];
                        NextCanBe = ExprNext.BExpr;
                        Index++;
                        CStack.Push(dblLiteral);
                        continue;
                    }
                    else if (Tokens[Index].isStr && FuncDef.ContainsKey((string)Tokens[Index]))
                    {    // If function is exists
                        var function = new ExprFunction();
                        function.Identity = (string)Tokens[Index];
                        var P = FuncDef[(string)Tokens[Index]].Parameters.Count;
                        int i = 0;
                        Index++;
                        while (Index < Tokens.Count && i < P)
                        {
                            function.Parameters.Add(ParseExpr());
                            i++;
                        }
                        if (Index == Tokens.Count && i < P)
                        {
                            throw new RPExeption(29, App.Current.TryFindResource("x_fparnm").ToString(), Line, Column);
                        }
                        CStack.Push(function);
                        NextCanBe = ExprNext.BExpr;
                        continue;
                    }
                }

                // if token is not expression either break
                if (!NextCanBe.HasFlag(ExprNext.UExpr) && !NextCanBe.HasFlag(ExprNext.BExpr) && !NextCanBe.HasFlag(ExprNext.Bracket) || !Tokens[Index].isStr) break;
                // else token is an operator
                switch ((string)Tokens[Index])
                {
                    case Scanner.BracketStart:
                        if (NextCanBe.HasFlag(ExprNext.Bracket))
                        {
                            Index++;
                            OpStack.Push(new Group());
                            NextCanBe = ExprNext.UExpr | ExprNext.BExpr | ExprNext.Literal | ExprNext.Bracket;
                            continue;
                        }
                        break;
                    case Scanner.BracketEnd:
                        {
                            Index++;
                            var o = (OpStack.Count > 0) ? OpStack.Peek() : null;
                            while (OpStack.Count > 0 && !(o is Group))
                            {
                                if (o.IsBinary)
                                {
                                    var expr = new BinaryExpression();
                                    expr.BinaryOperator = OpStack.Pop();
                                    if (expr.BinaryOperator.Level >= OpStack.Peek().Level)
                                    {
                                        expr.Right = CStack.Pop();
                                        expr.Left = CStack.Pop();
                                    }
                                    else
                                    {
                                        expr.Left = CStack.Pop();
                                        expr.Right = CStack.Pop();
                                    }
                                    CStack.Push(expr);
                                }
                                else
                                {
                                    var expr = new UnaryExpression();
                                    expr.Right = CStack.Pop();
                                    expr.UnaryOperator = OpStack.Pop();
                                    CStack.Push(expr);
                                }
                                if (OpStack.Count > 0) o = OpStack.Peek();
                            }
                            if (OpStack.Count > 0)
                            {
                                OpStack.Pop();
                                NextCanBe = ExprNext.BExpr;
                            }
                            else NextCanBe = 0;
                            continue;
                        }
                    case Scanner.ValueOf:
                        if (NextCanBe.HasFlag(ExprNext.UExpr))
                        {
                            Index++;
                            var var = new Variable();
                            var.Identity = (string)Tokens[Index];
                            CStack.Push(var);
                            OpStack.Push(new ValueOf());
                            NextCanBe = ExprNext.BExpr;
                            Index++;
                            continue;
                        }
                        break;
                    case Scanner.AsIs:
                        if (NextCanBe.HasFlag(ExprNext.UExpr))
                        {
                            Index++;
                            var strL = new StringLiteral();
                            strL.Value = (string)Tokens[Index];
                            CStack.Push(strL);
                            OpStack.Push(new AsIs());
                            NextCanBe = ExprNext.BExpr;
                            Index++;
                            continue;
                        }
                        break;
                    case Scanner.And:
                    case Scanner.Or:
                    case Scanner.Xor:
                    case Scanner.Not:
                    case Scanner.Add:
                    case Scanner.Subtract:
                    case Scanner.Multiply:
                    case Scanner.Divide:
                    case Scanner.Equal:
                    case Scanner.Bigger:
                    case Scanner.BiggerEqual:
                    case Scanner.Smaller:
                    case Scanner.SmallerEqual:
                    case Scanner.NotEqual:
                        {
                            var op = Operator.Parse((string)Tokens[Index]);
                            var o = (OpStack.Count > 0) ? OpStack.Peek() : op;
                            while (OpStack.Count > 0 && op.Level >= o.Level && !(o is Group))
                            {
                                if (o.IsBinary)
                                {
                                    var expr = new BinaryExpression();
                                    expr.Right = CStack.Pop();
                                    expr.BinaryOperator = OpStack.Pop();
                                    expr.Left = CStack.Pop();
                                    CStack.Push(expr);
                                }
                                else
                                {
                                    var expr = new UnaryExpression();
                                    expr.Right = CStack.Pop();
                                    expr.UnaryOperator = OpStack.Pop();
                                    CStack.Push(expr);
                                }
                                if (OpStack.Count > 0) o = OpStack.Peek();
                            }
                            if (CStack.Count == 0 && op is Sub || Diff(CStack, OpStack) && op is Sub) op = new Minus();        // If there was no literal before or previous token was also an operator
                            OpStack.Push(op);
                            NextCanBe = ExprNext.BExpr | ExprNext.UExpr | ExprNext.Literal | ExprNext.Bracket;
                            Index++;
                            continue;
                        }
                }
                break;
            }
            while (OpStack.Count > 0)
            {
                var o = OpStack.Peek();
                if (o.IsBinary)
                {
                    var expr = new BinaryExpression();
                    expr.Right = CStack.Pop();
                    expr.BinaryOperator = OpStack.Pop();
                    expr.Left = CStack.Pop();
                    CStack.Push(expr);
                }
                else
                {
                    var expr = new UnaryExpression();
                    expr.Right = CStack.Pop();
                    expr.UnaryOperator = OpStack.Pop();
                    CStack.Push(expr);
                }
            }
            return CStack.Pop();
        }
예제 #2
0
        Expr ParseExpr()
        {
            var      OpStack   = new Stack <Operator>();
            var      CStack    = new Stack <Expr>();
            ExprNext NextCanBe = ExprNext.UExpr | ExprNext.BExpr | ExprNext.Literal | ExprNext.Bracket;

            while (Index < Tokens.Count)
            {
                // token is literal (double, int, bool, string, function call)
                if (NextCanBe.HasFlag(ExprNext.Literal))
                {
                    if (Tokens[Index].isSB)
                    {
                        var stringLiteral = new StringLiteral();
                        stringLiteral.Value = ((StringBuilder)Tokens[Index]).ToString();
                        Index++;
                        CStack.Push(stringLiteral);
                        NextCanBe = ExprNext.BExpr;
                        continue;
                    }
                    else if (Tokens[Index].isInt)
                    {
                        var intLiteral = new IntLiteral();
                        intLiteral.Value = (int)Tokens[Index];
                        Index++;
                        CStack.Push(intLiteral);
                        NextCanBe = ExprNext.BExpr;
                        continue;
                    }
                    else if (Tokens[Index].isDbl)
                    {
                        var dblLiteral = new DblLiteral();
                        dblLiteral.Value = (double)Tokens[Index];
                        NextCanBe        = ExprNext.BExpr;
                        Index++;
                        CStack.Push(dblLiteral);
                        continue;
                    }
                    else if (Tokens[Index].isStr && FuncDef.ContainsKey((string)Tokens[Index]))
                    {    // If function is exists
                        var function = new ExprFunction();
                        function.Identity = (string)Tokens[Index];
                        var P = FuncDef[(string)Tokens[Index]].Parameters.Count;
                        int i = 0;
                        Index++;
                        while (Index < Tokens.Count && i < P)
                        {
                            function.Parameters.Add(ParseExpr());
                            i++;
                        }
                        if (Index == Tokens.Count && i < P)
                        {
                            throw new RPExeption(29, App.Current.TryFindResource("x_fparnm").ToString(), Line, Column);
                        }
                        CStack.Push(function);
                        NextCanBe = ExprNext.BExpr;
                        continue;
                    }
                }

                // if token is not expression either break
                if (!NextCanBe.HasFlag(ExprNext.UExpr) && !NextCanBe.HasFlag(ExprNext.BExpr) && !NextCanBe.HasFlag(ExprNext.Bracket) || !Tokens[Index].isStr)
                {
                    break;
                }
                // else token is an operator
                switch ((string)Tokens[Index])
                {
                case Scanner.BracketStart:
                    if (NextCanBe.HasFlag(ExprNext.Bracket))
                    {
                        Index++;
                        OpStack.Push(new Group());
                        NextCanBe = ExprNext.UExpr | ExprNext.BExpr | ExprNext.Literal | ExprNext.Bracket;
                        continue;
                    }
                    break;

                case Scanner.BracketEnd:
                {
                    Index++;
                    var o = (OpStack.Count > 0) ? OpStack.Peek() : null;
                    while (OpStack.Count > 0 && !(o is Group))
                    {
                        if (o.IsBinary)
                        {
                            var expr = new BinaryExpression();
                            expr.BinaryOperator = OpStack.Pop();
                            if (expr.BinaryOperator.Level >= OpStack.Peek().Level)
                            {
                                expr.Right = CStack.Pop();
                                expr.Left  = CStack.Pop();
                            }
                            else
                            {
                                expr.Left  = CStack.Pop();
                                expr.Right = CStack.Pop();
                            }
                            CStack.Push(expr);
                        }
                        else
                        {
                            var expr = new UnaryExpression();
                            expr.Right         = CStack.Pop();
                            expr.UnaryOperator = OpStack.Pop();
                            CStack.Push(expr);
                        }
                        if (OpStack.Count > 0)
                        {
                            o = OpStack.Peek();
                        }
                    }
                    if (OpStack.Count > 0)
                    {
                        OpStack.Pop();
                        NextCanBe = ExprNext.BExpr;
                    }
                    else
                    {
                        NextCanBe = 0;
                    }
                    continue;
                }

                case Scanner.ValueOf:
                    if (NextCanBe.HasFlag(ExprNext.UExpr))
                    {
                        Index++;
                        var var = new Variable();
                        var.Identity = (string)Tokens[Index];
                        CStack.Push(var);
                        OpStack.Push(new ValueOf());
                        NextCanBe = ExprNext.BExpr;
                        Index++;
                        continue;
                    }
                    break;

                case Scanner.AsIs:
                    if (NextCanBe.HasFlag(ExprNext.UExpr))
                    {
                        Index++;
                        var strL = new StringLiteral();
                        strL.Value = (string)Tokens[Index];
                        CStack.Push(strL);
                        OpStack.Push(new AsIs());
                        NextCanBe = ExprNext.BExpr;
                        Index++;
                        continue;
                    }
                    break;

                case Scanner.And:
                case Scanner.Or:
                case Scanner.Xor:
                case Scanner.Not:
                case Scanner.Add:
                case Scanner.Subtract:
                case Scanner.Multiply:
                case Scanner.Divide:
                case Scanner.Equal:
                case Scanner.Bigger:
                case Scanner.BiggerEqual:
                case Scanner.Smaller:
                case Scanner.SmallerEqual:
                case Scanner.NotEqual:
                {
                    var op = Operator.Parse((string)Tokens[Index]);
                    var o  = (OpStack.Count > 0) ? OpStack.Peek() : op;
                    while (OpStack.Count > 0 && op.Level >= o.Level && !(o is Group))
                    {
                        if (o.IsBinary)
                        {
                            var expr = new BinaryExpression();
                            expr.Right          = CStack.Pop();
                            expr.BinaryOperator = OpStack.Pop();
                            expr.Left           = CStack.Pop();
                            CStack.Push(expr);
                        }
                        else
                        {
                            var expr = new UnaryExpression();
                            expr.Right         = CStack.Pop();
                            expr.UnaryOperator = OpStack.Pop();
                            CStack.Push(expr);
                        }
                        if (OpStack.Count > 0)
                        {
                            o = OpStack.Peek();
                        }
                    }
                    if (CStack.Count == 0 && op is Sub || Diff(CStack, OpStack) && op is Sub)
                    {
                        op = new Minus();                                                                                      // If there was no literal before or previous token was also an operator
                    }
                    OpStack.Push(op);
                    NextCanBe = ExprNext.BExpr | ExprNext.UExpr | ExprNext.Literal | ExprNext.Bracket;
                    Index++;
                    continue;
                }
                }
                break;
            }
            while (OpStack.Count > 0)
            {
                var o = OpStack.Peek();
                if (o.IsBinary)
                {
                    var expr = new BinaryExpression();
                    expr.Right          = CStack.Pop();
                    expr.BinaryOperator = OpStack.Pop();
                    expr.Left           = CStack.Pop();
                    CStack.Push(expr);
                }
                else
                {
                    var expr = new UnaryExpression();
                    expr.Right         = CStack.Pop();
                    expr.UnaryOperator = OpStack.Pop();
                    CStack.Push(expr);
                }
            }
            return(CStack.Pop());
        }