Bison 错误处理

标签 bison yacc parser-generator

我对 Bison 的错误处理有疑问。我有以下语法(我只删除了相关部分)。 Flex 将其 token 发送给 Bison,如果解析了字符串“ConfigParam”,则返回终端符号“KW_CONFIGPARAM”。 IDENT 是一个指向 C++ 字符串对象的指针。

statementlist   : statement ';'               { $$ = new string("statementlist"); }
                | statementlist statement ';' { $$ = new string("statementlist"); }
;
statement       : KW_CONFIGPARAM IDENT        { $$ = new string("statement"); /* use $2, IDENT is used in main program */ }
;

我为 IDENT 这样的字符串指定了以下析构函数。

%destructor { printf ("在第 %d 行空闲: %s\n",@$.first_line, $$->c_str());删除($$); }

现在我有以下输入。第一行有效,第二行无效(缺少标识符):

ConfigParam p;
ConfigParam;

输出:

In input 2:12 - 2:12 : syntax error
free at line 2: p
free at line 1: statementlist

由于第二行出现错误,Bison 提示,返回语法错误并调用解析堆栈上所有对象的析构函数。 现在我不明白为什么调用第一行中标识符“p”的析构函数?属于第一行,解析成功。问题是 p 在主程序中使用,不应该被 Bison 删除。

如果我选择任意字符串 (“foo”) p 作为(无效)语句,Bison 不会删除它。

ConfigParam p;
foo;

In input 2:1 - 2:3 : syntax error
free at line 1: statementlist
free at line 2: foo

为什么这有效?

最佳答案

在不查看更多文件的情况下很难判断确切的问题,但情况肯定并非如此

The first line was successfully parsed and should be popped off the stack

发生错误时的堆栈如下所示:

statementlist KW_CONFIGPARAM

哪里statementlist据 Bison 报道,是通过减少第一行而创建的。

您似乎没有为statement_list指定值;如果您的摘录是字面的,那么它将被编译,就像它已经被写入一样:

statementlist   : statement ';'                 {$0 = $1;}

我不知道 statement 对应的值是什么是,但当然可以想象它包含字符串 "p" 。这取决于你设置的$0期间{ /* do some stuff, create a new ConfigParam object */ } .

(一旦发现它有点接近正确答案,就从评论中移走。) 我的另一个想法是:也许您已经使所有终端和非终端都具有触发该析构函数的类型。也许你的词法分析器不会修改 yylval当它返回KW_CONFIGPARM时。在这种情况下, Bison 解析器无法知道 yylval无关紧要,因此它将使用剩下的 yylval (这是一个指向 "p" 的指针)。

关于 Bison 错误处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14537906/

相关文章:

c - Bison 中缀计算器的计算结果始终为 0

c++ - 如何在 Bison C++中制作全局参数

c - 运行时公式评估

javascript - 在哪里可以找到 ECMAscript/Actionscript/Javascript 的 yacc 语法

PHP 词法分析器和解析器生成器?

parsing - 解析器的性能 : PEG vs LALR(1) or LL(k)

parsing - Python3解析器生成器

c++ - 制作可重入解析器的错误

c++ - undefined reference yyparse C++

f# - lex/yacc 和 fslex/fsyacc 有什么区别?