예제 #1
0
        /// <summary>
        /// The following are rules for C expressions.
        /// </summary>
        public static void SetExpressionRules()
        {
            // expression
            //   : assignment-expression [ ',' assignment-expression ]*
            Expression.Is(
                AssignmentExpression
                .OneOrMore(Comma)
                .Then(exprs => {
                if (exprs.Count == 1)
                {
                    return(exprs[0]);
                }
                return(AssignmentList.Create(exprs));
            })
                );

            // primary-expression
            //   : identifier          # Cannot be a typedef name.
            //   | constant
            //   | string-literal
            //   | '(' expression ')'
            PrimaryExpression.Is(
                Either(Variable)
                .Or(Constant)
                .Or(StringLiteral)
                .Or(
                    (LeftParen).Then(Expression).Then(RightParen)
                    )
                );

            // An identifier for a variable must not be defined as a typedef name.
            Variable.Is(
                Identifier.Check(result => !result.Environment.IsTypedefName(result.Result)).Then(AST.Variable.Create)
                );

            // constant
            //   : const-char
            //   : const-int
            //   : const-float
            Constant.Is(
                Either(ConstChar)
                .Or(ConstInt)
                .Or(ConstFloat)
                );


            // constant-expression
            //   : conditional-expression
            //
            // Note:
            // The size of an array should be a constant.
            // Note that the check is actually performed in semantic analysis.
            ConstantExpression.Is(
                ConditionalExpression
                );

            // conditional-expression
            //   : logical-or-expression [ '?' expression ':' conditional-expression ]?
            ConditionalExpression.Is(
                (LogicalOrExpression)
                .Then(
                    Given <Expr>()
                    .Then(Question)
                    .Then(Expression)
                    .Then(Colon)
                    .Then(ConditionalExpression)
                    .Then(AST.ConditionalExpression.Create)
                    .Optional()
                    )
                );

            // assignment-expression
            //   : unary-expression assignment-operator assignment-expression   # first-set = first-set(unary-expression)
            //   | conditional-expression                                       # first-set = first-set(cast-expression) = first-set(unary-expression) ++ { '(' }
            //
            // Note:
            //   Assignment operators are:
            //     '=', '*=', '/=', '%=', '+=', '-=', '<<=', '>>=', '&=', '^=', '|='
            AssignmentExpression.Is(
                Either(
                    AssignmentOperator(
                        UnaryExpression,
                        AssignmentExpression,
                        BinaryOperatorBuilder.Create(Assign, Assignment.Create),
                        BinaryOperatorBuilder.Create(MultAssign, AST.MultAssign.Create),
                        BinaryOperatorBuilder.Create(DivAssign, AST.DivAssign.Create),
                        BinaryOperatorBuilder.Create(ModAssign, AST.ModAssign.Create),
                        BinaryOperatorBuilder.Create(AddAssign, AST.AddAssign.Create),
                        BinaryOperatorBuilder.Create(SubAssign, AST.SubAssign.Create),
                        BinaryOperatorBuilder.Create(LeftShiftAssign, LShiftAssign.Create),
                        BinaryOperatorBuilder.Create(RightShiftAssign, RShiftAssign.Create),
                        BinaryOperatorBuilder.Create(BitwiseAndAssign, AST.BitwiseAndAssign.Create),
                        BinaryOperatorBuilder.Create(XorAssign, AST.XorAssign.Create),
                        BinaryOperatorBuilder.Create(BitwiseOrAssign, AST.BitwiseOrAssign.Create)
                        )
                    ).Or(
                    ConditionalExpression
                    )
                );

            // postfix-expression
            //   : primary-expression [
            //         '[' expression ']'                      # Get element from array
            //       | '(' [argument-expression-list]? ')'     # Function call
            //       | '.' identifier                          # Get member from struct/union
            //       | '->' identifier                         # Get member from struct/union
            //       | '++'                                    # Increment
            //       | '--'                                    # Decrement
            //     ]*
            PostfixExpression.Is(
                PrimaryExpression
                .Then(
                    Either(
                        Given <Expr>()
                        .Then(LeftBracket)
                        .Then(Expression)
                        .Then(RightBracket)
                        .Then((array, index) => Dereference.Create(AST.Add.Create(array, index)))
                        ).Or(
                        Given <Expr>()
                        .Then(LeftParen)
                        .Then(ArgumentExpressionList.Optional(ImmutableList <Expr> .Empty))
                        .Then(RightParen)
                        .Then(FuncCall.Create)
                        ).Or(
                        Given <Expr>()
                        .Then(Period)
                        .Then(Identifier)
                        .Then(Attribute.Create)
                        ).Or(
                        Given <Expr>()
                        .Then(RightArrow)
                        .Then(Identifier)
                        .Then((expr, member) => Attribute.Create(Dereference.Create(expr), member))
                        ).Or(
                        Given <Expr>()
                        .Then(Increment)
                        .Then(PostIncrement.Create)
                        ).Or(
                        Given <Expr>()
                        .Then(Decrement)
                        .Then(PostDecrement.Create)
                        ).ZeroOrMore()
                    )
                );

            // argument-expression-list
            //   : assignment-expression [ ',' assignment-expression ]*
            ArgumentExpressionList.Is(
                AssignmentExpression.OneOrMore(Comma)
                );

            // unary-expression
            //   : postfix-expression               # first-set = { id, const, string }
            //   | '++' unary-expression            # first-set = { '++' }
            //   | '--' unary-expression            # first-set = { '--' }
            //   | unary-operator cast-expression   # first-set = { '&', '*', '+', '-', '~', '!' }
            //   | 'sizeof' unary-expression        # first-set = { 'sizeof' }
            //   | 'sizeof' '(' Type-name ')'       # first-set = { 'sizeof' }
            //
            // Notes:
            // 1. unary-operator can be '&', '*', '+', '-', '~', '!'.
            // 2. The last two rules are ambiguous: you can't figure out whether the x in sizeof(x) is a typedef of a variable.
            //    I have a parser hack for this: add a parser environment to track all the typedefs.
            // 3. first_set = first_set(postfix-expression) + { '++', '--', '&', '*', '+', '-', '~', '!', 'sizeof' }
            //              = first_set(primary-expression) + { '++', '--', '&', '*', '+', '-', '~', '!', 'sizeof' }
            //              = { id, const, string, '++', '--', '&', '*', '+', '-', '~', '!', 'sizeof' }
            UnaryExpression.Is(
                Either(
                    PostfixExpression
                    ).Or(
                    (Increment).Then(UnaryExpression).Then(PreIncrement.Create)
                    ).Or(
                    (Decrement).Then(UnaryExpression).Then(PreDecrement.Create)
                    ).Or(
                    (BitwiseAnd).Then(CastExpression).Then(Reference.Create)
                    ).Or(
                    (Mult).Then(CastExpression).Then(Dereference.Create)
                    ).Or(
                    (Add).Then(CastExpression).Then(Positive.Create)
                    ).Or(
                    (Sub).Then(CastExpression).Then(Negative.Create)
                    ).Or(
                    (BitwiseNot).Then(CastExpression).Then(AST.BitwiseNot.Create)
                    ).Or(
                    (LogicalNot).Then(CastExpression).Then(AST.LogicalNot.Create)
                    ).Or(
                    (SizeOf).Then(UnaryExpression).Then(SizeofExpr.Create)
                    ).Or(
                    (SizeOf).Then(LeftParen).Then(TypeName).Then(RightParen).Then(SizeofType.Create)
                    )
                );

            // cast-expression
            //   : unary-expression                     # first-set = { id, const, string, '++', '--', '&', '*', '+', '-', '~', '!', 'sizeof' }
            //   | '(' type_name ')' cast-expression    # first-set = '('
            CastExpression.Is(
                Either(
                    UnaryExpression
                    ).Or(
                    (LeftParen).Then(TypeName).Then(RightParen).Then(CastExpression)
                    .Then(TypeCast.Create)
                    )
                );

            // multiplicative-expression
            //   : cast-expression [ [ '*' | '/' | '%' ] cast-expression ]*
            MultiplicativeExpression.Is(
                BinaryOperator(
                    CastExpression,
                    BinaryOperatorBuilder.Create(Mult, Multiply.Create),
                    BinaryOperatorBuilder.Create(Div, Divide.Create),
                    BinaryOperatorBuilder.Create(Mod, Modulo.Create)
                    )
                );

            // additive-expression
            //   : multiplicative-expression [ [ '+' | '-' ] multiplicative-expression ]*
            AdditiveExpression.Is(
                BinaryOperator(
                    MultiplicativeExpression,
                    BinaryOperatorBuilder.Create(Add, AST.Add.Create),
                    BinaryOperatorBuilder.Create(Sub, AST.Sub.Create)
                    )
                );

            // shift-expression
            //   : additive-expression [ [ '<<' | '>>' ] additive-expression ]*
            ShiftExpression.Is(
                BinaryOperator(
                    AdditiveExpression,
                    BinaryOperatorBuilder.Create(LeftShift, LShift.Create),
                    BinaryOperatorBuilder.Create(RightShift, RShift.Create)
                    )
                );

            // relational-expression
            //   : shift-expression [ [ '<' | '>' | '<=' | '>=' ] shift-expression ]*
            RelationalExpression.Is(
                BinaryOperator(
                    ShiftExpression,
                    BinaryOperatorBuilder.Create(Less, AST.Less.Create),
                    BinaryOperatorBuilder.Create(Greater, AST.Greater.Create),
                    BinaryOperatorBuilder.Create(LessEqual, LEqual.Create),
                    BinaryOperatorBuilder.Create(GreaterEqual, GEqual.Create)
                    )
                );

            // equality-expression
            //   : relational-expression [ [ '==' | '!=' ] relational-expression ]*
            EqualityExpression.Is(
                BinaryOperator(
                    RelationalExpression,
                    BinaryOperatorBuilder.Create(Equal, AST.Equal.Create),
                    BinaryOperatorBuilder.Create(NotEqual, AST.NotEqual.Create)
                    )
                );

            // and-expression
            //   : equality-expression [ '&' equality-expression ]*
            AndExpression.Is(
                BinaryOperator(
                    EqualityExpression,
                    BinaryOperatorBuilder.Create(BitwiseAnd, AST.BitwiseAnd.Create)
                    )
                );

            // exclusive-or-expression
            //   : and-expression [ '^' and-expression ]*
            ExclusiveOrExpression.Is(
                BinaryOperator(
                    AndExpression,
                    BinaryOperatorBuilder.Create(Xor, AST.Xor.Create)
                    )
                );

            // inclusive-or-expression
            //   : exclusive-or-expression [ '|' exclusive-or-expression ]*
            InclusiveOrExpression.Is(
                BinaryOperator(
                    ExclusiveOrExpression,
                    BinaryOperatorBuilder.Create(BitwiseOr, AST.BitwiseOr.Create)
                    )
                );

            // logical-and-expression
            //   : inclusive-or-expression [ '&&' inclusive-or-expression ]*
            LogicalAndExpression.Is(
                BinaryOperator(
                    InclusiveOrExpression,
                    BinaryOperatorBuilder.Create(LogicalAnd, AST.LogicalAnd.Create)
                    )
                );

            // logical-or-expression
            //   :logical-and-expression [ '||' logical-and-expression ]*
            LogicalOrExpression.Is(
                BinaryOperator(
                    LogicalAndExpression,
                    BinaryOperatorBuilder.Create(LogicalOr, AST.LogicalOr.Create)
                    )
                );
        }