1

我想运行以下 .y 代码来构建 C 编译器。代码取自这本书

下面的 miniC.y 代码是:

    %{
         #include <stdio.h>
         #include "mini.h" 
         #include "miniC.h"
    %}
    %union {
        ADDRESS  address;
        int code;   /* comparison code 1-6 */
        struct  {int L1;
             int L2;
             int L3;
             int L4;} labels;
    }
    %token <address> IDENTIFIER
    %token <code> INT
    %token <code> FLOAT
    %token FOR
    %token WHILE
    %token <code> COMPARISON
    %token IF
    %token ELSE
    %token <address> NUM 
    %type <code> Type
    %type <address> Expr
    %type <address> OptExpr
    %type <labels> WhileStmt
    %type <labels> ForStmt
    %type <labels> IfStmt
    %type <labels> Label
    %right '='
    %left COMPARISON
    %left '+' '-'
    %left '*' '/'
    %left UMINUS UPLUS
   %%
   Function:    Type IDENTIFIER '(' ArgListOpt ')' CompoundStmt
    ;
   ArgListOpt:  ArgList
    |
    ;
   ArgList: ArgList ',' Arg
    | Arg
    ;
   Arg:     Type IDENTIFIER
    ;
  Declaration:  Type            {dcl = TRUE;
                                identType = $1;}
    IdentList ';'           {dcl = FALSE;}
    ;
  IdentList:    IDENTIFIER ',' IdentList
    | IDENTIFIER
    ;
  Type:     INT         {$$ = $1;}
    | FLOAT         {$$ = $1;}
    ;
  Stmt:     ForStmt
    | WhileStmt
    | Expr ';'  
    | IfStmt
    | CompoundStmt
    | Declaration
    | ';'           /* null statement */
    ;
 ForStmt:   FOR '(' Expr ';'    {$$.L1 = newlabel();
                 atom (LBL,NULL,NULL,NULL,0,$$.L1);}
    OptExpr ';'         {$$.L2 = newlabel();
                 atom (TST,$6,zero,NULL,6,
                    $<labels>$.L2);
                 $$.L3 = newlabel();
                 atom (JMP,NULL,NULL,NULL,0,
                    $<labels>$.L3);
                 $$.L4 = newlabel();
                 atom (LBL,NULL,NULL,NULL,0,
                    $<labels>$.L4);}
    OptExpr ')'     {atom (JMP,NULL,NULL,NULL,0,
                    $<labels>5.L1);
                 atom (LBL,NULL,NULL,NULL,0,
                    $<labels>8.L2);}
     Stmt           {atom (JMP,NULL,NULL,NULL,0,
                    $<labels>8.L4);
                 atom (LBL,NULL,NULL,NULL,0,
                    $<labels>8.L3);}
    ;   
 OptExpr:   Expr            {$$ = $1;}
    |           {$$ = one;} /* default to inf loop */
    ;
 WhileStmt:   WHILE         {$$.L1 = newlabel();
                   atom (LBL,NULL,NULL,NULL,0,$$.L1);}
       '(' Expr ')'     {$$.L2 = newlabel();
                 atom (TST,$4, zero, NULL,1,$$.L2);}
      Stmt          {atom (JMP,NULL,NULL,NULL,0,
                    $<labels>2.L1);
                 atom (LBL,NULL,NULL,NULL,0,
                    $<labels>6.L2);}
       ;
   IfStmt:     IF '(' Expr ')'      {$$.L1 = newlabel();
                         atom (TST, $3, zero, NULL, 1, $$.L1);}
       Stmt             {$$.L2 = newlabel();
                          atom (JMP,NULL,NULL,NULL,0, $$.L2);
                          atom (LBL,NULL,NULL,NULL,0, 
                       $<labels>5.L1);}
       ElsePart              {atom (LBL,NULL,NULL,NULL,0, 
                         $<labels>7.L2);} 
    ;
    ElsePart:   
    | ELSE Stmt
    ;
    CompoundStmt:   '{' StmtList '}'
    ;
    StmtList:   StmtList Stmt
    | 
    ; 

    Expr:       IDENTIFIER '=' Expr {atom (MOV, $3, NULL, $1,0,0);
                 $$ = $3;}
            | Expr COMPARISON Expr  
             Label      {$$ = alloc(1);
                 atom (MOV, one, NULL, $$,0,0);
                 atom (TST, $1, $3, NULL, $2, $4.L1);
                 atom (MOV, zero, NULL, $$,0,0);
                 atom (LBL,NULL,NULL,NULL,0,$4.L1);}
           | '+' Expr %prec UPLUS   {$$ = $2;}
           | '-' Expr %prec UMINUS  {$$ = alloc(1);
                 atom (NEG, $2,NULL,$$,0,0); } 
           | Expr '+' Expr  {$$ = alloc(1); 
                 atom (ADD, $1, $3,$$,0,0); }
           | Expr '-' Expr      {$$ = alloc(1);
                 atom (SUB, $1, $3, $$,0,0); }
           | Expr '*' Expr      {$$ = alloc(1);
                 atom (MUL, $1, $3, $$,0,0); }
           | Expr '/' Expr      {$$ = alloc(1);
                 atom (DIV, $1, $3, $$,0,0); }
           | '(' Expr ')'       {$$ = $2;}
           | IDENTIFIER     {$$ = $1; }
           | NUM        {$$ = $1; }
            ;
   Label:                   {$$.L1 = newlabel();}
           ;            /* Used to store a label in 
                   compare expr above */

   %%
   char *progname;
   char * op_text();
   int lineno = 1;
   ADDRESS save;
   ADDRESS one;   
   ADDRESS zero;
   int nextlabel = 1;

   #include "lex.yy.c"
   #include "gen.c"

   main (int argc, char *argv[]){
         progname = argv[0];
         atom_file_ptr = fopen ("atoms", "wb");
         strcpy (yytext,"0.0");
         zero = searchNums();   /* install the constant 0.0 in table */
         strcpy (yytext, "1.0");
         one = searchNums();  /* also 1.0 */
         yyparse();
         fclose (atom_file_ptr);
         if (!err_flag) code_gen();
   }
   yyerror (char * s){
        fprintf(stderr, "%s[%d]: %s\n", progname, lineno, s);
        printf ("yytext is <%s>", yytext);
        err_flag = TRUE;
   }

   newlabel (void){ return nextlabel++;}

   atom (int operation, ADDRESS operand1, ADDRESS operand2, 
         ADDRESS result, int comparison, int dest)
            /* put out an atom. destination will be a label number. */
   {   struct atom outp;
       outp.op = operation;
       outp.left = operand1;
       outp.right = operand2;
       outp.result = result;
       outp.cmp = comparison;
       outp.dest = dest;

       fwrite (&outp, sizeof (struct atom), 1, atom_file_ptr);
    } 

     decode (int atom){ 

          switch (atom){ 
                case ADD:   strcpy (mne, "ADD");
                    break;
                case SUB:   strcpy (mne, "SUB");
                    break;
                case MUL:  strcpy (mne, "MUL");
                   break;  
                case DIV: strcpy (mne, "DIV");
                  break;
               case JMP: strcpy (mne, "JMP");
                  break;
               case NEG: strcpy (mne, "NEG");
                 break;
               case LBL: strcpy (mne, "LBL");
                  break;
              case TST: strcpy (mne, "TST");
                  break;
              case MOV: strcpy (mne, "MOV");
     }

}

