예제 #1
0
        public override void Visit(BinaryOpNode node)
        {
            Contracts.AssertValue(node);

            if (TryShowValue(node))
            {
                return;
            }

            Precedence prec    = GetPrec(node.Op);
            Precedence prec1   = GetPrec(node.Left);
            Precedence prec2   = GetPrec(node.Right);
            bool       parens1 = NeedParensLeft(prec1, prec);
            bool       parens2 = NeedParensRight(prec, prec2);

            if (parens1)
            {
                _wrt.Write('(');
            }
            node.Left.Accept(this);
            if (parens1)
            {
                _wrt.Write(')');
            }

            _wrt.Write(GetString(node.Op));

            if (parens2)
            {
                _wrt.Write('(');
            }
            node.Right.Accept(this);
            if (parens2)
            {
                _wrt.Write(')');
            }

            ShowType(node);
        }
예제 #2
0
        // Parses the next (maximal) expression with precedence >= precMin.
        private ExprNode ParseExpr(Precedence precMin)
        {
            // ParseOperand may accept PrefixUnary and higher, so ParseExpr should never be called
            // with precMin > Precedence.PrefixUnary - it will not correctly handle those cases.
            Contracts.Assert(Precedence.None <= precMin);
            Contracts.Assert(precMin <= Precedence.PrefixUnary);

            // Get the left operand.
            ExprNode node = ParsePrimary();

            // Process operators and right operands as long as the precedence bound is satisfied.
            for (; ;)
            {
                Contracts.AssertValue(node);
                switch (TidCur)
                {
                case TokKind.Car:
                    Contracts.Assert(precMin <= Precedence.Power);
                    // Note that the right operand can include unary operators.
                    node = new BinaryOpNode(TokMove(), BinaryOp.Power, node, ParseExpr(Precedence.PrefixUnary));
                    break;

                case TokKind.Mul:
                    if (precMin > Precedence.Mul)
                    {
                        return(node);
                    }
                    node = new BinaryOpNode(TokMove(), BinaryOp.Mul, node, ParseExpr(Precedence.Mul + 1));
                    break;

                case TokKind.Div:
                    if (precMin > Precedence.Mul)
                    {
                        return(node);
                    }
                    node = new BinaryOpNode(TokMove(), BinaryOp.Div, node, ParseExpr(Precedence.Mul + 1));
                    break;

                case TokKind.Per:
                    if (precMin > Precedence.Mul)
                    {
                        return(node);
                    }
                    node = new BinaryOpNode(TokMove(), BinaryOp.Mod, node, ParseExpr(Precedence.Mul + 1));
                    break;

                case TokKind.Sub:
                    if (precMin > Precedence.Add)
                    {
                        return(node);
                    }
                    node = new BinaryOpNode(TokMove(), BinaryOp.Sub, node, ParseExpr(Precedence.Add + 1));
                    break;

                case TokKind.Add:
                    if (precMin > Precedence.Add)
                    {
                        return(node);
                    }
                    node = new BinaryOpNode(TokMove(), BinaryOp.Add, node, ParseExpr(Precedence.Add + 1));
                    break;

                case TokKind.AmpAmp:
                case TokKind.And:
                    if (precMin > Precedence.And)
                    {
                        return(node);
                    }
                    node = new BinaryOpNode(TokMove(), BinaryOp.And, node, ParseExpr(Precedence.And + 1));
                    break;

                case TokKind.BarBar:
                case TokKind.Or:
                    if (precMin > Precedence.Or)
                    {
                        return(node);
                    }
                    node = new BinaryOpNode(TokMove(), BinaryOp.Or, node, ParseExpr(Precedence.Or + 1));
                    break;

                case TokKind.QueQue:
                    if (precMin > Precedence.Coalesce)
                    {
                        return(node);
                    }
                    // Note that the associativity is different than other binary operators (right instead of left),
                    // so the recursive call accepts Precedence.Coal.
                    node = new BinaryOpNode(TokMove(), BinaryOp.Coalesce, node, ParseExpr(Precedence.Coalesce));
                    break;

                case TokKind.Que:
                    if (precMin > Precedence.Conditional)
                    {
                        return(node);
                    }
                    node = new ConditionalNode(TokMove(), node, ParseExpr(), TokEat(TokKind.Colon), ParseExpr());
                    break;

                // Comparison operators
                // expr = ... = expr
                // expr <> ... <> expr
                case TokKind.Equ:
                case TokKind.EquEqu:
                    if (precMin > Precedence.Compare)
                    {
                        return(node);
                    }
                    node = ParseCompareExpr(node, CompareOp.Equal, TokKind.Equ, TokKind.EquEqu);
                    break;

                case TokKind.LssGrt:
                case TokKind.BngEqu:
                    if (precMin > Precedence.Compare)
                    {
                        return(node);
                    }
                    node = ParseCompareExpr(node, CompareOp.NotEqual, TokKind.LssGrt, TokKind.BngEqu);
                    break;

                // expr < expr
                // expr <= expr
                case TokKind.Lss:
                case TokKind.LssEqu:
                    if (precMin > Precedence.Compare)
                    {
                        return(node);
                    }
                    node = ParseCompareExpr(node, CompareOp.IncrChain, TokKind.LssEqu, TokKind.Lss);
                    break;

                // expr > expr
                // expr >= expr
                case TokKind.Grt:
                case TokKind.GrtEqu:
                    if (precMin > Precedence.Compare)
                    {
                        return(node);
                    }
                    node = ParseCompareExpr(node, CompareOp.DecrChain, TokKind.GrtEqu, TokKind.Grt);
                    break;

                case TokKind.True:
                case TokKind.False:
                case TokKind.IntLit:
                case TokKind.FltLit:
                case TokKind.DblLit:
                case TokKind.CharLit:
                case TokKind.StrLit:
                    PostError(TokCur, "Operator expected");
                    node = new BinaryOpNode(TokCur, BinaryOp.Error, node, ParseExpr(Precedence.Error));
                    break;

                default:
                    return(node);
                }
            }
        }
예제 #3
0
 public override void PostVisit(BinaryOpNode node)
 {
     Contracts.Assert(false);
 }
예제 #4
0
 public override bool PreVisit(BinaryOpNode node)
 {
     Visit(node); return(false);
 }
예제 #5
0
 public abstract void Visit(BinaryOpNode node);
예제 #6
0
 public virtual bool PreVisit(BinaryOpNode node)
 {
     return(true);
 }