parsing - 在Bison错误后如何跳过一行中的其余 token

标签 parsing error-handling bison flex-lexer

我正在为使用Flex和Bison确定语句是否有效的作业编写应用程序。在语句中检测到错误后,我想打印一条错误消息并移至下一行以查看下一条语句,但是我尝试的所有操作均不起作用。

Bison在线研究,拥有一个内置的错误 token ,可用于错误处理。通过使用错误'\ n'{yyerrok;},我应该能够实现我想要的功能,但是它不起作用。

我的Flex代码:

%{
  #include <cstdio>
  #include <iostream>
  using namespace std;

  #include "exp.tab.h"  // to get the token types from Bison

%}
%%

--.*                    ;
[a-zA-Z][a-zA-Z0-9]*    {yylval.print = strdup(yytext); return ID;}
;\s*                    {return EOL;}
[-+*/%]                 {yylval.print = strdup(yytext); return OP;}
=                       {return EQU;}
\(                      {return OPEN;}
\)                      {return CLOSE;}
[0-9]                   ;
\n                      ;
\r                      ;
.                       ;
%%

我的Bison代币和规则:
%union{

    char *print;

}

%token EQU
%token <print> ID
%token EOL
%token <print> OP
%token OPEN
%token CLOSE

%%

lines: line
    |   lines line
;

line: ass {cout << " VALID" << endl;}
    |   exp {cout << " VALID" << endl;}
    |   error '\n' {yyerrok;}
;

ass: id EQU {cout << " ="; } exp EOL {cout << ";";}
;

exp: term
    |   exp op term 
;

term: id 
    |   OPEN {cout << "(";} exp op term CLOSE {cout << ")";}
;

id: ID {cout << $1; }

op: OP {cout << $1; }


%%

我的yyerror()仅显示“错误”。

我的解析输入:
-- Good (valid) statements:

first = one1 + two2 - three3 / four4 ;
second = one1 * (two2 * three3) ;
one1 * i8766e98e + bignum
second = (one1 * two2) * three3 ;
third = ONE + twenty - three3 ;
third = old * thirty2 / b567 ;

-- Bad (invalid) statements:

first = = one1 + two2 - three3 / four4 ;
first = one1 + - two2 - three3 / four4 ;
first = one1 + two2 - three3 / four4
first = one1 + two2 ? three3 / four4 ;
second = 4 + ( one1 * two2 ) * ( three3 + four4 ;
third = one1 + 24 - three3 ;
one1 +- delta
sixty6 / min = fourth ;

我希望输出会显示错误,然后移至下一行
first =one1+two2-three3/four4; VALID
second =one1*(two2*three3); VALID
one1*i8766e98e+bignum VALID
second =(one1*two2)*three3; VALID
third =ONE+twenty-three3; VALID
third =old*thirty2/b567; VALID
first = Error
first = one1 + Error
first = one1 + two2 - three3 / four4 Error
first = one1 + two2 Error
.
.
.

但是当我运行它时,它只会在第一个错误打印时停止
first =one1+two2-three3/four4; VALID
second =one1*(two2*three3); VALID
one1*i8766e98e+bignum VALID
second =(one1*two2)*three3; VALID
third =ONE+twenty-three3; VALID
third =old*thirty2/b567; VALID
first = Error

任何帮助将不胜感激,但主要是我想知道为什么错误'\ n'规则不起作用以及如何解决。

最佳答案

使用'\n'不起作用,因为您的词法分析器从不返回'\n',因此 token 流中将永远没有任何'\n' token 。基本上,如果词法分析器忽略某些字符,则不能以任何方式在解析器中使用它们,包括用于错误恢复。

因此,您的两个选择是停止忽略换行符(这可能是个坏主意,因为您必须在语法中允许换行的地方提到它们),或使用其他 token 进行错误恢复。跳过所有内容直到下一个分号可能是一个不错的选择(尽管由于并非所有行都以分号结尾,所以仍然无法产生预期的输出)。

关于parsing - 在Bison错误后如何跳过一行中的其余 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55989252/

相关文章:

tsql - SQL怎么做;尝试将错误信息捕获到错误日志表中,以获取在事务中执行的存储过程?

c - 我们如何定义用于识别给定系列中特定序列的规则?

c - 避免警告 : unreferenced find_rule label

c - 如何在 GCC -> C 中将 flex 和 bison 文件输出链接在一起

c - 发生 fatal error 时如何重新启动Linux系统(C编程)

c++ - 如何适本地反检查 Boost 错误代码?

ruby-on-rails - Ruby:从字符串中提取单词

parsing - 是否有一种既定的方法来编写可以重建其确切输入的解析器?

python - 使用 float 和整数解析 python 字符串

python - 使用 Beautiful Soup 从非类部分获取数据