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
节点来检查它是否为空,这很无聊。再次感谢