2016-04-12 14 views
1

こんにちは私は、プログラムコードを取り、いくつのassignステートメントがあるかを数える単純なyaccプログラムを書いています。例えばYaccはルールの最初の一致のみを読み込みます

、次のコードスニペットのために:

void main() { 
    int a = 3; 
    int bb = 10; 
} 

私は2つのアサイン文があることをプリントアウトするために私のyaccをしたいと思います。私は初心者であるため、Oreilyのオンラインブックからサンプルコードを見つけ、コードを修正しました。 〜

yacc.y

%{ 
2 #include <stdio.h> 
3 int assign = 0; 
4 %} 
5 
6 %token NAME NUMBER 
7 %start statement 
8 %% 
9 statement:  NAME '=' expression ';' {assign++;} 
11   ; 
12   |  expression    { printf("= %d\n", $1); } 
13   ; 
14 expression:  expression '+' NUMBER { $$ = $1 + $3; 
15           printf ("Recognized '+' expression.\n"); 
16           } 
17   |  expression '-' NUMBER { $$ = $1 - $3; 
18           printf ("Recognized '-' expression.\n"); 
19           } 
20   |  NUMBER     { $$ = $1; 
21           printf ("Recognized a number.\n"); 
22           } 
23   ; 
24 %% 
25 int main (void) { 
26   yyparse(); 
27   printf("assign =%d", assign); 
28   } 
29 
30 /* Added because panther doesn't have liby.a installed. */ 
31 int yyerror (char *msg) { 
32   return fprintf (stderr, "YACC: %s\n", msg); 
33   } 

lex.l

1 %{ 
2 #include "y.tab.h" 
3 extern int yylval; 
4 %} 
5 
6 %% 
7 [0-9]+ { yylval = atoi (yytext); 
8   printf ("scanned the number %d\n", yylval); 
9   return NUMBER; } 
10 [ \t] { printf ("skipped whitespace\n"); } 
11 \n  { printf ("reached end of line\n"); 
12   return 0; 
13   } 
14 [a-zA-Z]+  {printf("found name"); return NAME;} 
15 .  { printf ("found other data \"%s\"\n", yytext); 
16   return yytext[0]; 
17   /* so yacc can see things like '+', '-', and '=' */ 
18   } 
19 %% 
20 int yywrap(){ 
21   return 1; 
22 } 

私はコードをビルドするとき、私はa.outのがあるtest.txt

a = 3; 
3+2; 
b = 3; 

を取得。 ./a.out < test.txtを実行すると、出力には1つの割り当てがあることが示されます。 ITは最初の文章だけを認識したようです。

最初の試合後にプログラムが一致を探し続けるようにするにはどうすればよいですか?

また、yacc.yの11行目と13行目にセミコロンがあるのはなぜですか?すべてが '|'で結ばれているので、私はその理由を理解していません。そこに置かれます。

答えて

1

文法は1つの文だけを解析します。次のように変更します。

%start statements 

statements 
: statement 
| statements statement 
; 

などと同じように変更します。

1

プログラムをデバッグする方法を知っておくことは非常に重要です。ファイルの最初の部分では、#define YYDEBUG 1を追加し、メイン関数yydebug = 1に追加する必要があります。これにより、パーサーを実行したときの正確な手順を確認し、エラーの原因を特定できます。これを知ることは非常に重要です。なぜなら、Yaccの間違いは通常見つけにくいからです。だからあなたのプログラムをデバッグしてください!

セミコロン11は間違っています。 Yaccの規則は次のようになります。

Nonterminal : something here 
| something else here 
| ... etc. 
... 
; 
+0

すべてが真ですが質問には答えません。 – EJP

+0

それはありませんか?私はエラーがどこにあるのかを指摘し、理由を説明しました。あなたは次回全体の答えを読むべきです。 –

+0

私は全体の答え*最後の*時間を読んで、私は質問への解決策を見つけられませんでした。あなたは* an *エラーがどこに問題を引き起こす原因ではないかを指摘しました。 – EJP