代码之家  ›  专栏  ›  技术社区  ›  Asaf R

如何解决野牛警告“…没有声明类型”

  •  41
  • Asaf R  · 技术社区  · 15 年前

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

    这意味着什么?我该如何解决?

    2 回复  |  直到 10 年前
        1
  •  40
  •   Joey Adams    12 年前

    定义的联合(%union)不打算直接使用。相反,您需要告诉bison哪个联合体成员被哪个表达式使用。

    这是用 %type directive .

    代码的固定版本是:

    %{
        #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
  •  7
  •   Aiden Bell    15 年前

    进一步考虑,如果您想要更明确地进行缩减(如果您正在进行ast annoation,这很方便),那么您可以创建堆栈值指针,然后自己处理类型值。与标量类型非常相似:

    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,将lexem转换成正确的标量负载。

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

    希望这有助于您的未来野牛/雷克斯前端和…

    祝你好运