Using the infix syntax
Let’s implement a simple expression grammar with the following operators:
| Operator | Precedence | Associativity |
|---|---|---|
+ |
1 | Left |
- |
1 | Left |
* |
2 | Left |
/ |
2 | Left |
^ |
3 | Right |
Expression: BinaryExpr;
infix BinaryExpr on PrimaryExpression:
right assoc '^'
> '*' | '/'
> '+' | '-'
;
PrimaryExpression: '(' expr=Expression ')' | value=Number;
In addition to better readability, the new notation also makes use of performance optimizations to speed up expression parsing by roughly 50% compared to the typical way of writing expressions.
The PrimaryExpression rule defines the basic building blocks of our expressions, which can be (for example) a parenthesized expression, an unary expression, or a number literal.
Expression: BinaryExpr;
infix BinaryExpr on PrimaryExpression:
...
;
PrimaryExpression: '(' expr=Expression ')' | '-' value=PrimaryExpression | value=Number | ...;
Use the > operator to define precedence levels. Operators listed after a > have lower precedence than those before it. In the example above, ^ has the highest precedence, followed by * and /, and finally + and - with the lowest precedence.
infix BinaryExpr on ...:
A > B > C
//A has higher precedence than B, B higher than C
;
If you have multiple operators with the same precedence, list them on the same line separated by |.
The default associativity for infix operators is left associative. To specify right associativity, use the assoc keyword preceded by right before the operator.
infix BinaryExpr on ...:
...> right assoc '^' >...
;