简体   繁体   中英

Antlr4: dealing with priority and left-side recursion at the same time

I'm writing a language parser in Antlr4. I'm already quite well versed with it, but I don't want to fall into a pitfall (again), so here it is:

expression
    |   gate=expression QUESTION
            (ifTrue=expression)? COLON
            (ifFalse=expression)?               # TernaryExpression
    |   Identifier                              # IdentifierExpression
    |   literal                                 # LiteralExpression
    |   expression logicalComparator expression # LogicalComparisonExpression
    |   expression logicalOperator expression   # LogicalOperationExpression
    ;

and the input:

user.field == 'STRING' ? user.field + user.otherField : user.somethingElse

The tree I obtain is:

(expression
    (expression
        (expression user) . (expression field)
    )
    (logicalComparator = =)
    (expression
        (expression (literal 'STRING'))
        ? (expression
            (expression
                (expression user) . (expression field)
            )
            (binaryOperator +)
            (expression
                (expression user) . (expression otherField)
            )
        )
        : (expression
            (expression user) . (expression somethingElse)
        )
    )
)

(An expression of logical comparison, where left-hand-side is user.field, comparator is == and right-hand-side is the ternary operator.)

The actual result should be a ternary operator, where gate expression is a logical comparison.

How can I fix it? I was certain, that the fact I placed TernaryExpression above LogicalComparisonExpression will suffice, but apparently it doesn't.

Ok, here is the workaround. I don't like it, but it seems to work for some reason.

In expression rule, changed

|   expression logicalComparator expression # LogicalComparisonExpression

to

|   lhs=expression operator=(   DEQUALS
                                 |LSHARP
                             ) rhs=expression # LogicalComparisonExpression

I placed only two items in operator=(...) for testing purposes.

This has some negative effects though:

  1. inline definition of operators <- I'd love to have them separate for readability.
  2. forces me to tokenize '==' instead of '=' '='. If I try:

    operator=(EQUALS EQUALS | LSHARP)

I get "label assigned to a block which is not a set".

I guess I'll work with this, but I'd still to see if it can be done better.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM