如何解决Bison警告“...没有声明类型”的问题

54

在此文件上运行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'的$$没有声明的类型。

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


25
+1:在谷歌搜索“bison error has no declared type”时首先出现。 - INS
只是一个小的澄清。我有%union { int intValue; int floatValue; },但它不允许我使用$$.intValue$1.intValue。 它显示错误:请求在非结构体或联合体中使用成员'floatValue'。为什么会这样呢? - Shashwat
2个回答

51

这里定义的联合体(%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
一个小细节:符号 %type<val> exp NUM 并不意味着特定的规约 exp NUM 具有类型 val;它意味着 exp 具有类型 VAL,而 NUM 具有类型 val。顺便说一下,这个回答比类型指令的官方文档更有用,因为它提供了示例。 - Reb.Cabin
@Reb.Cabin,VAL 是在哪里定义的?或者你是指 val - Michael Dorst

8
作为进一步的思考,如果您想在缩减方面更加明确(如果您正在进行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

当您转向更复杂的编译器前端时,构建AST可以帮助您这样做,以便在遍历树时具有更好的元数据,并且您还可以增加预语义类型的翻译。然后,它归结为您的叶子生成,例如ID将词素洗入正确的标量有效载荷。

这不是完整的解释,但您可以了解到这个想法。

希望这对您未来的Bison / Lex前端有所帮助,祝你好运!


2
你能再解释得详细一点吗?我还不理解 %type 是怎么用的。 - Jaseem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接