N-ary operator parsing

2019-09-19 06:01发布

I'm trying to match an operator of variable arity (e.g. "1 < 3 < x < 10" yields true, given that 3 < x < 10) within a mathematical expression. Note that this is unlike most languages would parse the expression) The (simplified) production rule is:

expression: '(' expression ')'                  # parenthesisExpression
      | expression ('*' | '/' | '%') expression # multiplicationExpression
      | expression ('+' | '-') expression       # additionExpression
      | expression (SMALLER_THAN expression)+   # smallerThanExpression
      | IDENTIFIER                              # variableExpression
      ;

How do we keep the precedence, but still parse the smallerThanExpression as greedy as possible?

For example; "1 < 1+1 < 3" should be parsed as a single parse node "smallerThanExpression" with three child nodes, each of which is an expression. At this moment, the smallerThanExpression is broken up in two smallerThanExpressions (1 < (1+1 < 3)).

标签: antlr4
1条回答
欢心
2楼-- · 2019-09-19 06:36

To give an answer for "future generations": we fixed it by separating arithmetic expressions from the other expressions. We know that only arithmetic expressions can be used as operands for our variable-arity operators ('true < false' is not a valid expression).

expression: 
        '!' expression
      | arithmetic (SMALLER_THAN arithmetic)+
      | arithmetic (GREATER_THAN arithmetic)+
      | ....
      ;

arithmetic:
        '(' expression ')'                 
      | expression ('*' | '/' | '%') expression 
      | expression ('+' | '-') expression 
      | IDENTIFIER
      | ...
      ;

This enforces an expression such as "x < y < z" to be parsed as a single 'expression' node with three 'arithmetic' nodes as children.

(Note that an identifier might refer to a non-integer object; this is checked in the context checker)

查看更多
登录 后发表回答