- 締切済み
yacc,lexで作ったプログラムが正しく動きません。
加減乗除ができ、平方根や常用対数を計算でき、PIが円周率3.14159265に変換される、負の数、浮動小数点数を扱える電卓のインタプリタ(数式を入力すると計算結果を表示して終了するプログラム)をyacc構文解析とlex字句解析を用いて以下のようにしました。 yacc %{ #include<stdio.h> #include<math.h> int yyerror(char* s); %} %union{ double num; } %type<num> E T F %token<num> NUM SQRT LOG10 PI %% program: E {printf("%lf\n", $1); } E : E'+'T {$$=$1+$3; } |E'-'T {$$=$1-$3; } |T {$$=$1; } ; T : T'*'F {$$=$1*$3; } |T'/'F {$$=$1/$3; } |F {$$=$1; } ; F : '('E')' {$$=$2; } |SQRT'('E')' {$$=sqrt($3); } |LOG10'('E')' {$$=log10($3); } |PI {$$=3.14159265; } |NUM {$$=$1; } |'-'F {$$=$2*(-1); } ; %% main(){ yyparse(); } yyerror(char* s){ fprintf(stderr, "%s\n", s); } lex %{ #include "j5_13y.h" %} D 0|1|2|3|4|5|6|7|8|9 DEZ 1|2|3|4|5|6|7|8|9 %% "+" {return *yytext; } "-" {return *yytext; } "*" {return *yytext; } "/" {return *yytext; } "(" {return *yytext; } ")" {return *yytext; } "sqrt" {return SQRT; } "log10" {return LOG10; } "PI" {return PI; } ({DEZ}{D}*|0)|({DEZ}{D}*|0).{D}* {yylval.num=atof(yytext); return NUM; } . {yyerror("invalid character"); exit(1); } %% int yywrap(){return 1; } コンパイルは通り、実行時エラーも出ません。 しかし、数式を入力してエンターキーを押すと、何も表示せず入力待ち状態が続き、ここでの入力は前の入力に連結されて処理されます。 (例)入力1.0+2.0(Enter) ↓ 改行して入力待ち状態 ↓ 入力-log10(100.0)(Enter) ↓ 改行して入力待ち ↓ 入力+sqrt(4.0)(Enter) ↓ 改行して入力待ち ↓ 入力-2.0*PI(Enter) ↓ 改行して入力待ち ↓ 入力2.0-1.0 ↓ syntax error表示し終了 上記コードのどこが悪いのでしょうか。よろしくお願いします。
- みんなの回答 (3)
- 専門家の回答
みんなの回答
- sakusaker7
- ベストアンサー率62% (800/1280)
質問者さんの使っているyacc や lex がどういうものかわかりませんが、 GNU bison をyacc として使っているのなら、 main(){ yydebug=1; yyparse(); } yyerror(char* s){ fprintf(stderr, "%s\n", s); } main() 関数をちょっといじって、 >bison -y -d -t -v okw.y >gcc -DYYDEBUG=1 y.tab.c lex.yy.c -ookw のようにデバッグ版のパーザをつくります。 これを実行すると >okw Starting parse Entering state 0 Reading a token: という入力待ちになります。 ここで適当な入力( log10(100.0) とか)を入力すると Reading a token: log10(100.0) Next token is token LOG10 () Shifting token LOG10 () Entering state 3 Reading a token: Next token is token '(' () Shifting token '(' () Entering state 12 Reading a token: Next token is token NUM () Shifting token NUM () Entering state 1 Reducing stack by rule 12 (line 25): $1 = token NUM () -> $$ = nterm F () Stack now 0 3 12 Entering state 10 Reducing stack by rule 7 (line 19): $1 = nterm F () -> $$ = nterm T () Stack now 0 3 12 Entering state 9 Reading a token: Next token is token ')' () Reducing stack by rule 4 (line 15): $1 = nterm T () -> $$ = nterm E () Stack now 0 3 12 Entering state 21 Next token is token ')' () Shifting token ')' () Entering state 28 Reducing stack by rule 10 (line 23): $1 = token LOG10 () $2 = token '(' () $3 = nterm E () $4 = token ')' () -> $$ = nterm F () Stack now 0 Entering state 10 Reducing stack by rule 7 (line 19): $1 = nterm F () -> $$ = nterm T () Stack now 0 Entering state 9 Reading a token: と、どのように文法規則をたどっていったかがわかります。 bison (yacc) に対するオプション指定で y.output というファイルができてますから、 入力に対して自分の期待通り構文解析されているか確かめてみてください。 あとヒントひとつ。 ({DEZ}{D}*|0)|({DEZ}{D}*|0).{D}* {yylval.num=atof(yytext); この正規表現に間違いがあります。