1

I have some mutually left-recursive ANTLR code:

expr: int_liter
| bool_liter
| char_liter
| str_liter
| pair_liter
| ident
| array_elem
| unary_oper expr
| expr binary_oper expr
| OPEN_PARENTHESES expr CLOSE_PARENTHESES
;

array_elem:  expr  OPEN_BRACKET expr CLOSE_BRACKET ;

Any ideas on how to fix this?

Matt Fenwick
  • 48,199
  • 22
  • 128
  • 192

1 Answers1

1

ANTLR 4 can handle direct left-recursion only, but your grammar contains indirect left recursion from the rules exprarray_elemexpr. The easiest way to resolve this problem in your particular grammar is to inline the array_elem rule into the expr rule, and use labeled outer alternatives to assign meaningful names to each of the alternatives in expr.

expr
  : int_liter                                # someLabel
  | bool_liter                               # someLabel               
  | char_liter                               # someLabel
  | str_liter                                # someLabel
  | pair_liter                               # someLabel
  | ident                                    # someLabel
  | expr OPEN_BRACKET expr CLOSE_BRACKET     # array_elem
  | unary_oper expr                          # someLabel
  | expr binary_oper expr                    # someLabel
  | OPEN_PARENTHESES expr CLOSE_PARENTHESES  # someLabel
  ;

Note the following constraints around using labeled outer alternatives:

  1. No two outer alternatives can share a label, and labels cannot match any rule name; labels must be unique throughout the grammar.
  2. If one outer alternative of a rule is labeled (e.g. the array_elem alternative), then all outer alternatives for that rule must be labeled.
Sam Harwell
  • 97,721
  • 20
  • 209
  • 280
  • 1
    I am shocked to learn that a modern tool like ANTLR cannot do what yacc can since the 70's. – Ingo Nov 01 '13 at 16:23
  • @Ingo: ANTLR is an LL parser generator; YACC is an LALR parser generator. You're comparing apples to rice. – Sam Harwell Nov 01 '13 at 18:21
  • This is news to me. I always thought that the *LR* in *ANTLR* promises LALR. Anyway, I am happy I never took the effort to learn ANTLR and sticked with yacc (or, pbyacc -j, if you need something java-ish) – Ingo Nov 01 '13 at 18:35
  • @280Z28 hey thanks for the answer! Another question, I tried to do the labelling and now the array_elem rule is said undefined when called from other rules like this `assign_lhs: ident | array_elem | pair_elem ; ` – user2640331 Nov 02 '13 at 10:30