由于换行引起的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);}
;