$1 of [...] has no declared type
$1, $2, and so on refer to the terms on the right-hand side of a grammar rule. For example in
stat: expr
{
printf("%d\n",$1);
}
|
LETTER '=' expr {
regs[$1] = $3;
}
LETTER '=' expr is one of the rules and in the following parentheses $1 refers to LETTER. regs[$1] = $3;
will be made into a C statement but in order to do that, yacc needs to know what type $1 has. If you add
%type <a> LETTER
after the first %type declaration (or simply list LETTER
after expr) the first error will be taken care of. Same goes for DIGIT
and base
. Note that there is nothing that refers to the value of stat (naturally) so there is no need for a %type declaration for stat. Thus in
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
the first line implies that DIGIT
has an unknown type, the second line refers to the same problem with number
; finally the last line reminds you to declare the type for base
. Here is the yacc code it is referring to:
number: DIGIT
{
$$ = $1;
base = ($1==0) ? 8 : 10;
} |
number DIGIT
{
$$ = base * $1 + $2;
}
;
Finally, without getting into too many details, the statement
regs[$1]=$3;
will be translated by yacc into something close to:
regs[YS[1].<type of LETTER>]=YS[3].<type of expr>;
where YS is a 'magic array' (actually yacc's stack); YS has the type of the declared %union. Thus you can see that to make this into legal C, yacc needs to know which member of the %union <type of LETTER>
refers to. This is what the %type
declaration is for.
emilytrabert
Updated on June 09, 2022Comments
-
emilytrabert almost 2 years
I am unfamiliar with Yacc and trying to get an example I found here to work. When I try to compile with
yacc -d calc.yacc
, I get the following errors.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
I tried googling and from what I can tell, the solution has to do with %type, but I'm not sure what to add.
The code is below:
%{ #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); }
-
torek over 10 yearsIncidentally, all the errors would also go away if you removed the
%union
and%type
directives. The default type for the stack isint
, and without a%union
yacc assumes all tokens and nonterminals have the same type (YYSTYPE
if I recall correctly, defaultint
anyway). Use%union
and%type
to set different types for different tokens/nonterminals. -
Artjom B. about 6 yearsWelcome to Stack Overflow! While this code block may answer the question, it would be best if you could provide a little explanation for why it does so. Please edit your answer to include such a description.