让野牛解析器泄露调试信息

Getting bison parser to divulge debug information

我在编写 bison 解析器时遇到了问题,并且出乎意料地 运行 遇到了让解析器打印调试信息的困难。我在网上找到了两个解决方案,但似乎都不起作用。

This主张将这段代码放在主程序中:

extern int yydebug;
yydebug = 1;

不幸的是,C++ 编译器检测到对 `yydebug' 的未定义引用。

This建议放

        #if YYDEBUG == 1
           extern yydebug;
           yydebug = 1;
        #endif

进入语法文件。它编译但不产生输出。

有效的是编辑解析器文件本身,替换

int yydebug;

来自

int yydebug = 1;

最大的缺点是每次更改语法文件都必须重做,这在调试过程中经常发生。有没有其他方法可以让解析器说出它的秘密阴谋?

我正在使用 bison v2.4.1 生成解析器,具有以下命令行选项:

bison -ldv -p osil -o $(srcdir)/OSParseosil.tab.cpp OSParseosil.y

尽管输出的是 C++ 文件,但我使用的是标准 C 框架。

使用 bison 和标准 C 框架,要启用调试支持,您需要执行以下操作之一:

  • 在创建语法时使用 -t (Posix) 或 --debug(Bison 扩展)命令行选项。 (bison -t ...)

  • 在编译生成的语法时使用 -DYYDEBUG=1 命令行选项(至少是 gcc 或 clang)(gcc -DYYDEBUG=1 parser.tab.c ...` ).

  • %debug 指令添加到您的 bison 来源

  • #define YYDEBUG 1 放在 bison 源文件的序言中(%{%} 之间的文件部分。

我会在 bison 命令行中使用 -t。这很简单,而且由于它是 Posix 标准,因此 可能 也适用于其他派生的解析器生成器。但是,将 %debug 添加到 bison 源中也很简单;虽然它不那么便携,但它可以在 bison 2.4 中使用。

完成后,只需将 yydebug 设置为非零值就足以产生调试输出。

如果您想在生成的解析器本身以外的某些翻译单元中设置 yydebug,则需要注意您在 bison 命令行中声明的解析器前缀。 (在解析器本身中,yydebug 是前缀名称的 #defined。)并且您需要将调试变量(具有正确的前缀)声明为 extern。所以在你的主要,你可能想使用:

extern int osildebug;
// ...

int main(int argc, char** argv) {
  osildebug = 1;
  // ...
}

如果您使用 bison,查找信息的最佳位置是 bison manual;上面的大部分答案都可以在该页面中找到。