如何使用 bison + flex 编写计算器
How to write a calculator using bison + flex
我正在测试使用 bison 和 flex 实现的计算器示例。文件 "rpn-all-calc2.y" 中的示例代码是:
%{
#define YYSTYPE double
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int yyerror(const char* s);
int yylex(void);
%}
%token NUM
%% /* grammer rules and actions follow */
input: /* empty */
| input line
;
line: '\n'
| exp '\n' { printf("\t%.10g\n", ); }
;
exp: NUM { $$ = ; }
| exp exp '+' { $$ = + ; }
| exp exp '-' { $$ = - ; }
| exp exp '*' { $$ = * ; }
| exp exp '/' { $$ = / ; }
| exp exp '^' { $$ = pow(, ); }
| exp 'n' { $$ = -; }
;
%%
#include <ctype.h>
int yylex(void)
{
int c;
while ((c = getchar()) == ' '||c == '\t') ; /* skip white spaces*/
if (c == '.' || isdigit(c)) /* process numbers */
{
ungetc(c, stdin);
scanf("%lf", &yylval);
printf("value is %lf\n",yylval);
return NUM;
}
if (c == EOF) return 0;
printf("symbol is %c, %d",c,c);
return c; }
int yyerror(const char* s) { printf("%s\n", s); return 0; }
int main(void) { return yyparse(); }
效果很好。
我想使用 flex + bison 来实现这个计算器,如下所示:
文件 "rp.lex":
%option noyywrap
%{
#include "rpn-all-calc3.tab.h"
%}
op [+\-*/^n]+
ws [ \t]+
letter [a-zA-Z]
digit [0-9]+
%%
{letter} REJECT;
{digit} return NUM;
{op}|\n return *yytext;
{ws} /* eat up white spaces */
%%
文件"rpn-all-calc2.y"是:
%{
#define YYSTYPE double
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int yyerror(const char* s);
int yylex(void);
%}
%token NUM
%% /* grammer rules and actions follow */
input: /* empty */
| input line
;
line: '\n'
| exp '\n' { printf("\t%.10g\n", ); }
;
exp: NUM { $$ = ; }
| exp exp '+' { $$ = + ; }
| exp exp '-' { $$ = - ; }
| exp exp '*' { $$ = * ; }
| exp exp '/' { $$ = / ; }
| exp exp '^' { $$ = pow(, ); }
| exp 'n' { $$ = -; }
;
%%
#include <ctype.h>
int main(void) { return yyparse(); }
int yyerror(const char* s) { printf("%s\n", s); return 0; }
编译没有错误:
bison -d rpn-all-calc2.y
flex -o rpn-all-calc3.lex.yy.c rp.lex
gcc *.c -o test -lm
但是当我运行“./test”时,我输入,说:
1 1 +
然后我得到0
无论我输入什么方程式,我总是得到 0。
我的代码有什么问题?
谢谢大家的帮助!!!
在您的 Flex 词法分析器中,您忘记将 yylval 设置为找到的数字。
你可以换行
{digit} return NUM;
至
{digit} { sscanf(yytext, "%lf", &yylval); return NUM; }
我正在测试使用 bison 和 flex 实现的计算器示例。文件 "rpn-all-calc2.y" 中的示例代码是:
%{
#define YYSTYPE double
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int yyerror(const char* s);
int yylex(void);
%}
%token NUM
%% /* grammer rules and actions follow */
input: /* empty */
| input line
;
line: '\n'
| exp '\n' { printf("\t%.10g\n", ); }
;
exp: NUM { $$ = ; }
| exp exp '+' { $$ = + ; }
| exp exp '-' { $$ = - ; }
| exp exp '*' { $$ = * ; }
| exp exp '/' { $$ = / ; }
| exp exp '^' { $$ = pow(, ); }
| exp 'n' { $$ = -; }
;
%%
#include <ctype.h>
int yylex(void)
{
int c;
while ((c = getchar()) == ' '||c == '\t') ; /* skip white spaces*/
if (c == '.' || isdigit(c)) /* process numbers */
{
ungetc(c, stdin);
scanf("%lf", &yylval);
printf("value is %lf\n",yylval);
return NUM;
}
if (c == EOF) return 0;
printf("symbol is %c, %d",c,c);
return c; }
int yyerror(const char* s) { printf("%s\n", s); return 0; }
int main(void) { return yyparse(); }
效果很好。 我想使用 flex + bison 来实现这个计算器,如下所示: 文件 "rp.lex":
%option noyywrap
%{
#include "rpn-all-calc3.tab.h"
%}
op [+\-*/^n]+
ws [ \t]+
letter [a-zA-Z]
digit [0-9]+
%%
{letter} REJECT;
{digit} return NUM;
{op}|\n return *yytext;
{ws} /* eat up white spaces */
%%
文件"rpn-all-calc2.y"是:
%{
#define YYSTYPE double
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int yyerror(const char* s);
int yylex(void);
%}
%token NUM
%% /* grammer rules and actions follow */
input: /* empty */
| input line
;
line: '\n'
| exp '\n' { printf("\t%.10g\n", ); }
;
exp: NUM { $$ = ; }
| exp exp '+' { $$ = + ; }
| exp exp '-' { $$ = - ; }
| exp exp '*' { $$ = * ; }
| exp exp '/' { $$ = / ; }
| exp exp '^' { $$ = pow(, ); }
| exp 'n' { $$ = -; }
;
%%
#include <ctype.h>
int main(void) { return yyparse(); }
int yyerror(const char* s) { printf("%s\n", s); return 0; }
编译没有错误:
bison -d rpn-all-calc2.y
flex -o rpn-all-calc3.lex.yy.c rp.lex
gcc *.c -o test -lm
但是当我运行“./test”时,我输入,说: 1 1 + 然后我得到0 无论我输入什么方程式,我总是得到 0。 我的代码有什么问题? 谢谢大家的帮助!!!
在您的 Flex 词法分析器中,您忘记将 yylval 设置为找到的数字。
你可以换行
{digit} return NUM;
至
{digit} { sscanf(yytext, "%lf", &yylval); return NUM; }