flex/bison将数字解释为浮点数

flex/bison将数字解释为浮点数,bison,yacc,lex,flex-lexer,Bison,Yacc,Lex,Flex Lexer,我正在尝试实现一个flex/bison计算器,它可以进行浮点运算。我的flex代码如下所示 %{ #include "calc.tab.h" #include <stdlib.h> void yyerror(char *s); %} digit [0-9] integer {digit}+ real ({digit}+[.]{digit}*)|({digit}*[.]{digit}+) exp ({integer}|{real})[eE]-?{integer} %% ({in

我正在尝试实现一个flex/bison计算器,它可以进行浮点运算。我的flex代码如下所示

%{
#include "calc.tab.h"
#include <stdlib.h>

void yyerror(char *s);
%}

digit [0-9]
integer {digit}+
real ({digit}+[.]{digit}*)|({digit}*[.]{digit}+)
exp ({integer}|{real})[eE]-?{integer}

%%

({integer}|{real}|{exp}) { yylval = atof(yytext); return NUMBER; }
[-+*/\n]                 { return *yytext; }
[ \t\v\f\r]              { }
.                        { yyerror("Unknown Character"); }

%%

int yywrap(void)
{
  return 1;
}
%{
#include <stdio.h>

typedef double YYSTYPE;
#define YYSTYPE_IS_DECLARED

void yyerror(char *s);
extern char *yytext;
extern int yylineno;
%} 

%token NUMBER

%left '+' '-'
%left '*' '/'

%%

program: program expr '\n' { printf("%g\n", $2); }
       | program '\n'
       |
       ;
expr: expr '+' expr { $$ = $1 + $3; }
    | expr '-' expr { $$ = $1 - $3; }
    | expr '*' expr { $$ = $1 * $3; }
    | expr '/' expr { $$ = $1 / $3; }
    | NUMBER { $$ = $1; }
    ;

%%

void yyerror(char *s)
{
  fprintf(stderr, "error: %s at %s, line %d\n", s, yytext, yylineno);
}

int main(int argc, char *argv[])
{
  yyparse();

  return 0;
}
%{
#包括“计算表h”
#包括
无效错误(字符*s);
%}
数字[0-9]
整数{位}+
实数({digit}+[.]{digit}*)|({digit}*[.]{digit}+)
exp({integer}{real})[eE]-?{integer}
%%
({integer}{real}{exp}){yylval=atof(yytext);返回数字;}
[-+*/\n]{return*yytext;}
[\t\v\f\r]{}
.                        {yyerror(“未知字符”);}
%%
int-yywrap(无效)
{
返回1;
}
我的野牛代码是这样的

%{
#include "calc.tab.h"
#include <stdlib.h>

void yyerror(char *s);
%}

digit [0-9]
integer {digit}+
real ({digit}+[.]{digit}*)|({digit}*[.]{digit}+)
exp ({integer}|{real})[eE]-?{integer}

%%

({integer}|{real}|{exp}) { yylval = atof(yytext); return NUMBER; }
[-+*/\n]                 { return *yytext; }
[ \t\v\f\r]              { }
.                        { yyerror("Unknown Character"); }

%%

int yywrap(void)
{
  return 1;
}
%{
#include <stdio.h>

typedef double YYSTYPE;
#define YYSTYPE_IS_DECLARED

void yyerror(char *s);
extern char *yytext;
extern int yylineno;
%} 

%token NUMBER

%left '+' '-'
%left '*' '/'

%%

program: program expr '\n' { printf("%g\n", $2); }
       | program '\n'
       |
       ;
expr: expr '+' expr { $$ = $1 + $3; }
    | expr '-' expr { $$ = $1 - $3; }
    | expr '*' expr { $$ = $1 * $3; }
    | expr '/' expr { $$ = $1 / $3; }
    | NUMBER { $$ = $1; }
    ;

%%

void yyerror(char *s)
{
  fprintf(stderr, "error: %s at %s, line %d\n", s, yytext, yylineno);
}

int main(int argc, char *argv[])
{
  yyparse();

  return 0;
}
%{
#包括
typedef-double-YYSTYPE;
#定义YYSTYPE_是否已声明
无效错误(字符*s);
外部字符*文本;
外部内部yylineno;
%} 
%令牌号
%左'+''-'
%左'*''/'
%%
程序:程序expr'\n'{printf(“%g\n”,$2);}
|程序'\n'
|
;
expr:expr'+'expr{$$=$1+$3;}
|expr'-'expr{$$=$1-$3;}
|expr'*'expr{$$=$1*$3;}
|expr'/'expr{$$=$1/$3;}
|编号{$$=$1;}
;
%%
无效错误(字符*s)
{
fprintf(标准,“错误:%s位于%s,行%d\n”,s,yytext,yylineno);
}
int main(int argc,char*argv[])
{
yyparse();
返回0;
}
这不会产生正确的输出。即使lexer将字符串解释为double,并将它们正确地存储在
yylval
变量中,但当解析器将数字相加时,它只输出
0.0000
。但是,如果我通过仅由一个
双lf\u val组成的
%union
指令将
yylval
声明为联合
变量,并将
atof
输出存储在lexer中的
yylval
字段中,同时在解析器中声明
%tokennumber
%typeexpr
,一切似乎正常


但是,为什么
typedef
ing
YYSTYPE
的简单方法不起作用呢?我还尝试了
#定义YYSTYPE double
。这也不起作用。

关于
%code
,声明:

因此,只需在bison文件的顶部添加以下内容:

%code requires
  {
    #define YYSTYPE double
  }
您还需要删除这两行:

typedef double YYSTYPE;
#define YYSTYPE_IS_DECLARED
请注意,据我所知,YYSTYPE_声明在任何地方都没有记录,因此仅供野牛内部使用


如果您不熟悉Bison的
%code
指令在简单的
%{
序言中的用法,您可能会发现阅读起来很有趣。

谢谢@yroeht。我注意到在
%code中包含
#define
需要{}
指令在lexer包含的
.h
文件中也生成了YYSTYPE的定义。因此,lexer正在写入一个整数变量,而解析器正在读取double!