Как решить предупреждение Bison "... не имеет объявленного типа"
Запуск Bison в этом файле:
%{
#include <iostream>
int yylex();
void yyerror(const char*);
%}
%union
{
char name[100];
int val;
}
%token NUM ID
%right '='
%left '+' '-'
%left '*'
%%
exp : NUM {$$.val = $1.val;}
| ID {$$.val = vars[$1.name];}
| exp '+' exp {$$.val = $1.val + $3.val;}
| ID '=' exp {$$.val = vars[$1.name] = $3.val;}
;
%%
Приводит к предупреждениям типа:
предупреждение: $$ из 'exp' не имеет объявленного типа.
Что это значит и как его решить?
Ответы
Ответ 1
Определенный союз (% union) не предназначен для непосредственного использования. Скорее, вам нужно указать Bison, членом которого является член союза.
Это делается с помощью директивы type%.
Фиксированная версия кода:
%{
#include <iostream>
int yylex();
void yyerror(const char*);
%}
%union
{
char name[100];
int val;
}
%token NUM ID
%right '='
%left '+' '-'
%left '*'
%type<val> exp NUM
%type<name> ID
%%
exp : NUM {$$ = $1;}
| ID {$$ = vars[$1];}
| exp '+' exp {$$ = $1 + $3;}
| ID '=' exp {$$ = vars[$1] = $3;}
;
%%
Ответ 2
В качестве дополнительной мысли, если вы хотите быть более явным с вашими сокращениями (если вы выполняете аннотацию AST, это может быть удобно), тогда вы можете сделать указатели на значения стека, а затем сами обрабатывать значения типов. Подобно скалярным типам:
struct myScalar {
union {
int num;
char *id;
char *float_lexeme;
}payload;
enum {
TYPE_NUM,
TYPE_IDENTIFIER,
TYPE_FLOAT_CHAR
} type;
char *orig_lexeme;
};
И у вас есть typedef и scalar_val *val
для стека.
Когда вы переходите на более сложные интерфейсы компилятора, это может помочь построить ваш АСТ таким образом, чтобы при пересечении дерева у вас были лучшие метаданные, и вы также можете увеличить перевод с переводами для пред-семантических типов, Затем он сводится к вашим листовым продуктам, таким как ID, чтобы перетасовать лексему в нужную скалярную полезную нагрузку.
Не полное объяснение, но вы получаете идею.
Надеюсь, что это поможет с вашим будущим интерфейсом Bison/Lex и...
Удача