2

我对 Bison 的错误处理有疑问。我有以下语法(我只删掉了相关部分)。如果字符串“ConfigParam”被解析,Flex 将其令牌发送到 Bison 并返回终端符号“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 ("free at line %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

为什么这行得通?

4

2 回答 2

1

在不查看更多文件的情况下很难说出确切的问题,但事实并非如此

第一行已成功解析,应该从堆栈中弹出

错误点的堆栈如下所示:

statementlist KW_CONFIGPARAM

正如野牛所报告的那样,其中statementlist是通过减少第一行而产生的。

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

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

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

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

于 2013-01-26T17:47:43.533 回答
1

@rici:非常感谢,您为我指明了正确的方向。我已经写了

%token <str>    STRING    IDENT       NUMBER
                KW_CONFIGPARAM

但正确的当然是......

%token <str>    STRING    IDENT       NUMBER
%token          KW_CONFIGPARAM

啊!

@rici:你成就了我的一天!!!

于 2013-01-27T00:46:13.780 回答