ANTLR:由于可以从alts 1,2访问递归规则调用,规则标记具有非LL(*)决策

ANTLR:由于可以从alts 1,2访问递归规则调用,规则标记具有非LL(*)决策,antlr,Antlr,试图在ANTLRWorks 1.4中解释此问题,并出现以下错误: grammar AdifyMapReducePredicate; PREDICATE : PREDICATE_BRANCH | EXPRESSION ; PREDICATE_BRANCH : '(' PREDICATE (('&&' PREDICATE)+ | ('||' PREDICATE)+) ')' ; EXPRESSION : ('a

试图在ANTLRWorks 1.4中解释此问题,并出现以下错误:

grammar AdifyMapReducePredicate;

PREDICATE 
    :   PREDICATE_BRANCH
    |   EXPRESSION
    ;

PREDICATE_BRANCH
    :   '(' PREDICATE (('&&' PREDICATE)+ | ('||' PREDICATE)+) ')'
    ;

EXPRESSION 
    :   ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
    ;
[12:18:21]错误(211)::1:8:[致命]规则令牌具有非LL(*)决策,因为可以从alts 1,2访问递归规则调用。通过左因子分解或使用语法谓词或使用backtrack=true选项进行解析。
[12:18:21]口译。。。
当我插入谓词时,我试图解释一个谓词,我的测试用例是(a | | B)


我遗漏了什么?

您没有语法分析器规则(语法分析器规则以小写字母开头),尽管我不确定在解释AntlWorks中的一些测试用例时是否需要最后一部分

无论如何,请尝试以下方法:

[12:18:21] error(211): <notsaved>:1:8: [fatal] rule Tokens has non-LL(*) decision due to recursive rule invocations reachable from alts 1,2.  Resolve by left-factoring or using syntactic predicates or using backtrack=true option.
[12:18:21] Interpreting...
使用以下测试类:

grammar AdifyMapReducePredicate;

parse
  :  (p=predicate {System.out.println("parsed :: "+$p.text);})+ EOF
  ;

predicate 
  :  expression
  ;

expression
  :  booleanExpression
  ;

booleanExpression
  :  atom ((AND | OR) atom)*
  ;

atom
  :  ID
  |  '(' predicate ')'
  ;

AND
  :  '&&'
  ;

OR
  :  '||'
  ;

ID 
  :  ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
  ;

SPACE
  :  (' ' | '\t' | '\r' | '\n') {skip();}
  ;
生成lexer&parser(a)、编译所有
.java
文件(b)并运行测试类(c)后,生成以下输出:

import org.antlr.runtime.*;
import org.antlr.runtime.tree.*;
import org.antlr.stringtemplate.*;

public class Main {
    public static void main(String[] args) throws Exception {
        ANTLRStringStream in = new ANTLRStringStream("(A || B) (C && (D || F || G))");
        AdifyMapReducePredicateLexer lexer = new AdifyMapReducePredicateLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        AdifyMapReducePredicateParser parser = new AdifyMapReducePredicateParser(tokens);
        parser.parse();
    }
}
解析::(A | | B) 解析::(C&(D|F|G)) A. java-cp antlr-3.2.jar org.antlr.Tool AdifyMapReducePredicate.g B javac-cp antlr-3.2.jar*.java c(*nix/MacOS) java-cp.:antlr-3.2.jar Main c(Windows) java-cp。;antlr-3.2.jar主管道
HTH

根据ANTLR的约定,解析器规则名称以小写字母开头,而lexer规则以大写字母开头。因此,正如您所写的,语法有三条lexer规则,定义标记。这可能不是你想要的

错误消息的原因显然是这些标记之间的歧义:您的输入模式匹配谓词和谓词分支的定义

只需使用以小写字母开头的名称,而不是谓词和谓词分支。您可能还必须为目标符号添加一个额外的规则,该规则不直接涉及递归


顺便说一下,这种语法是递归的,但不是左递归的,当使用解析器规则时,它肯定是LL(1)。

Wow,非常完整。我会尝试一下,但是当我集成它时,您能解释一下“左递归”的实际含义以及如何识别左递归吗?@Hounshell,@Gunther是对的:它不是左递归的,因为您的令牌谓词分支匹配一个
在它匹配谓词之前。很抱歉造成混淆!lexer和解析器之间有什么区别?可以在这篇文章中找到一个很好的解释: parsed :: (A||B) parsed :: (C&&(D||F||G)) java -cp antlr-3.2.jar org.antlr.Tool AdifyMapReducePredicate.g javac -cp antlr-3.2.jar *.java java -cp .:antlr-3.2.jar Main java -cp .;antlr-3.2.jar Main