0

编辑:整个代码。现在的问题是我必须在目标生成中使用':':这是为玩具c语言生成三个地址代码的代码:它有3个地址代码支持赋值,if和for;问题产生 id 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

没有冒号:即:-

 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

我想在 else 之后消除冒号。

4

1 回答 1

2

我从您的评论中猜测您的词法分析器正在将空格作为标记返回给您的解析器,这意味着由于您的语法没有任何空格 ( ' ') 标记,因此带有空格的输入不会匹配任何内容。

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

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

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

编辑

您还没有发布您的词法分析器代码,但结合以下 flex 词法分析器,您的解析器对我来说可以正常工作:

"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
于 2012-10-19T16:25:13.773 回答