1

VarsDecl.g4 describes the syntax of variable declarations, such as int a, b, c.

grammar VarsDecl;

decl : type vars ;
type : 'int'        # IntType
     | 'float'      # FloatType
     ;
vars : left = vars ',' ID  # VarsList
     | ID                  # VarsID
     ;

ID : [a-z]+ ;
WS : [ \t\r\n]+ -> skip ;

VarsDeclAG.g4 is the version of VarsDeclAG.g4 with parameters of rules and and embedded actions.

grammar VarsDeclAG;

decl : type vars[$type.text] ;
type : 'int'      
     | 'float'    
     ;
vars[String typeStr]
     : left = vars[$typeStr] ',' ID { System.out.println($ID.text + " : " + $typeStr); }
     | ID { System.out.println($ID.text + " : " + $typeStr); }
     ;

ID : [a-z]+ ;
WS : [ \t\r\n]+ -> skip ;

However, the ANTLR 4 IntelliJ plugin (version 4.1.11) reports that in VarsDeclAG.g4: rule vars is left recursive but doesn't conform to a pattern ANTLR can handle (no errors in VarsDecl.g4).

Why is it? And how to fix it?

By the way, I do not want to re-write vars as vars : ID (',' ID)*.

hengxin
  • 1,867
  • 2
  • 21
  • 42
  • 1
    Apparently for the version with parameter the method `translateLeftRecursiveRule(...)` returns `false`. Maybe step through it using a debugger as to why this happens. Could be a bug, seeing that the one without parameters is fine. https://github.com/antlr/antlr4/blob/8dcc6526cfb154d688497f31cf1e0904801c6df2/tool/src/org/antlr/v4/analysis/LeftRecursiveRuleTransformer.java#L94 – Bart Kiers Apr 20 '23 at 11:57
  • 1
    Internally Antlr rewrites direct left recursion. But, it can only do so if it fits a pattern that it can handle. The error, raised [here](https://github.com/antlr/antlr4/blob/8dcc6526cfb154d688497f31cf1e0904801c6df2/tool/src/org/antlr/v4/analysis/LeftRecursiveRuleTransformer.java#L76), happens because you have an attribute passed to the `vars` symbol. You're best option it so rewrite the rule using the Kleene `*`-operator, which also has the benefit of a smaller tree. Otherwise, there is no alternative but to not use Antlr. – kaby76 Apr 20 '23 at 12:13
  • 1
    If I follow the code, the `false` returned by `translateLeftRecursiveRule(...)` is because `leftRecursiveRuleWalker.rec_rule()` returns `false`, or a `RecognitionException` is thrown. Both of which sound odd: which is why I thought there might be a bug in the tool. It isn't immediately clear in `translateLeftRecursiveRule(...)` that the rule parameter is the culprit. – Bart Kiers Apr 20 '23 at 12:49
  • @BartKiers Do you know any example grammars containing left recursive rules with rule parameters? I do not find any one in the documentations of ANTLR 4 or books of Terence Parr. – hengxin Apr 20 '23 at 13:04
  • 1
    Alas, I don't. And I recommend to keep grammars clean from target code (and parameters, which are also target code). It is usually a better idea to move such things into visitors or listeners of the target language. – Bart Kiers Apr 20 '23 at 13:56
  • 1
    There aren't any examples in grammars-v4: all grammars that use actions are in "target agnostic format." grammars-v4 doesn't use attributes because that eliminates target portability immediately (the declaration is in target syntax). It's possible to invoke a parser listener during the parse, though. Each exit method can perform attribute evaluation to decorate the tree. See [addParseListener](https://www.antlr.org/api/Java/org/antlr/v4/runtime/Parser.html#addParseListener(org.antlr.v4.runtime.tree.ParseTreeListener)). Generally, all this is moved to a listener or visitor after parsing. – kaby76 Apr 20 '23 at 16:04
  • @kaby76 Thanks. Great to know about `addParseListener`. – hengxin Apr 21 '23 at 02:33

0 Answers0