bison定义CLOSE文件操作文法出现shift/reduce冲突问题求助
冲突根因
你遇到的是典型的无边界左递归序列导致的移进/归约冲突,本质原因是你的文法没有定义close语句的结束边界,Bison无法判断后续的NAME标记属于当前close的文件名列表,还是属于后续其他语法结构。
你给出的State 124状态里的两个项目已经明确了冲突场景:
- 项目
close: CLOSE filenames .表示当前已经匹配完CLOSE和文件名序列,可直接归约为close节点 - 项目
filenames: filenames . NAME表示当前已有的文件名序列后如果出现NAME,可以移进NAME扩展文件名列表
当超前扫描的下一个标记是NAME时,Bison有两个合法操作:
- 移进
NAME,扩展文件名列表 - 归约
CLOSE filenames为close节点,将当前NAME留给后续语法规则解析
在没有额外规则约束的情况下,Bison无法判断哪个操作是正确的,就会抛出冲突警告。
你存在的认知疏漏
你默认filenames规则会自动吃掉所有后续出现的NAME标记,但文法本身没有任何规则限制filenames的终止条件:Bison不知道什么时候该停止匹配文件名、什么时候该结束close语句。如果没有明确的结束标记,文法本身是二义的。
解决方案
最稳妥的解决方式是给close语句增加明确的结束边界,常见方案有两种:
- 用标点作为语句结束符(比如分号),修改文法如下:
close: CLOSE filenames ';' ; filenames: NAME | filenames NAME ;
- 用换行作为语句边界,先把换行定义为词法标记
NEWLINE,再修改文法:
close: CLOSE filenames NEWLINE ; filenames: NAME | filenames NAME ;
修改后Bison只有扫描到结束标记时才会归约close节点,遇到NAME只会执行移进操作扩展文件名列表,冲突自然消除。
内容的提问来源于stack exchange,提问作者James K. Lowden
相关产品推荐
相关产品推荐

