如何消除 bison 中变量声明的 shift/reduce 冲突?
How to remove shift/reduce conflicts on variable declarations in bison?
我正在处理我的编译器设计项目,我必须从这个语法中删除所有歧义。起初,以下代码(.yac)有 27 个 shift/reduce 冲突和 3 个 reduce/reduce 冲突。我设法使它们只有 15 个 shift/reduce 冲突,现在我可以看到只有 BOOLEAN_KW、[ 等变量声明存在冲突=39=],等等。我真的需要解决这个问题,我知道一些 Precedence 或 Priority 需要在这里使用,我测试了很多可能性,但没有成功。如果有人可以帮助我处理显示 shift/reduce 上的冲突的 bison 输出文件,我将不胜感激。
顺便说一句,我想这些 reduce/conflicts 是 bison 出于确认目的而给我的一些警告,但不幸的是,即使知道这些也不会让我 运行 整个 lexer 和 parser 与我的主程序,我在尝试 运行 整个代码时遇到此错误:
Error : syntax error
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at YYParser$YYStack.stateAt(YYParser.java:315)
at YYParser.parse(YYParser.java:1568)
at global.main(global.java:39)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
最后,这是我使用 bison 启用 -o output 选项的输出,其中显示了冲突代码的早期部分:
My code is uploaded here.
关键警告是:
Rules useless in parser due to conflicts
5 declarations: /* empty */
指的是这些作品:
declarations_list: declarations_list declarations
| /* empty */
declarations: type_specifiers declarator_list SEMICOLON_KW
| /* empty */
这表示 declarations_list
由零个或多个 declarations
组成。但是,declaration
可能为空。所以这显然是模棱两可的:在给定的 declarations_list
中出现了多少个空 declarations
非终结符实例?它可以是任何数字,因为它们都是空的。
所有 shift/reduce 冲突都源于这种本质上的歧义。当解析器需要一个declarations_list
时,它需要决定在列表的开头解析多少个空的declarations
。
默认情况下,它选择不插入任何declarations
,这使得产生式:
declarations: /* empty */
没用(正如警告所说)。由于产生式实际上是无用的,您不妨将其删除,从而避免歧义(以及 shift/reduce 冲突)。
正如 Austin Hastings 在评论中指出的那样,这对解析器的行为没有影响。解析器已经消除了无用的产生式,并且不会改变对任何输入的响应。因此,如果某些输入在您尝试解析它时产生了意外的语法错误,这反映了您的语法存在一些不同的问题。
我正在处理我的编译器设计项目,我必须从这个语法中删除所有歧义。起初,以下代码(.yac)有 27 个 shift/reduce 冲突和 3 个 reduce/reduce 冲突。我设法使它们只有 15 个 shift/reduce 冲突,现在我可以看到只有 BOOLEAN_KW、[ 等变量声明存在冲突=39=],等等。我真的需要解决这个问题,我知道一些 Precedence 或 Priority 需要在这里使用,我测试了很多可能性,但没有成功。如果有人可以帮助我处理显示 shift/reduce 上的冲突的 bison 输出文件,我将不胜感激。 顺便说一句,我想这些 reduce/conflicts 是 bison 出于确认目的而给我的一些警告,但不幸的是,即使知道这些也不会让我 运行 整个 lexer 和 parser 与我的主程序,我在尝试 运行 整个代码时遇到此错误:
Error : syntax error
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at YYParser$YYStack.stateAt(YYParser.java:315)
at YYParser.parse(YYParser.java:1568)
at global.main(global.java:39)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
最后,这是我使用 bison 启用 -o output 选项的输出,其中显示了冲突代码的早期部分: My code is uploaded here.
关键警告是:
Rules useless in parser due to conflicts
5 declarations: /* empty */
指的是这些作品:
declarations_list: declarations_list declarations
| /* empty */
declarations: type_specifiers declarator_list SEMICOLON_KW
| /* empty */
这表示 declarations_list
由零个或多个 declarations
组成。但是,declaration
可能为空。所以这显然是模棱两可的:在给定的 declarations_list
中出现了多少个空 declarations
非终结符实例?它可以是任何数字,因为它们都是空的。
所有 shift/reduce 冲突都源于这种本质上的歧义。当解析器需要一个declarations_list
时,它需要决定在列表的开头解析多少个空的declarations
。
默认情况下,它选择不插入任何declarations
,这使得产生式:
declarations: /* empty */
没用(正如警告所说)。由于产生式实际上是无用的,您不妨将其删除,从而避免歧义(以及 shift/reduce 冲突)。
正如 Austin Hastings 在评论中指出的那样,这对解析器的行为没有影响。解析器已经消除了无用的产生式,并且不会改变对任何输入的响应。因此,如果某些输入在您尝试解析它时产生了意外的语法错误,这反映了您的语法存在一些不同的问题。