我正在用野牛写一个解析器。我遇到一个问题,即野牛检测到解析错误,但没有调用yyerror
。
这是我的脚本片段,用于处理类定义:
%{ ...
void yyerror(char *s);
Program ast_root; /* the result of the parse */
Classes parse_results;
}%
...
%%
/*
Save the root of the abstract syntax tree in a global variable.
*/
program : class_list { @$ = @1; ast_root = program($1); }
;
class_list
: class /* single class */
{ $$ = single_Classes($1);
parse_results = $$; }
| class_list class /* several classes */
{ $$ = append_Classes($1,single_Classes($2));
parse_results = $$; }
| class_list error
{
$$ = $1;
}
;
/* If no parent is specified, the class inherits from the Object class. */
class : CLASS TYPEID '{' dummy_feature_list '}' ';'
{ @$ = @2;
SET_NODELOC(@2);
$$ = class_($2,idtable.add_string("Object"),$4,
stringtable.add_string(curr_filename)); }
| CLASS TYPEID INHERITS TYPEID '{' dummy_feature_list '}' ';'
{
@$ = @2;
SET_NODELOC(@2);
$$ = class_($2,$4,$6,stringtable.add_string(curr_filename));
}
;
测试文件如下:
(* no error *)
class A {
};
(* error 1: b is not a type identifier *)
Class b inherits A {
};
(* error 2: a is not a type identifier *)
Class C inherits a {
};
(* error 3: keyword inherits is misspelled *)
Class D inherts A {
};
(* error 4: closing brace is missing *)
Class E inherits A {
;
运行结果如下:
“ bad.cl”,第15行:OBJECTID = b或附近的语法错误
“ bad.cl”,第19行:OBJECTID = a或附近的语法错误
“ bad.cl”,第28行:';'
或附近的语法错误由于lex和parse错误导致编译暂停
没有显示拼写为继承的第三个错误。
我检查调试信息。错误2就像:
Stack now 0
Entering state 3
Reading a token: Next token is token CLASS (: )
Shifting token CLASS (: )
Entering state 1
Reading a token: Next token is token TYPEID (: )
Shifting token TYPEID (: )
Entering state 5
Reading a token: Next token is token INHERITS (: )
Shifting token INHERITS (: )
Entering state 9
Reading a token: Next token is token OBJECTID (: )
"bad.cl", line 19: syntax error at or near OBJECTID = a
Error: popping token INHERITS (: )
Stack now 0 3 1 5
Error: popping token TYPEID (: )
Stack now 0 3 1
Error: popping token CLASS (: )
Stack now 0 3
Shifting token error (: )
Entering state 7
Reducing stack by rule 4 (line 165):
$1 = nterm class_list (: )
$2 = token error (: )
-> $$ = nterm class_list (: )
Stack now 0
Entering state 3
Next token is token OBJECTID (: )
Error: discarding token OBJECTID (: )
Shifting token error (: )
我看到Reading a token: Next token is token OBJECTID (: )
之后,野牛检测到解析错误,因此它调用yyerror
并打印"bad.cl", line 19: syntax error at or near OBJECTID = a
但错误3的信息如下:
Stack now 0
Entering state 3
Reading a token: Next token is token CLASS (: )
Shifting token CLASS (: )
Entering state 1
Reading a token: Next token is token TYPEID (: )
Shifting token TYPEID (: )
Entering state 5
Reading a token: Next token is token OBJECTID (: )
Error: popping token TYPEID (: )
Stack now 0 3 1
Error: popping token CLASS (: )
Stack now 0 3
Shifting token error (: )
Entering state 7
很明显,当遇到Reading a token: Next token is token OBJECTID (: )
时,野牛会检测到错误,但是没有打印错误消息,因此yyerror
没有被调用。
我很困惑为什么会发生这种情况,因为上述三个错误几乎相同。任何帮助将不胜感激。
答案 0 :(得分:1)
Chspter six of the bison manual(说明错误恢复)包括以下文本:
错误恢复策略必定是猜测。当他们猜错时,一种语法错误通常会导致另一种语法错误。……
为防止错误消息大量涌入,解析器将不输出任何错误消息,该错误消息发生在第一个语法错误之后不久;只有成功地连续移位了三个连续的输入令牌后,错误消息才会恢复。
从跟踪中可以看到,在遇到拼写错误的令牌之前,只有两个令牌已成功移位。
对于测试错误恢复,通常最好对每个要测试的错误使用单独的文件。或者至少用大量有效的程序文本来分隔错误。