检测到解析错误时,野牛不会调用yyerror

时间:2018-09-21 09:14:45

标签: bison

我正在用野牛写一个解析器。我遇到一个问题,即野牛检测到解析错误,但没有调用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没有被调用。

我很困惑为什么会发生这种情况,因为上述三个错误几乎相同。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

Chspter six of the bison manual(说明错误恢复)包括以下文本:

  

错误恢复策略必定是猜测。当他们猜错时,一种语法错误通常会导致另一种语法错误。……

     

为防止错误消息大量涌入,解析器将不输出任何错误消息,该错误消息发生在第一个语法错误之后不久;只有成功地连续移位了三个连续的输入令牌后,错误消息才会恢复。

从跟踪中可以看到,在遇到拼写错误的令牌之前,只有两个令牌已成功移位。

对于测试错误恢复,通常最好对每个要测试的错误使用单独的文件。或者至少用大量有效的程序文本来分隔错误。