为什么这个语法规则在Yacc中不匹配?

时间:2012-10-19 14:01:08

标签: yacc

编辑:整个代码。现在的问题是我必须在目标制作中使用':': 这是为玩具c语言生成三个地址代码的代码: 它有3个地址代码支持分配,if和for; 问题生产是从if开始的。

修改 我的旧勒克斯代码:

%%


"if" return IF;
"else" return ELSE;
"for"  return FOR;
[0-9]+ {strcpy(yylval.dval,yytext);return NUM;}
{CHAR}+({DIGIT}*{CHAR}*)* {strcpy(yylval.dval,yytext);return ID;}

[ \t]+  ;
[\n]    return -1;
. {return yytext[0];}
%%

Yacc代码:

%{
    #include <stdio.h>
    #include <math.h>
    int yylex(void);
    char p[10]="t",n1[10];
    int n =0;

    %}
    %union
    {
    char dval[10];
    }
    %token IF ELSE FOR
    %left '+' '-'
    %left '*' '/'
    %nonassoc UMINUS

    %token <dval> ID NUM
    %type <dval> S E
    %type <dval> RO
    %%


    goal : IF '(' RO ')' {if_label1();} S ';'{if_label2();} ELSE ':' S ';' {if_label3();}
         | S
         | FOR '(' S ';' {for_label1();} RO ';' {for_label2();} S ')' {for_label3();}  S {for_label4();}  
         ;


    S : ID '=' E {printf(" %s = %s\n",$$, $3);}
      | E 
      ;


    E : ID        {n++;sprintf(n1,"%d",n);strcpy($$,p);strcat($$,n1);printf(" %s = %s\n",$$,$1);}
      | NUM {}    {n++;sprintf(n1,"%d",n);strcpy($$,p);strcat($$,n1);printf(" %s = %s\n",$$,$1);}

      | E '+' E {n++;sprintf(n1,"%d",n);strcpy($$,p);strcat($$,n1);printf(" %s = %s + %s\n",$$,$1,$3);}
      | E '-' E {n++;sprintf(n1,"%d",n);strcpy($$,p);strcat($$,n1);printf(" %s = %s – %s\n",$$,$1,$3);}
      | E '*' E {n++;sprintf(n1,"%d",n);strcpy($$,p);strcat($$,n1);printf(" %s = %s * %s\n",$$,$1,$3);}
      | E '/' E {n++;sprintf(n1,"%d",n);strcpy($$,p);strcat($$,n1);printf(" %s = %s / %s\n",$$,$1,$3);}
      | '(' E ')' {strcpy($$,p);strcat($$,n1);}

    RO : E '>' E  {n++;sprintf(n1,"%d",n);strcpy($$,p);strcat($$,n1);printf(" %s = %s > %s\n",$$,$1,$3);}
       | E '<' E  {n++;sprintf(n1,"%d",n);strcpy($$,p);strcat($$,n1);printf(" %s = %s < %s\n",$$,$1,$3);}
       | E '==' E {n++;sprintf(n1,"%d",n);strcpy($$,p);strcat($$,n1);printf(" %s = %s == %s\n",$$,$1,$3);}
       | E '!=' E {n++;sprintf(n1,"%d",n);strcpy($$,p);strcat($$,n1);printf(" %s = %s != %s\n",$$,$1,$3);}
       | E

    ;
    %%

    main()
    {
    yyparse();
    }

    int yyerror (char *s)
    {


    }
    if_label1()
    {
        printf("t%d = not t%d\n", n+1, n);
        printf("if t%d GOTO L1\n",n+1);
    }
    if_label2()
    {
        printf("GOTO L2\n");
        printf("L1 :\n");
    }

    if_label3()
    {
        printf("L2\n");
    }

    for_label1()
    {
        printf("L0:\n");
    }
    for_label2()
    {
        printf("t%d = not t%d\n", n+1, n);
        printf("if t%d GOTO L1\n",n+1);
        printf("GOTO L2:\n");
        printf("L3:\n");    
    }
    for_label3()
    {
        printf("GOTO L0\n");
        printf("L2:\n");
    }

    for_label4()
    {
        printf("GOTO L3\n");
        printf("L1:\n");
    }

以上代码的输出:

./a.out
if(a>c)a=b;else:a=c;
 t1 = a
 t2 = c
 t3 = t1 > t2
t4 = not t3
if t4 GOTO L1
 t4 = b
 a = t4
GOTO L2
L1 :
 t5 = c
 a = t5
L2

没有冒号:ie: -

 goal : IF '(' RO ')' {if_label1();} S ';'{if_label2();} ELSE  S ';' {if_label3();}

输出

./a.out
if(a>c)a=d;else d=s;
 t1 = a
 t2 = c
 t3 = t1 > t2
t4 = not t3
if t4 GOTO L1
 t4 = d
 a = t4
GOTO L2
L1 :
wrong syntax  //which is not expected

我想在其他地方消灭结肠。

1 个答案:

答案 0 :(得分:2)

我猜你的评论是你的词法分析器将空格作为标记返回到你的解析器,这意味着由于你的语法没有任何空格(' ')标记,所以带空格的输入不匹配任何东西。

更常见的安排是让词法分析器不返回空格 - 只需忽略它们。所以你有一个lex / flex规则,如:

[ \t\n]    ;    /* ignore spaces, tabs, and newlines */

当然这只是一个猜测,因为你没有提供有关你的词法分析器或它使用的标记的信息。

修改

你还没有发布你的词法分析器代码,但结合下面的flex lexer,你的解析器对我来说很好:

"if"    return IF;
"else"  return ELSE;
"for"   return FOR;
[a-z]+  { strcpy(yylval.dval, yytext); return ID; }
[0-9]+  { strcpy(yylval.dval, yytext); return NUM; }
[ \t\n] ;
.       return *yytext;


$ ./a.out
if(a>c)a=d;else d=s;
 t1 = a
 t2 = c
 t3 = t1 > t2
t4 = not t3
if t4 GOTO L1
 t4 = d
 a = t4
GOTO L2
L1 :
 t5 = s
 d = t5
L2