我对 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/