$ ...的[...]没有声明的类型

时间:2013-08-05 01:15:22

标签: yacc

我对Yacc不熟悉并试图找到一个例子,我发现here可以工作。当我尝试使用yacc -d calc.yacc进行编译时,出现以下错误。

  

calc.yacc:42.17-18:`stat'的$ 1没有声明的类型

     

calc.yacc:96.22-23:`expr'的$ 1没有声明的类型

     

calc.yacc:105.17-18:$ number的$ 1没有声明的类型

     

calc.yacc:106.20-21:$ number的$ 1没有声明的类型

     

calc.yacc:110.29-30:“number”的$ 2没有声明的类型

我尝试使用谷歌搜索,据我所知,解决方案与%类型有关,但我不确定要添加什么。

代码如下:

%{
    #include <stdio.h>

    int regs[26];
    int base;

    %}

    %start list

    %union { int a; }

    %type <a> expr number

    %token DIGIT LETTER

    %left '|'
    %left '&'
    %left '+' '-'
    %left '*' '/' '%'
    %left UMINUS  /*supplies precedence for unary minus */

    %%                   /* beginning of rules section */

    list:                       /*empty */
             |
            list stat '\n'
             |
            list error '\n'
             {
               yyerrok;
             }
             ;

    stat:    expr
             {
               printf("%d\n",$1);
             }
             |
             LETTER '=' expr
             {
               regs[$1] = $3;
             }

             ;

    expr:    '(' expr ')'
             {
               $$ = $2;
             }
             |
             expr '*' expr
             {

               $$ = $1 * $3;
             }
             |
             expr '/' expr
             {
               $$ = $1 / $3;
             }
             |
             expr '%' expr
             {
               $$ = $1 % $3;
             }
             |
             expr '+' expr
             {
               $$ = $1 + $3;
             }
             |
             expr '-' expr
             {
               $$ = $1 - $3;
             }
             |
             expr '&' expr
             {
               $$ = $1 & $3;
             }
             |
             expr '|' expr
             {
               $$ = $1 | $3;
             }
             |

            '-' expr %prec UMINUS
             {
               $$ = -$2;
             }
             |
             LETTER
             {
               $$ = regs[$1];
             }

             |
             number
             ;

    number:  DIGIT
             {
               $$ = $1;
               base = ($1==0) ? 8 : 10;
             }       |
             number DIGIT
             {
               $$ = base * $1 + $2;
             }
             ;

    %%
    main()
    {
     return(yyparse());
    }

    yyerror(s)
    char *s;
    {
      fprintf(stderr, "%s\n",s);
    }

    yywrap()
    {
      return(1);
    }

2 个答案:

答案 0 :(得分:4)

$ 1,$ 2等等是指语法规则右侧的术语。例如在

stat:    expr
             {
               printf("%d\n",$1);
             }
             |
             LETTER '=' expr {
               regs[$1] = $3;
             }

LETTER'='expr是规则之一,在下面的括号中,$ 1指的是LETTER。 regs[$1] = $3;将被制作成C语句,但为了做到这一点,yacc需要知道$ 1的类型。如果你添加

%type <a> LETTER

在第一个%类型声明之后(或者只是在expr之后列出LETTER),将会处理第一个错误。 DIGITbase也是如此。请注意,没有任何内容可以引用stat(自然)的值,因此不需要stat的%类型声明。因此在

calc.yacc:105.17-18: $1 of `number' has no declared type

calc.yacc:106.20-21: $1 of `number' has no declared type

calc.yacc:110.29-30: $2 of `number' has no declared type

第一行表示DIGIT具有未知类型,第二行表示与number相同的问题;最后,最后一行提醒您声明base的类型。这是它所指的yacc代码:

 number:  DIGIT
             {
               $$ = $1;
               base = ($1==0) ? 8 : 10;
             }       |
             number DIGIT
             {
               $$ = base * $1 + $2;
             }
             ;

最后,没有涉及太多细节,声明

regs[$1]=$3; 

将由yacc翻译成接近:

的内容
regs[YS[1].<type of LETTER>]=YS[3].<type of expr>;

其中YS是'魔术数组'(实际上是yacc的堆栈); YS具有声明的%union的类型。因此,您可以看到,为了使其成为合法的C,yacc需要知道%union <type of LETTER>的哪个成员引用。这是%type声明的用途。

答案 1 :(得分:-1)

%{
#include<stdio.h>
int regs[26];
int base;
%}

%union { int a; }


%token DIGIT LETTER

%left '|'
%left '&'
%left '+' '-'
%left '*' '/' '%'
%left UMINUS  /*supplies precedence for unary minus */


%type <a> stat expr number DIGIT LETTER

%%                   /* beginning of rules section */

list:    list stat  '\n'
         |
        list error '\n'
         {
           yyerrok;
         }
         | /*empty */
         ;
stat:    expr
         {
           printf("%d\n",$1);
         }
         |
         LETTER '=' expr
         {
           regs[$1] = $3;
         }

         ;

expr:    '(' expr ')'
         {
           $$ = $2;
         }
         |
         expr '*' expr
         {

           $$ = $1 * $3;
         }
         |
         expr '/' expr
         {
           $$ = $1 / $3;
         }
         |
         expr '%' expr
         {
           $$ = $1 % $3;
         }
         |
         expr '+' expr
         {
           $$ = $1 + $3;
         }
         |
         expr '-' expr
         {
           $$ = $1 - $3;
         }
         |
         expr '&' expr
         {
           $$ = $1 & $3;
         }
         |
         expr '|' expr
         {
           $$ = $1 | $3;
         }
         |

        '-' expr %prec UMINUS
         {
           $$ = -$2;
         }
         |
         LETTER
         {
           $$ = regs[$1];
         }

         |
         number
         ;

number:  DIGIT
         {
           $$ = $1;
           base = ($1==0) ? 8 : 10;
         }       
         |
         number DIGIT
         {
           $$ = base * $1 + $2;

         }
         ;

%%
main()
{
 return(yyparse());
}

yyerror(s)
char *s;
{
  fprintf(stderr, "%s\n",s);
}

yywrap()
{
  return(1);
}

需要使用%type 指令来指定在哪些表达式中使用union的成员。为了使用union成员a,我们应该使用上述指令。 点击此处%type