2016-04-12 62 views
1

嗨,我正在寫一個簡單的yacc程序,它需要一個程序代碼並計算它有多少個分配語句。Yacc只讀取規則的第一個匹配

例如,對於下面的代碼片段:

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

我想我YACC打印出有2分分配的句子。由於我是初學者,因此我在網上找到了來自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 } 

的test.txt

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

當我建立的代碼,我得到的a.out 。當我運行./a.out < test.txt時,輸出顯示有一個分配。 IT似乎只是承認了第一句話。

我該如何製作以便程序在第一場比賽後繼續尋找比賽?

另外,爲什麼在yacc.y中有11行和13行分號?由於它全部通過'|'連接,所以我不明白爲什麼;放在那裏。

回答

1

您的語法只解析一條語句。進行以下更改:

%start statements 

statements 
: statement 
| statements statement 
; 

等等。

1

知道如何調試程序非常重要。在文件的第一部分中,您需要添加#define YYDEBUG 1,並在主要功能yydebug = 1中。這將允許您在運行解析器時查看確切的步驟,然後您將知道錯誤的位置。瞭解這一點非常重要,因爲Yacc中的錯誤通常很難找到。所以調試你的程序!

%{ 

#define YYDEBUG 1 // This is new 

%} 

int main(){ 

    yydebug = 1; // This is new 
    yyparse(); 
} 

11行上的分號錯誤。 Yacc規則如下所示:

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

全部爲真,但沒有回答問題。 – EJP

+0

它不?我指出錯誤在哪裏,並解釋了原因。你應該在下次閱讀完整的答案。 –

+0

我讀完了整個答案*最後一次*,但沒有找到解決問題的方法。你指出*錯誤是什麼,而不是導致問題被問到的那個錯誤。 – EJP