快捷搜索:

关于lex与yacc生成parser的错误信息提示

曩昔在黉舍的时刻弄过lex和yacc,当时抱着完成功课的心态,对付一些问题也没好好钻研过。近来忙里偷闲,又玩了一把,对付若何孕育发生parser差错信息算是有了一些懂得。

用的是freebsd5.3自带的lex以及yacc,一样平常环境下天生的parser在遇履新错是只能报出一句简单的“syntax error”,对付差错的位置、等候的token等均没有提示。

事实上从lex可以得到行号的信息,只要在lex源文件的头上加上,

%option yylineno

即可。

而对付yacc输出的一些处置惩罚即可以实现简单的差错信息提示。措施是改动yyerror这个函数,下面是我改动后的一个例子,

void yyerror(char* s, int state){

fprintf(stderr, "%s\n", s);

if(state != -1){

fprintf(stderr, "line %d: ", yylineno);

fprintf(stderr, "%s expected ", yyerrmtx[state]);

fprintf(stderr, "before \"%s\"\n", yytext);

}//if

}

这里经由过程extern int yylineno获得当前的行号;另一方面,用一个自定义的yyerrmtx字符串数组寄放各个状态值下的等候的token,同时从经由过程extern char* yytext从lex引入当前实际输入的token。这样就可以形成一个简单的差错提示,形如,

line 3: VARIABLE expected before LEFTBRACE

这里的关键是若何获得yyerrmtx这张表。当然可以手工输入,然则有个措施可自动天生。履行yacc的时刻加上-d参数可以获得一个名为y.output的文件,其内容是对parser的各个状态、所作shift或reduce动作的一个文本阐明。那么就可以写一段脚本(我是用perl写的)从这个文件中掏出各个状态下等候的token的信息,从而获得yyerrmtx。

此外,关于掉足位置,lex只能经由过程yylineno供给行号(听说有很大年夜开销),而列号即行内的字符位置是不能直接供给的,网上有一些对应的措施,不过我没有试过。

您可能还会对下面的文章感兴趣: