带有 flex 和 bison 的计算器

Calculator with flex and bison

我正在用 flex 和 bison 做一个简单的计算器,当我编译它时它告诉我“$1 of ... has no declared type” 我必须打印表达式的类型及其结果。 表达式的类型可以是浮点数、整数或字符串。 这是我的野牛代码:

%{    
    #include <stdio.h>    
    #include <stdlib.h>    
    #include <math.h>    
    #include <symtab.h>    
    extern int yylex(void);    
    extern char *yytext;    
    extern int nlines;    
    extern FILE *yyin;    
    void yyerror(char *s);    
%}    

%union {    
    char *str;    
}    
%union{    
    struct{    
        char *lexema;    
        int lenght;    
        int line;    
    }ident;    
}    
%union{    
    struct{    
        int integer;    
        float real;    
        char *string;    
        int type;    
        }num    
}    
%token <num> IDENT    
%token <num> LIT_INT    
%token <num> LIT_FLOAT    
%token <num> CADENA    
%token PARENTESIS1    
%token PARENTESIS2    
%token OP_SUM    
%token OP_REST    
%token OP_MULT    
%token OP_DIV    
%token OP_MOD    
%token OP_POW    
%token ASSIGN    

%type <num> expr    
%type <num> term    
%type <num> factor    
%type <num> primary    
%type <num> linea    

%%    
linea   :   IDENT ASSIGN expr '\n'  {sym_enter(,);}    
        |   OP_SUM expr '\n'    {if(.type==0) {    
                            printf("El valor es %d. \n", .integer);    
                        } else if(.type==1) {    
                            printf("El valor es %f. \n", .real);    
                        }}    
        |   OP_REST expr '\n'   {if(.type==0) {    
                            printf("El valor es %d. \n", -.integer);    
                        } else if(.type==1) {    
                            printf("El valor es %f. \n", -.real);    
                        }}    
        |   expr '\n'   {if(.type==0) {    
                            printf("El valor es %d. \n", .integer);    
                        } else if(.type==1) {    
                            printf("El valor es %f. \n", .real);    
                        }}    
        ;    
expr    :   expr OP_SUM term    {if(.type==0 && .type==0) {    
                                            $$.type=0;    
                                            $$.integer=+;    
                                    } else if(.type==1 && .type==1) {    
                                        $$.type=1;    
                                        $$.real=+;    
                                    } else if(.type==0 $$ .type==1 {    
                                        $$.type=1;    
                                        $$.real=+;    
                                    } else if(.type==1 && .type==0) {    
                                        $$.type=0;    
                                        $$.real=+;    
                                    }}    
        |   expr OP_REST term   {if(.type==0 && .type==0) {    
                                            $$.type=0;    
                                            $$.integer=-;    
                                    } else if(.type==1 && .type==1) {    
                                        $$.type=1;    
                                        $$.real=-;    
                                    } else if(.type==0 $$ .type==1 {   
                                        $$.type=1;    
                                        $$.real=-;    
                                    } else if(.type==1 && .type==0) {    
                                        $$.type=0;    
                                        $$.real=-;    
                                    }}    
        |   OP_SUM term         {$$=;}    
        |   OP_REST term        {$$=-;}    
        |   term                {$$=;}    
        ;    
term    :   term OP_MULT factor {if(.type==0 && .type==0) {    
                                            $$.type=0;    
                                            $$.integer=*;    
                                    } else if(.type==1 && .type==1) {    
                                        $$.type=1;    
                                        $$.real=*;    
                                    } else if(.type==0 $$ .type==1 {    
                                        $$.type=1;    
                                        $$.real=*;    
                                    } else if(.type==1 && .type==0) {    
                                        $$.type=0;    
                                        $$.real=*;    
                                    }}    
        |   term OP_DIV factor {if(.type==0 && .type==0) {    
                                            $$.type=0;    
                                            $$.integer=/;    
                                    } else if(.type==1 && .type==1) {    
                                        $$.type=1;    
                                        $$.real=/;    
                                    } else if(.type==0 $$ .type==1 {    
                                        $$.type=1;    
                                        $$.real=/;    
                                    } else if(.type==1 && .type==0) {    
                                        $$.type=0;   
                                        $$.real=/;    
                                    }}    
        |   term OP_MOD factor {if(.type==0 && .type==0) {    
                                            $$.type=0;    
                                            $$.integer=%;    
                                    } else if(.type==1 && .type==1) {    
                                        $$.type=1;    
                                        $$.real=%;    
                                    }}    
        |   factor              {$$=;}    
        ;    
factor  :   primary             {$$=;}    
        |   primary OP_POW factor   {if(.type==0 && .type==0) {    
                                            $$.type=0;    
                                            $$.integer=Math.pow(,);    
                                    } else if(.type==1 && .type==1) {    
                                        $$.type=1;    
                                        $$.real=Math.pow(,)    
                                    }}    
        ;    
primary :   PARENTESIS1 expr PARENTESIS2    {$$=;}    
        |   PARENTESIS1 OP_REST expr PARENTESIS2    {$$=-;}    
        |   PARENTESIS1 OP_SUM expr PARENTESIS2 {$$=;}    
        |   LIT_INT {$$=inicializarEntero();}    
        |   LIT_FLOAT   {$$=inicializarReal();}    
        |   CADENA  {$$=;}    
        |   IDENT   {sym_lookup(,$$);}    
        ;    

%%    

num* inicializarReal(float real) {    
    num *n;    
    n=(num *)malloc(sizeof(int)+sizeof(float));    
    *n.real=real;    
    *n.type=1;    
    return n;    
}    
num* inicializarEntero(int entero) {    
    num *n;    
    n=(num *)malloc(2*sizeof(int));    
    *n.integer=entero;    
    *n.type=0;    
    return n;    
}    

void yyerror(char *s)    
{    
    printf("Error %s",s);    
}    
int main(int argc,char **argv)    
{
    if (argc>1)    
        yyin=fopen(argv[1],"rt");    
    else    
        yyin=stdin;    
    yyparse();    
    printf("FIN del Analisis. Entrada CORRECTA\n");    
    printf("Numero lineas analizadas: %d\n", nlines);    
    return 0;    
}

在寻求错误消息的解释时引用 complete 错误消息并指出它适用于哪一行总是有帮助的。

所以这里只是其中一行会触发与问题中的错误类似的错误。无疑还有更多。

OP_SUM expr '\n'    {if(.type==0) ...

这里,</code>指的是第一个符号(<code>OP SUM)的语义值; </code> 将引用第二个符号 (<code>expr)。 OP_SUM 没有声明类型,这不足为奇,因为它不表示具有值的符号。

显然,目的是使用 expr 的语义值,即