2016-04-12 3 views
1

Привет Я пишу простую программу yacc, которая принимает программный код и подсчитывает, сколько операторов присваивания есть.Yacc только читает первое совпадение правила

Например, для следующего фрагмента кода:

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

Я хочу, чтобы мой Yacc напечатать, что есть 2 Назначьте предложения. Поскольку я новичок, я нашел образец кода из книги Орейли онлайн и изменил код.

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, вывод показывает, что есть одно назначение. Кажется, что это только признание первого предложения.

Как это сделать, чтобы программа продолжала искать совпадения после первого совпадения?

Кроме того, почему существует точка с запятой в строке 11 и 13 в yacc.y? Поскольку все это связано с '|', я не понимаю, почему; находится там.

ответ

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