【发布时间】:2011-08-04 21:46:57
【问题描述】:
我正在使用 Bison,并且生成了一个非常复杂的语法。问题是我的第一个测试用例失败了——但 Bison 只会说“语法错误”。有没有办法让Bison输出匹配失败的规则和有问题的token?我用过
%define parse.trace true
但仍然只能得到syntax error 作为输出。
【问题讨论】:
标签: bison
我正在使用 Bison,并且生成了一个非常复杂的语法。问题是我的第一个测试用例失败了——但 Bison 只会说“语法错误”。有没有办法让Bison输出匹配失败的规则和有问题的token?我用过
%define parse.trace true
但仍然只能得到syntax error 作为输出。
【问题讨论】:
标签: bison
当出现问题时,没有一个基于 Yacc 的解析器比“语法错误”做得更好;这在很大程度上取决于您自己的改进。
有几件事你可以很容易地做到。
一种是检测您的词法分析器,以便在将找到的标记返回给正确的解析器时打印出它们。这会告诉您语法在哪个标记上失败,以及预先提供了哪些标记。
另一种是编译开启Yacc调试,然后开启。这需要-DYYDEBUG=1 并将变量yydebug 设置为非零值(通常为1)。第一步将额外的信息编译成语法;第二步启用输出。
来自 Bison 2.4.3 手册:
§8.2 跟踪解析器
如果 Bison 语法编译正确,但在运行时没有执行您想要的操作,则 yydebug 解析器跟踪功能可以帮助您找出原因。
有几种方法可以启用跟踪工具的编译:
宏
YYDEBUG在编译解析器时,将宏
YYDEBUG定义为非零值。 这符合 POSIX Yacc。您可以使用-DYYDEBUG=1作为编译器 选项,或者您可以将#define YYDEBUG 1放在语法的序言中 文件(参见第 3.1.1 节 [序言],第 47 页)。选项
-t、--debug在运行 Bison 时使用
-t选项(参见第 9 章 [调用 Bison], 第 117 页)。这也符合 POSIX。指令
%debug添加
%debug指令(参见第 3.7.12 节 [Bison 声明摘要], 第 72 页)。这是一个 Bison 扩展,当 Bison 将 不使用预处理器的语言的输出解析器。除非 POSIX 和 Yacc 的可移植性对你很重要,这是首选的解决方案。我们建议您始终启用调试选项,以便始终可以进行调试。
跟踪工具通过
YYFPRINTF (stderr, format, args)形式的宏调用输出消息,其中format和args是通常的printf格式和可变参数。 如果将YYDEBUG定义为非零值但未定义YYFPRINTF,则<stdio.h>被自动包含,YYFPRINTF被定义为fprintf。一旦你用跟踪工具编译了程序,请求跟踪的方法是 在变量
yydebug中存储一个非零值。您可以通过使 C 代码执行此操作 它(可能在 main 中),或者您可以使用 C 调试器更改该值。当
yydebug为非零时,解析器执行的每一步都会产生一行或两行跟踪 信息,写在stderr。跟踪消息会告诉您以下信息:
- 解析器每次调用
yylex,读取的令牌类型。- 每次移动令牌时,状态堆栈的深度和完整内容(请参阅 第 5.5 节 [解析器状态],第 95 页)。
- 每减少一条规则,是哪条规则,状态的完整内容 之后堆叠。
【讨论】:
使用%error-verbose 指令来帮助您。它会给你一个解析器期望的标记的提示。请注意,可能有多个潜在规则无法匹配。
【讨论】:
%define parse.error verbose,但上述方法仍然有效!
如果您将全局变量yydebug 设置为非零值,bison 将在运行时输出调试信息,其中包含有关解析堆栈的外观、处于什么状态、正在使用什么规则等信息。我通常会调试这些类型的错误。
【讨论】:
这里有点混乱。
"%define parse.trace" 与"%debug" 完全相同:它将生成的解析器用于运行时跟踪,显示解析器在工作(但您仍然必须设置yydebug 变量,请参阅Jonathan Leffler 转载的文档)。
为了使错误消息更准确(在这方面 Jonathan 是错误的),Bison 可以做得更好,这要感谢 Alek 报告的 "%define error-verbose"。
【讨论】: