【问题标题】:bison doesn't call yyerror when detecting a parsing error检测到解析错误时,bison 不调用 yyerror
【发布时间】:2018-09-21 09:14:44
【问题描述】:

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

不显示inherits拼写错误的第三个错误。

我检查调试信息。 Error2 是这样的:

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 (: ) 之后,bison 检测到解析错误,因此它调用 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 (: ) 时,bison 检测到错误但没有打印错误消息,因此 yyerror 没有被调用。

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

【问题讨论】:

    标签: bison


    【解决方案1】:

    Chspter six of the bison manual,解释错误恢复,包括以下文字:

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

    为了防止错误消息的大量涌现,解析器将不会为在第一个语法错误之后不久发生的另一个语法错误输出错误消息;只有在三个连续的输入标记成功转移后,错误消息才会恢复。

    从跟踪中可以看出,在遇到拼写错误的标记之前,只有两个标记已成功移动。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多