LR(1) 解析器如何处理空规则?
How does a LR(1) parser handles empty rules?
我使用过一些解析器(Yacc、Bison 和 Menhir)。如果我没记错的话,它们都允许一个规则为空。这是我使用 Menhir 的一个例子,它是我用得最多的一个。
some_list:
| {[]}
| some_non_empty_list { }
some_non_empty_list:
| SEMICOLON some_list { }
| element { [] }
| element some_non_empty_list { :: }
重要的是some_list可以减少虚无。
我目前对构建解析算法的理解 table(构建 NFA,从 NFA 构建 DFA,最小化)使我认为这会导致整个 shift/reduce 冲突地方。但它显然没有,因为我的代码当时有效。
那么如何构建一个可以接受那些空规则的解析table?
为什么您认为空规则比具有一个右侧标记的规则更难处理?
过于简单化,语法规则 L = R1 R2 R3 ;表示 "reduce to L if you see R1 R2 R3"。不简化,如果我们有 X= A L B ;那么我们的 L 规则意味着“如果你的左上下文是 A,你已经看到 R1 R2 R3,并且下一个标记是 first(B),则减少到 L。
如果L = R1 R2,这个思路是一样的; L = R1 ;.
甚至对于(空规则)的极限情况:L = ;
除非您已经看到它的左边上下文、它的内容以及后面的开头,否则您不能缩小到 L。所以你不能在 "any time".
减少到一个空规则
您需要做的是了解 LR 解析器的工作原理,方法是学习如何在构建解析状态时跟踪项目集。在纸上做一次,(痛苦的是,值得的是)一个小语法,LR 解析器将变得清晰。你可以在任何关于 LR 解析的书中找到这个过程,包括 Aho 等人的经典编译器。
我使用过一些解析器(Yacc、Bison 和 Menhir)。如果我没记错的话,它们都允许一个规则为空。这是我使用 Menhir 的一个例子,它是我用得最多的一个。
some_list:
| {[]}
| some_non_empty_list { }
some_non_empty_list:
| SEMICOLON some_list { }
| element { [] }
| element some_non_empty_list { :: }
重要的是some_list可以减少虚无。
我目前对构建解析算法的理解 table(构建 NFA,从 NFA 构建 DFA,最小化)使我认为这会导致整个 shift/reduce 冲突地方。但它显然没有,因为我的代码当时有效。
那么如何构建一个可以接受那些空规则的解析table?
为什么您认为空规则比具有一个右侧标记的规则更难处理?
过于简单化,语法规则 L = R1 R2 R3 ;表示 "reduce to L if you see R1 R2 R3"。不简化,如果我们有 X= A L B ;那么我们的 L 规则意味着“如果你的左上下文是 A,你已经看到 R1 R2 R3,并且下一个标记是 first(B),则减少到 L。
如果L = R1 R2,这个思路是一样的; L = R1 ;.
甚至对于(空规则)的极限情况:L = ;
除非您已经看到它的左边上下文、它的内容以及后面的开头,否则您不能缩小到 L。所以你不能在 "any time".
减少到一个空规则您需要做的是了解 LR 解析器的工作原理,方法是学习如何在构建解析状态时跟踪项目集。在纸上做一次,(痛苦的是,值得的是)一个小语法,LR 解析器将变得清晰。你可以在任何关于 LR 解析的书中找到这个过程,包括 Aho 等人的经典编译器。