C 为什么我在flex和bison中的程序不是';不行吗?正反函数计算器
我有这个程序,但不起作用,谁能帮我?当我输入2+3并输入时,.exe文件突然关闭。我不知道出了什么问题,但我需要尽快解决这个问题,希望你能帮助我。这是lexico.l:C 为什么我在flex和bison中的程序不是';不行吗?正反函数计算器,c,bison,flex-lexer,C,Bison,Flex Lexer,我有这个程序,但不起作用,谁能帮我?当我输入2+3并输入时,.exe文件突然关闭。我不知道出了什么问题,但我需要尽快解决这个问题,希望你能帮助我。这是lexico.l: /* Ejemplo para una pequeña calculadora que permite trabajar con las funciones trigonometricas como el seno y el coseno */ #include <stdio.h> #include <stdl
/* Ejemplo para una pequeña calculadora que permite trabajar
con las funciones trigonometricas como el seno y el coseno */
#include <stdio.h>
#include <stdlib.h>
#include "sintactico.tab.h"
int nlines=0;
%}
DIGITO [0-9]
ID [a-zA-Z][a-zA-Z0-9_]*
%%
{DIGITO}+("."{DIGITO}+)? {//printf("Encontrado TKN_NUM: %f\n",atof(yytext));
yylval.real=atof(yytext);
return(TKN_NUM);}
"=" {//printf("Encontrado TKN_ASIGN: %s\n",yytext);
return(TKN_ASIGN);}
"(" {//printf("Encontrado TKN_PAA: %s\n",yytext);
return(TKN_PAA);}
")" {//printf("Encontrado TKN_PAC: %s\n",yytext);
return(TKN_PAC);}
"cos" {//printf("Encontrado TKN_COS: %s\n",yytext);
return(TKN_COS);}
"sen" {//printf("Encontrado TKN_SEN: %s\n",yytext);
return(TKN_SEN);}
{ID} {//printf("Encontrado TKN_ID: %s\n",yytext);
return(TKN_ID);}
"\n" {nlines++;}
.
%%
/*ejempo para una pequeña calculadora que permite trabajar
三角函数的con las functiones como el seno y el coseno*/
#包括
#包括
#包括“sintactico.tab.h”
int-nlines=0;
%}
DIGITO[0-9]
识别号[a-zA-Z][a-zA-Z0-9]*
%%
{DIGITO}+(“{DIGITO}+)?{//printf(“Encontrado TKN_NUM:%f\n”,atof(yytext));
yylval.real=atof(yytext);
返回值(TKN_NUM);}
“=”{//printf(“密码:%s\n”,yytext);
返回(TKN_ASIGN);}
“({//printf(“Encontrado TKN_PAA:%s\n”,yytext);
返回(TKN_PAA);}
“”{//printf(“Encontrado TKN_PAC:%s\n”,yytext);
返回(TKN_PAC);}
“cos”{//printf(“Encontrado TKN_cos:%s\n”,yytext);
返回(TKN_COS);}
“sen”{//printf(“Encontrado TKN_sen:%s\n”,yytext);
返回(TKN_SEN);}
{ID}{//printf(“Encontrado TKN_ID:%s\n”,yytext);
返回(TKN_ID);}
“\n”{nlines++;}
.
%%
和sintactico.y文件:
%{
/* Ejemplo para una pequeña calculadora que permite trabajar
con funciones trigonometricas como el seno y el coseno */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
extern int yylex(void);
extern char *yytext;
extern int nlines;
extern FILE *yyin;
void yyerror(char *s);
%}
%union
{
float real;
}
%start Calculadora
%token <real> TKN_NUM
%token TKN_ASIGN
%token TKN_PAA
%token TKN_PAC
%token TKN_COS
%token TKN_SEN
%token <real> TKN_ID
%type Calculadora
%type <real> Expresion
%left TKN_MAS TKN_MENOS
%left TKN_MULT TKN_DIV
%%
Calculadora : TKN_ID { printf("El valor de %s es: ", yytext);}
Expresion : TKN_NUM {$$=$1;}|
TKN_PAA Expresion TKN_PAC {$$=$2;}|
TKN_COS TKN_PAA Expresion TKN_PAC {$$=cos($3);}|
TKN_SEN TKN_PAA Expresion TKN_PAC {$$=sin($3);};
%%
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;
}
%{
/*在计算过程中,必须考虑到许可证的性质
三角函数como el seno y el coseno*/
#包括
#包括
#包括
外部内部yylex(无效);
外部字符*文本;
外联线;
外部文件*yyin;
无效错误(字符*s);
%}
%联合
{
浮动真实;
}
%从加尔各拉多拉开始
%令牌TKN_NUM
%令牌TKN\u ASIGN
%代币TKN_PAA
%令牌TKN_PAC
%代币
%代币
%令牌TKN_ID
%加尔各拉多拉型
%类型扩展
%左TKN_MAS TKN_MENOS
%左TKN_MULT TKN_DIV
%%
Calculadora:TKN_ID{printf(“El valor de%s:,yytext);}
表达式:TKN_NUM{$$=$1;}|
TKN_PAA表达式TKN_PAC{$$=$2;}|
TKN_COS TKN_PAA expression TKN_PAC{$$=COS($3);}|
这是一种表达形式{$$=sin($3);};
%%
无效错误(字符*s)
{
printf(“错误%s”,s);
}
int main(int argc,字符**argv)
{
如果(argc>1)
yyin=fopen(argv[1],“rt”);
其他的
yyin=stdin;
yyparse();
printf(“FIN del Analisis.Entrada CORRECTA\n”);
printf(“分析的数字线:%d\n”,nlines);
返回0;
}
怎么了?我对Flex和Bison是新手,很难理解错误
当我输入2+3并输入时,.exe文件突然关闭
这里发生了几件事:
Calculadora
,它的唯一产物是一个TKN\u ID
标记。lexer为给定输入返回的第一个标记将是与2
对应的TKN\u NUM
。将导致分析错误,yyparse()
将返回,程序将很快终止
Expresion
,“2+3”仍然不是有效的输入。TKN_NUM
仍然是第一个令牌。+
将仅由lexer的通配符模式匹配,该模式具有空操作,因此将打印它,但不会生成令牌。然后会有另一个TKN_NUM
,但语法没有规则可以应用于两个连续的TKN_NUM
标记看起来您想要使用变量名,然后需要在lexer中读入一个字符串值,并在bison文件中使用它 您的%联合可能如下所示:
%union
{
char* str;
float real;
}
{DIGITO}+("."{DIGITO}+)? { yylval.real=atof(yytext); return(TKN_NUM); }
= { return TKN_ASIGN; }
\( { return TKN_PAA; }
\) { return TKN_PAC; }
cos { return TKN_COS; }
sen { return TKN_SEN; }
{ID} { yylval.str = strdup(yytext); return TKN_ID; }
\+ { return TKN_MAS; }
\- { return TKN_MENOS; }
\n { nlines++; return '\n'; }
.
Calculadora: { $$ = 0; }
| Calculadora Expresion '\n' { printf("%f\n", $2); }
| Calculadora '\n'
;
同样,您的TNK_ID应该是:
%token <str> TKN_ID
还请注意,现在有+和-以及\n的定义。变量名存储在yylval.str中
Calculadora宁愿这样:
%union
{
char* str;
float real;
}
{DIGITO}+("."{DIGITO}+)? { yylval.real=atof(yytext); return(TKN_NUM); }
= { return TKN_ASIGN; }
\( { return TKN_PAA; }
\) { return TKN_PAC; }
cos { return TKN_COS; }
sen { return TKN_SEN; }
{ID} { yylval.str = strdup(yytext); return TKN_ID; }
\+ { return TKN_MAS; }
\- { return TKN_MENOS; }
\n { nlines++; return '\n'; }
.
Calculadora: { $$ = 0; }
| Calculadora Expresion '\n' { printf("%f\n", $2); }
| Calculadora '\n'
;
对于Expresion
而言,应添加ID、赋值以及加减运算的处理,例如:
Expresion: TKN_NUM { $$=$1; }
| TKN_ID { $$ = get_symbol($1)->value; }
| TKN_ID TKN_ASIGN Expresion { put_symbol($1, $3); $$ = $3; }
| Expresion TKN_MENOS Expresion { $$ = $1 - $3; }
| Expresion TKN_MAS Expresion { $$ = $1 + $3; }
| TKN_PAA Expresion TKN_PAC { $$ = $2; }
| TKN_COS TKN_PAA Expresion TKN_PAC { $$ = cos($3); }
| TKN_SEN TKN_PAA Expresion TKN_PAC { $$ = sin($3); }
;
因为您似乎想要为变量名赋值,所以需要一种符号表。您可以提供void put\u symbol(char*name,float value)
和struct symbol\u entry*get\u symbol(char*name)
的实现。符号条目可以定义为:
struct symbol_entry {
char name[50];
float value;
};
测试
快速测试-一行输入后是计算器的一行输出:
5 + 3
8.000000
a = 5 + 3
8.000000
a = 0.5
0.500000
a
0.500000
b = cos(a)
0.877583
c = b + a
1.377583
c
1.377583
这就是您要找的吗?它打印了行数吗?没有,应用程序刚刚关闭。@Megasaw:我强烈建议您阅读野牛手册中的内容,其中有详细的解释,以便您能够看到正在发生的事情。(不幸的是,仅用英语,但我认为它并不太复杂。)这些示例构建了一个包含函数和变量的完整计算器,但它们一开始很简单,值得花时间来遵循顺序。从长远来看,这将为您节省大量的痛苦。即使我把cos(2)放进去,程序也会突然终止:(而且我不知道如何修复它,我对它是新手,这个程序快把我逼疯了。@megasaw,“cos(2)”对您的程序来说也是无效的输入。同样,您的开始符号是
Calculadora
,唯一可以匹配的令牌序列是一个TKN\u ID
。因此,我必须将#start Calculadora by#start Expresion?@megasaw更改,如果您将开始符号更改为Expresion
,则我希望输入“cos(2)”但是,语法无法解析除此之外的其他输入,因此我希望yyparse()
返回,让您回到我的观点(2)。此外,Expresion
中没有任何内容打印表达式的值。这在Calculadora
中,但是Calculadora
的主体与Expresion
不匹配。非常感谢!