0

編集:コード全体。ここで問題となるのは、目標の作成で「:」を使用する必要があることです。これは、おもちゃのc言語の3番地コードを生成するためのコードです。問題の生成IDは、目標から始まります。

私の古いレクサーコードを編集します:

%%


"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

あとはコロンを消したい。

4

1 に答える 1

2

ここでのコメントから、レクサーがスペースをトークンとしてパーサーに返していると推測しています。つまり、文法にはスペース(' ')トークンがないため、スペースを含む入力は何にも一致しません。

より一般的な配置は、レクサーがスペースを返さないようにすることです。スペースは無視してください。したがって、次のようなlex/flexルールがあります。

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

もちろん、これは単なる推測です。レクサーやそれが機能するトークンに関する情報を提供していないからです。

編集

まだレクサーコードを投稿していませんが、次のフレックスレクサーと組み合わせると、パーサーは正常に機能します。

"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 に答える