带有 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
的语义值,即
我正在用 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
的语义值,即