Bison 野牛不';当检测到解析错误时,不要调用yyerror

Bison 野牛不';当检测到解析错误时,不要调用yyerror,bison,Bison,我正在用bison编写解析器。我遇到了一个问题,bison检测到了解析错误,但没有调用yyerror 下面是我处理类定义的脚本片段: %{ ... void yyerror(char *s); Program ast_root; /* the result of the parse */ Classes parse_results; }% ... %% /* Save the

我正在用bison编写解析器。我遇到了一个问题,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 (: )
我看到,在
读取一个令牌后:下一个令牌是令牌OBJECTID(:)
,bison检测到解析错误,因此它调用
yyerror
,并打印
“bad.cl”,第19行: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
显然,当它遇到读取令牌的
时:下一个令牌是令牌OBJECTID(:)
,bison检测到错误,但没有打印错误消息,因此没有调用
yyerror

我只是觉得很困惑,为什么会发生这种情况,因为上述三个错误几乎是一样的。如有任何帮助,将不胜感激。

,其中解释了错误恢复,包括以下文本:

错误恢复策略必然是猜测。当他们猜错的时候,一个语法错误往往会导致另一个

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

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

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