關于lex與yacc生成parser的錯誤信息提示
以前在學校的時候弄過lex和yacc,當時抱著完成作業的心態,對于一些問題也沒好好研究過。最近忙里偷閑,又玩了一把,對于如何產生parser錯誤信息算是有了一些了解。 用的是freebsd5.3自帶的lex以及yacc,一般情況下生成的parser在遇到錯誤是只能報出一句簡單
以前在學校的時候弄過lex和yaclearcase/" target="_blank" >cc,當時抱著完成作業的心態,對于一些問題也沒好好研究過。最近忙里偷閑,又玩了一把,對于如何產生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提供行號(據說有很大開銷),而列號即行內的字符位置是不能直接提供的,網上有一些對應的方法,不過我沒有試過。
原文轉自:http://www.anti-gravitydesign.com
- 評論列表(網友評論僅供網友表達個人看法,并不表明本站同意其觀點或證實其描述)
-
国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97
|