Parsing ANTLR不会自动进行前瞻性匹配吗?

Parsing ANTLR不会自动进行前瞻性匹配吗?,parsing,antlr,antlr3,Parsing,Antlr,Antlr3,我目前正在编写一个简单的语法,它要求在一个表达式中使用运算符优先级和混合关联性。一个示例表达式是a->b?>C?>D->e,它应该被解析为(a->(((b?>C)?>D)->e)。也就是说,?>操作符是高优先级的左关联操作符,而->操作符是低优先级的右关联操作符 我正在ANTLR 3.5.1(通过ANTLRWorks 1.5.2)中对语法进行原型设计,发现它无法处理以下语法: prog : expr EOF; expr : term '->' expr

我目前正在编写一个简单的语法,它要求在一个表达式中使用运算符优先级和混合关联性。一个示例表达式是
a->b?>C?>D->e
,它应该被解析为
(a->(((b?>C)?>D)->e)
。也就是说,
?>
操作符是高优先级的左关联操作符,而
->
操作符是低优先级的右关联操作符

我正在ANTLR 3.5.1(通过ANTLRWorks 1.5.2)中对语法进行原型设计,发现它无法处理以下语法:

prog    :   expr EOF;
expr    :   term '->' expr
        |   term;
term    :   ID rest;
rest    :   '?>' ID rest
        |   ;
它产生
规则expr具有非LL(*)决策,因为可以从alts 1,2访问递归规则调用
错误

当我测试时,
术语
rest
产品可以独立工作,因此我假设发生这种情况是因为解析器被
expr
弄糊涂了。为了避免这个问题,我进行了以下重构:

prog    :   expr EOF;
expr    :   term exprRest;
exprRest 
        :   '->' expr
        |   ;
term    :   ID rest;
rest    :   DU ID rest
        |   ;

这很好。但是,由于这次重构,我现在需要检查输出解析树中是否有空的
exprRest
节点,这是不理想的。有没有办法让ANTLR绕过
expr
初始声明中的模糊性?我假设生成的解析器将完全匹配
术语和en对
“->”
进行前瞻性搜索,然后继续解析或返回唯一的
术语。我缺少什么?

如前所述,此规则中存在问题:

expr    :   term '->' expr
        |   term;
有问题的部分是
术语
,这两个选项都通用

  • LL(1)语法根本不允许这样做(除非
    term
    只匹配零标记-但这样的规则将是毫无意义的),因为它无法决定使用哪种替代方法,而只能看到前面的一个标记(即LL(1)中的1)
  • LL(k)只有当
    术语
    规则最多可以匹配
    k-1
    标记时,语法才允许这样做
  • LL(*)ANTLR 3.5使用的语法有一些技巧,允许它处理匹配任意数量标记的规则(ANTLR作者称此为“变量前瞻”)

    • 但是,这些技巧无法处理的一件事是,如果规则是递归的,即如果它或它调用的任何规则以任何方式(直接或间接)引用自身,那么这正是
      术语
      规则所做的:

      term    :   ID rest;
      rest    :   '?>' ID rest
              |   ;
      
      -规则
      rest
      ,从
      term
      引用,递归地引用自身。因此,错误消息

      由于递归规则调用,规则expr具有非LL(*)决策


解决LL语法限制的方法称为左因子分解:

expr    :   term 
            ( '->' expr )?
        ;
我在这里所做的是说“首先匹配术语”(因为你想在两个选项中匹配它,所以没有必要决定在哪一个选项中匹配它),然后决定是否匹配
'->'expr
(这可以通过查看下一个标记来决定-如果它是
->
,使用它-所以这甚至是LL(1)决定)


这与您得到的结果非常相似,但解析树应该与原始语法非常相似。

这是一个很好的解释,帮助我克服了使用ANTLR时遇到的一些概念障碍,非常感谢。这将有助于我的最新项目!此外,了解左视图也很有帮助因为我发现必须遍历
expRest
节点来检查它是否为空,这很无聊。再次感谢