極北データモデリング このページをアンテナに追加 RSSフィード

2008-06-17

[]yyparse()でsyntax errorと言われたときのデバッグ方法


yacc/lex(bison/flex)で生成したパーサ yyparse() は、シンタクスエラーのある入力ファイルを食わせると、デフォルトでは

[syntax error]

というそっけないエラーメッセージを吐いてエラー終了する。これではどこが間違っているのか分からないので、以下の3ステップでエラーになっている理由を探る。


YYERROR_VERBOSE

y.tab.cのコンパイル時に-DYYERROR_VERBOSEを指定する。

$(CC) -c $(CFLAGS) -DYYERROR_VERBOSE $(CINC) y.tab.c

すると、エラーメッセージが少し人間に優しくなる。

[syntax error, unexpected YYYY, expecting XXXX]

これは「次はXXXXのはずなのにYYYYが出てきましたよ」というエラー。

yaccの定義ファイル(*.y)は正しく、入力ファイルが間違っているとき、YYERROR_VERBOSEするだけで問題は解決する。


yacc -v

yaccの定義ファイルにバグがあって、プログラマが期待したようなパーサが生成されていない場合は、エラーメッセージをverboseにしただけでは問題解決できないことが多い。

yacc コマンドに -v オプションを付けると、y.tab.cを出力するディレクトリに、同時にy.outputというファイルを生成する。

ここにはパーサの状態遷移ルールが人間に読めるような形で記述されているので、入力ファイルと付き合わせると「なぜ、yaccはXXXXがある位置にYYYYが来ると考えたのか」が分かる。

y.outputはあまり読みやすいものではないのだが、初期状態が「state 0」であることだけ押さえておけば、何となく読めるような気がしてくる。


YYDEBUG

y.outputを見ても何が間違っているのか分からない場合は、main()に yydebug=1; を追加し、

extern int yydebug;
int main(int argc, char *argv[]) {
	yydebug = 1;
	...		

y.tab.c のコンパイルオプションに YYDEBUG を指定する。

$(CC) -c $(CFLAGS) -DYYERROR_VERBOSE -DYYDEBUG $(CINC) y.tab.c


すると、標準エラー出力トレース情報を出力しながら動作するので、どのstateからどのstateに飛んで、何でこけたのか分かる。

Entering state 28

Reading a token: Next token is token AAAA ()

Shifting token AAAA ()

Entering state 19

Reading a token: Next token is token BBBB ()

Shifting token BBBB ()

Entering state 78

Reading a token: Next token is token XXXX ()

Error: popping token YYYY ()

トラックバック - http://d.hatena.ne.jp/tgk/20080617/1213719334