错误是:

miniC.y:65.42-43: $$ for the midrule at $5 of 'ForStmt' has no declared type
miniC.y:66.69-70: $$ for the midrule at $5 of 'ForStmt' has no declared type
miniC.y:67.42-43: $$ for the midrule at $8 of 'ForStmt' has no declared type
miniC.y:70.42-43: $$ for the midrule at $8 of 'ForStmt' has no declared type
miniC.y:73.42-43: $$ for the midrule at $8 of 'ForStmt' has no declared type
miniC.y:88.42-43: $$ for the midrule at $2 of 'WhileStmt' has no declared type
miniC.y:89.69-70: $$ for the midrule at $2 of 'WhileStmt' has no declared type
miniC.y:90.42-43: $$ for the midrule at $6 of 'WhileStmt' has no declared type
miniC.y:91.69-70: $$ for the midrule at $6 of 'WhileStmt' has no declared type
miniC.y:97.42-43: $$ for the midrule at $5 of 'IfStmt' has no declared type
miniC.y:98.72-73: $$ for the midrule at $5 of 'IfStmt' has no declared type
miniC.y:99.42-43: $$ for the midrule at $7 of 'IfStmt' has no declared type
miniC.y:100.70-71: $$ for the midrule at $7 of 'IfStmt' has no declared type
make: *** [y.tab.c] Error 1

我的makefile包含:

    miniC:  lex.yy.c y.tab.c 
        gcc -g  y.tab.c -o miniC -ly -ll
    lex.yy.c:miniC.l
         lex miniC.l
    y.tab.c:miniC.y
        yacc -d miniC.y

任何导师都可以出面建议我解决这个问题。感谢 Yoy

4

2 回答 2

4

这些错误抱怨$$在中间操作规则中使用(不包括类型标签),这是非法的。$$中途规则的所有使用都需要一个类型标签。有趣的是,并非所有用法都是错误的——其中一些具有 type 标签$<labels>$

我认为您需要做的是在所有中间规则操作中替换$$$<labels>$(但不是在规则结束操作中......)最简单的方法是查看错误消息(查看每个规则的行和列),并将其替换$$$<labels>$

于 2013-10-28T22:50:21.373 回答
0

您使用的是哪个版本的 bison/yacc?什么是命令行?我的版本给出了这些(非常常见的)信息:

[Charlies-MacBook-Pro:~/junk] crb% bison x.y
x.y: conflicts: 6 shift/reduce
[Charlies-MacBook-Pro:~/junk] crb% bison --version
bison (GNU Bison) 2.3
Written by Robert Corbett and Richard Stallman.

似乎说你的语法基本没问题。

也许发布您的 Makefile 并查看您的野牛版本。

于 2013-10-28T18:48:54.487 回答