我不熟悉 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/