Parsing LR解析算法中的负前瞻

Parsing LR解析算法中的负前瞻,parsing,generator,conflict,resolve,negative-lookahead,Parsing,Generator,Conflict,Resolve,Negative Lookahead,在LR族解析生成器(例如YACC、BISON等)的语法中考虑这样一个规则: 这是一个普通的规则,只是有一个限制:使用此规则生成的短语不能以Terminal1,…,TerminalN开头。(当然,这条规则可以用一组常用规则来代替,但它会导致更大的语法)。这有助于解决冲突 问题是,LR表构造算法是否有接受此类限制的修改?在我看来,这样的修改是可能的(如优先关系) 当然,它可以在运行时检查,但我指的是编译时检查(在构建解析表时执行的检查,如yacc可比较生成器中的%prec、%left、%right和

在LR族解析生成器(例如YACC、BISON等)的语法中考虑这样一个规则:

这是一个普通的规则,只是有一个限制:使用此规则生成的短语不能以
Terminal1,…,TerminalN
开头。(当然,这条规则可以用一组常用规则来代替,但它会导致更大的语法)。这有助于解决冲突

问题是,LR表构造算法是否有接受此类限制的修改?在我看来,这样的修改是可能的(如优先关系)


当然,它可以在运行时检查,但我指的是编译时检查(在构建解析表时执行的检查,如yacc可比较生成器中的
%prec
%left
%right
%nonassoc
指令)。

我不明白为什么这不可能,但我也看不出有什么明显的理由说明它会有用。你想举个例子吗

最简单的方法是进行括号中提到的语法转换。这将生成更大的语法,但不会人为地增加LR状态的数量

基本的转变,只需轻轻挥手:

对于具有终端限制的任何生产:

  • 如果生产以不可为空的非终端开始,请将该非终端替换为终端受限版本

  • 如果生产从终端限制列表中的终端开始,则删除生产

  • 如果生产开始时终端不在终端限制列表中,则无需更改

如果一个产品以一个可为空的非终端开始,您必须创建两个可为空的非终端版本,其中一个始终为空,另一个不可为空;然后创建两个版本的产品,一个从每个新的非终端开始。然后应用上述转换,但将“开始于”解释为“在任何始终为空的非终结符之后开始于”


实际上,您不需要修改语法,因为上述转换可以在构建底层SLR机器的过程中动态完成,至少对于LR(0)和LALR(1)构造。

谢谢您的回答!是的,我有一个例子,它是ECMA-262语法(例如第12.4节)。由于该语法使用有限制和无限制的
表达式
生成,因此我们必须将描述
表达式的语法部分加倍。在我的LALR(1)解析器生成器中,它会导致更多的状态(350对470)。保留350个州并满足限制是非常好的。
Nonterminal : [ lookahead not in {Terminal1, ..., TerminalN} ] Rule ;