yacc - $1 of [...] 没有声明类型

标签 yacc

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

calc.yacc:42.17-18: $1 of `stat' has no declared type

calc.yacc:96.22-23: $1 of `expr' has no declared type

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


我尝试使用谷歌搜索,据我所知,该解决方案与 %type 有关,但我不确定要添加什么。
代码如下:
%{
    #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);
    }

最佳答案

$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

在第一个 %type 声明之后(或者简单地在 expr 之后列出 LETTER),第一个错误将被处理。 DIGIT 也是如此和 base .请注意,没有任何内容(自然地)引用 stat 的值,因此不需要 %type 声明 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声明是为了。

关于yacc - $1 of [...] 没有声明类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18049349/

相关文章:

c++ - 声明类变量c++

parsing - 用于 R 的 Lex 和 YACC 类工具?

c++ - 是否可以堆叠Yacc文法规则代码?

mysql - 在 ANTLR 中编写 SQL 解析器有哪些挑战?

c - Lex - 识别标记

compiler-construction - 野牛移位/减少冲突-Tiger Compiler

c - 具有启动条件的 Flex 可重入

go - Go 1.5 和 1.6 中 yacc 的向后兼容性

gcc - Bison 解析器总是打印 "syntax error"

c - 为什么 Visual Studio 2012 在未更改源文件时运行自定义构建步骤?