如何解决Bison警告"......没有声明类型"

Asa*_*f R 43 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;}
;

%%
Run Code Online (Sandbox Code Playgroud)

导致出现以下类型的警告:

警告:'exp'的$$没有声明的类型.

它是什么意思,我该如何解决?

Asa*_*f R 42

定义的并集(%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;}
;

%%
Run Code Online (Sandbox Code Playgroud)

  • 一点:符号“%type&lt;val&gt; exp NUM”并不意味着特定的约简“exp NUM”具有类型“val”;这意味着“exp”的类型为“VAL”,而“NUM”的类型为“val”。顺便说一句,这个发布的答案比没有示例的类型指令的官方文档更有用。 (3认同)

Aid*_*ell 7

作为进一步的想法,如果你想更明确地减少你的数量(如果你正在进行AST通知,这可能很方便)那么你可以使你的堆栈值指针然后自己处理类型值.与标量类型非常相似:

struct myScalar {
    union {
        int num;
        char *id;
        char *float_lexeme;
    }payload;

    enum {
        TYPE_NUM,
        TYPE_IDENTIFIER,
        TYPE_FLOAT_CHAR
    } type;
    char *orig_lexeme;
};
Run Code Online (Sandbox Code Playgroud)

并有一个typedef和scalar_val *val堆栈.

当您转移到更复杂的编译器前端时,它可以帮助您构建这样的AST,这样当您遍历树时,您拥有更好的元数据,并且您还可以使用预语义类型的翻译来扩充翻译.然后它归结为你的叶片制作,如ID,将lexeme洗牌到正确的标量有效载荷.

不是一个完整的解释,但你明白了.

希望这有助于您未来的Bison/Lex前端和......

祝好运

  • 你能解释一下吗?我不明白“%type”是如何工作的。 (2认同)