由于换行引起的bison程序报错ERROR: syntax error解决方法

最近在写flex & bison程序,但是bison总是解析不正确,第一次运行yyparse()是正确的,但enter后再输入,总会报错ERROR: syntax error。改写yyerror函数为

yyerror(char *s)
{
	extern int yylineno;	// defined and maintained in lex
	extern char *yytext;	// defined and maintained in lex
	int len=strlen(yytext);
	int i;
	char buf[512]={0};
	for (i=0;i<len;++i)
	{
		sprintf(buf,"%s%d ",buf,yytext[i]);
	}
	fprintf(stderr, "ERROR: %s at symbol '%s' on line %d\n", s, buf, yylineno);
	yyparse();
}

之后,可以输出报错字符串的ASCII码。发现是10号字符,也就是换行的\n解析出错导致。众所周知,Linux下换行就是\n,而windows下是\r\n。
在这里插入图片描述
于是,在a.l文件加入:

[\r\n]  {printf("%d",yytext[0]);return EOL;}

让\r和\n都能输出EOL,同时把ASCII码送出来方便调试。

结果,经过测试,windosws控制台的换行就是\n,就没有\r什么事儿。只能另寻思路排错。

最后发现是BNC写错了。
原来的BNC写的是这样:

exp: 
  | block exp EOL
;

block: NOTE {printf("%c ",$1);}
  | AT NUMBER {printf("at%d ",$2);}
  | LEFT NUMBER COLON exp RIGHT
  | EXCLAM NOTE {printf("%c3/4 ",$2);}
  | BIGGER NOTE {printf("%c1/4 ",$2);}
  | NOTE MINUS {printf("%c%d ",$1,$2+1);}
;

解析exp的时候,每层exp展开都会在后面带一个EOL,展开多少层就多少个EOL,但实际输入串只有一个EOL是结束符,这样,bison在读完第一个EOL时,还在等待后面的EOL送进来,但实际上进来的已经是另一个串了,所以这时新串无法解析,就会报错。

改为以下写法后,问题解决。

exp: 
  | block exp
;

block: NOTE {printf("%c ",$1);}
  | AT NUMBER {printf("at%d ",$2);}
  | LEFT NUMBER COLON exp RIGHT
  | EXCLAM NOTE {printf("%c3/4 ",$2);}
  | BIGGER NOTE {printf("%c1/4 ",$2);}
  | NOTE MINUS {printf("%c%d ",$1,$2+1);}
  | EOL {printf("eol ",$1);}
;
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,你的问题是如何用flex和bison自动化工具实现语法分析器,程序输入是一段C--源代码,如果检测到语法误,误提示信息在输出中单独占一Error type (Syntactical) at line xx。 首先,你需要准备一个用于语法分析的bison源文件和一个用于词法分析的flex源文件。 在flex源文件中,你需要定义C--中的关键字、运算符、标识符等词法单元,并为每个词法单元分配一个唯一的token值。同时,你还需要定义误处理规则,以便在遇到无法识别的词法单元时输出误信息。 在bison源文件中,你需要定义C--语法规则,并指定每个规则的动作。在动作中,你可以进语法分析、语义分析等操作,并在遇到语法误时输出误信息。 下面是一个简单的例子,演示了如何使用flex和bison实现C--语法分析器: flex文件: ``` %{ #include "y.tab.h" %} %% "if" { return IF; } "else" { return ELSE; } "while" { return WHILE; } "return" { return RETURN; } "int" { return INT; } "void" { return VOID; } "+" { return PLUS; } "-" { return MINUS; } "*" { return TIMES; } "/" { return DIVIDE; } "=" { return ASSIGN; } "<" { return LT; } "<=" { return LE; } ">" { return GT; } ">=" { return GE; } "==" { return EQ; } "!=" { return NEQ; } "(" { return LPAREN; } ")" { return RPAREN; } "{" { return LBRACE; } "}" { return RBRACE; } ";" { return SEMICOLON; } "," { return COMMA; } [0-9]+ { yylval.intval = atoi(yytext); return INTVAL; } [a-zA-Z][a-zA-Z0-9]* { yylval.strval = strdup(yytext); return ID; } "//"(.)* { /* ignore comments */ } [ \t\r\n] { /* ignore whitespace */ } . { yyerror("Syntax Error"); } %% int yywrap() { return 1; } ``` bison文件: ``` %{ #include <stdio.h> #include <stdlib.h> #include "y.tab.h" %} %token IF ELSE WHILE RETURN INT VOID %token PLUS MINUS TIMES DIVIDE ASSIGN %token LT LE GT GE EQ NEQ %token LPAREN RPAREN LBRACE RBRACE SEMICOLON COMMA %token INTVAL ID %% program: declaration_list ; declaration_list: declaration | declaration_list declaration ; declaration: var_declaration | fun_declaration ; var_declaration: type_specifier ID SEMICOLON ; type_specifier: INT | VOID ; fun_declaration: type_specifier ID LPAREN params RPAREN compound_stmt ; params: param_list | VOID ; param_list: param | param_list COMMA param ; param: type_specifier ID ; compound_stmt: LBRACE local_declarations statement_list RBRACE ; local_declarations: empty | local_declarations var_declaration ; statement_list: empty | statement_list statement ; statement: expression_stmt | compound_stmt | selection_stmt | iteration_stmt | return_stmt ; expression_stmt: expression SEMICOLON | SEMICOLON ; selection_stmt: IF LPAREN expression RPAREN statement | IF LPAREN expression RPAREN statement ELSE statement ; iteration_stmt: WHILE LPAREN expression RPAREN statement ; return_stmt: RETURN SEMICOLON | RETURN expression SEMICOLON ; expression: var ASSIGN expression | simple_expression ; var: ID ; simple_expression: additive_expression relop additive_expression | additive_expression ; additive_expression: term | additive_expression PLUS term | additive_expression MINUS term ; term: factor | term TIMES factor | term DIVIDE factor ; factor: LPAREN expression RPAREN | var | INTVAL ; relop: LT | LE | GT | GE | EQ | NEQ ; empty: ; %% void yyerror(const char* s) { printf("Error type (Syntactical) at line %d: %s\n", yylineno, s); } int main() { yyparse(); return 0; } ``` 在编译并运程序时,你需要将生成的flex和bison源文件编译为可执文件,并将C--源代码作为输入参数传递给程序。如果程序检测到语法误,它会在输出中单独占一输出误信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值