Yacc只读取规则的第一个匹配项

时间:2016-04-12 19:15:23

标签: yacc lex

您好我正在编写一个简单的yacc程序,它接受一个程序代码并计算有多少个assign语句。

例如,对于以下代码段:

 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&lt; test.txt,输出显示有一个赋值。它似乎只承认第一句话。

如何让程序在第一场比赛后继续寻找比赛?

另外,为什么yacc.y的第11行和第13行有分号?由于它全部用“|”连接,我不明白为什么;放在那里。

2 个答案:

答案 0 :(得分: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.
...
;

答案 1 :(得分:1)

您的语法只解析一个语句。进行以下更改:

%start statements

statements
: statement
| statements statement
;

等。和以前一样。