1
votes

Hi I am writing a simple yacc program that takes a program code and counts how many assign statements there are.

For example, for the following code snippet:

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

I'd like my yacc to print out that there are 2 assign sentences. Since I am a beginner, I found a sample code from Oreily's book online and modified the 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;

When I build the code, I get a.out. When I run ./a.out < test.txt, the output shows that the there is one assign. IT seems like it only recognized the first sentence.

How do I make it so that the program keeps looking for the matches after the first match?

Also, why is there semi-colon in line 11 and 13 in yacc.y? Since it's all connected by '|', I don't understand why ; is placed there.

2

2 Answers

2
votes

Your grammar only parses one statement. Make the following changes:

%start statements

statements
: statement
| statements statement
;

etc. as before.

0
votes

It's very important knowing how to debug your program. In first part of the file you need to add #define YYDEBUG 1, and in main function yydebug = 1. This will allow you to see exact steps when you run your parser and then you'll know where your error is. Knowing this is extremely important, because mistakes in Yacc are usually very hard to find. So debug your program!

%{

#define YYDEBUG 1 // This is new

%}

int main(){

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

Semicolon on line 11 is wrong. Yacc rules look like this:

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