2016-04-12 8 views
1

Hi Ich schreibe ein einfaches yacc-Programm, das einen Programmcode nimmt und zählt, wie viele Assign-Anweisungen es gibt.Yacc liest nur die erste Übereinstimmung der Regel

Zum Beispiel für den folgenden Code-Schnipsel:

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

Ich würde meine yacc darauf zu drucken, dass es 2 assign Sätze. Da ich ein Anfänger bin, fand ich einen Beispielcode aus Oreilys Buch online und modifizierte den Code.

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; 

Wenn ich den Code zu bauen, bekomme ich a.out . Wenn ich ./a.out < test.txt ausführe, zeigt die Ausgabe an, dass es dort eine Zuweisung gibt. Es scheint, als hätte es nur den ersten Satz erkannt.

Wie mache ich es so, dass das Programm nach dem ersten Spiel nach den Spielen sucht?

Auch warum gibt es Semikolon in Zeile 11 und 13 in yacc.y? Da alles mit '|' verbunden ist, verstehe ich nicht warum; ist dort platziert.

Antwort

1

Ihre Grammatik analysiert nur eine Aussage. Nehmen Sie die folgenden Änderungen vor:

%start statements 

statements 
: statement 
| statements statement 
; 

usw. wie zuvor.

1

Es ist sehr wichtig zu wissen, wie Sie Ihr Programm debuggen. Im ersten Teil der Datei müssen Sie #define YYDEBUG 1 und in der Hauptfunktion yydebug = 1 hinzufügen. Dies ermöglicht es Ihnen, genaue Schritte zu sehen, wenn Sie Ihren Parser ausführen und dann wissen Sie, wo Ihr Fehler ist. Das zu wissen ist extrem wichtig, weil Fehler in Yacc normalerweise sehr schwer zu finden sind. Also debuggen Sie Ihr Programm!

%{ 

#define YYDEBUG 1 // This is new 

%} 

int main(){ 

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

Semikolon auf Linie 11 ist falsch. Yacc-Regeln sehen so aus:

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

Alles stimmt, aber beantwortet die Frage nicht. – EJP

+0

Es nicht? Ich wies darauf hin, wo Fehler ist und warum erklärt. Sie sollten das nächste Mal die ganze Antwort lesen. –

+0

Ich las die ganze Antwort * letzte * Zeit und ich fand keine Lösung für die Frage. Sie haben darauf hingewiesen, wo * ein * Fehler ist, nicht der, der das Problem verursacht, über das gefragt wird. – EJP

Verwandte Themen