【问题标题】:Bison yyerror ignore next token on grammarBison yyerror 忽略语法上的下一个标记
【发布时间】:2021-07-08 14:48:15
【问题描述】:

所以我的 Bison 程序有一个小问题,首先请注意我的程序可以正常工作并且功能齐全,您在这里看到的只是一个摘录,足以帮助我。

解析器基本上读取“vector(x,2)”程序正在检查变量“x em>" 已经存在并且如果元素的数量"2" 大于 1。当这种情况不发生时,我会抛出 yyerror。问题是错误没有忽略令牌的其余部分。让我举一个vector(x,1)的例子,你会看到它应该在reduce时忽略语句而不是。

Starting parse
Entering state 0
Stack now 0
Reducing stack by rule 1 (line 58):
-> $$ = nterm PROGRAM (1.1: )
Entering state 1
...
....
Entering state 24
Stack now 0 1 5 12 15 18 24
Next token is token PARENTSIS_RIGHT (1.1: )
Shifting token PARENTSIS_RIGHT (1.1: )
Entering state 33
Stack now 0 1 5 12 15 18 24 33
Reducing stack by rule 10 (line 87):
   $1 = token RESEV_VAR (1.1: )
   $2 = token PARENTSIS_LEFT (1.1: )
   $3 = token STRING (1.1: )
   $4 = token COMMA (1.1: )
   $5 = nterm ELEMENTS (1.1: )
   $6 = token PARENTSIS_RIGHT (1.1: )
        Erro: blalalala.
-> $$ = nterm DEFINE_VECTOR (1.1: ) //here it should not run this one should skip it
Entering state 9
Stack now 0 1 9
Reducing stack by rule 6 (line 65):
   $1 = nterm DEFINE_VECTOR (1.1: )
        VECTOR
-> $$ = nterm DECLARACAO (1.1: )

正如你在最后看到的那样,当我指定错误时,他正在运行归约到 DEFINE_VECTOR。

%start PROGRAM

%%

PROGRAM:
       | PROGRAM STATMENT
       | PROGRAM error STATMENT
;

STATMENT: QUIT  { fclose(yyin); printf("\nBYE\n"); exit('0');}
    | DEFINE_VAR    { printf("\tVAR\n"); }
    | DEFINE_VECTOR { printf("\tVAR\n"); }
;

...
DEFINE_VECTOR: RESEV_VAR PARENTSIS_LEFT STRING COMMA ELEMENT PARENTSIS_RIGHT { 
            if($5<=1){
                 yyerror("Vector to small");
            }else{
                 if(check($3)==0){
                    createVar($3, 2, $5);
                 }else{
                    yyerror("Variable alrady exists");
                 }
            }
}
;

ELEMENTS: ELMENTINT
    | ELMENTFLOAT{ $$ = $1;}
;

解决方案:

%start PROGRAM

%%

PROGRAM:
       | PROGRAM STATMENT
       | PROGRAM error STATMENT
       | PROGRAM error PARENTSIS_RIGHT STATMENT // added here
;

STATMENT: QUIT  { fclose(yyin); printf("\nBYE\n"); exit('0');}
    | DEFINE_VAR    { printf("\tVAR\n"); }
    | DEFINE_VECTOR { printf("\tVAR\n"); }
;

...
DEFINE_VECTOR: RESEV_VAR PARENTSIS_LEFT STRING COMMA ELEMENT PARENTSIS_RIGHT { 
            if($5<=1){
                 yyerror("Vector to small");
                 YYERROR;  //added here
            }else{
                 if(check($3)==0){
                    createVar($3, 2, $5);
                 }else{
                    yyerror("Variable alrady exists");
                    YYERROR;  added here
                 }
            }
}
;

ELEMENTS: ELMENTINT
    | ELMENTFLOAT{ $$ = $1;}
;

【问题讨论】:

    标签: c compilation compiler-construction bison flex-lexer


    【解决方案1】:

    yyerror 只是一个打印错误消息的函数。野牛解析器在出现语法错误时调用它,但您也可以在其他地方调用它来打印错误。它对解析没有影响(它不会中断或改变它——它不会“抛出”)

    如果你想影响解析,你需要使用YYERROR(一个触发解析器错误的宏,然后解析器会尝试从中恢复)。但是,如果您有这样的语义错误(不是语法错误),您可能不想这样做,因为没有可恢复的语法。您可能想使用 YYABORT 立即中止解析(从 yyparse 返回)。或者您可能只想继续解析,以识别其他错误。

    【讨论】:

    • 谢谢,有点难理解,文档不是很好阅读,但在使用 YYERROR 反复试验后,我做到了。
    • 如果您没有任何错误规则可以从错误中恢复,那么使用 YYERROR 是没有意义的——您还不如使用 YYABORT。
    猜你喜欢
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    • 2021-01-26
    • 2016-05-30
    • 1970-01-01
    相关资源
    最近更新 更多