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

bor*_*der 4 yacc lex bison 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}

%%

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

%%

int yywrap(void)
{
  return 1;
}
Run Code Online (Sandbox Code Playgroud)

我的野牛代码看起来像这样

%{
#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;
}
Run Code Online (Sandbox Code Playgroud)

这不会产生正确的输出.即使lexer将字符串解释为双精度并将它们正确地存储在yylval变量中,当解析器将数字相加时,它只会吐出0.0000.但是,如果我yylval通过%union只包含一个double lf_val;变量的指令声明为联合,并将atof输出存储yylval在词法分析器的这个字段中,%token <lf_val> NUMBER并且%type <lf_val> expr在解析器中声明,那么事情似乎有效.

但是,为什么不的简单方法typedef荷兰国际集团YYSTYPE的工作?我也试过了#define YYSTYPE double.那也行不通.

yro*_*eht 5

关于%code,Bison的文件说明:

%code requires [...] is the best place to override Bison's default YYSTYPE
and YYLTYPE definitions.
Run Code Online (Sandbox Code Playgroud)

所以juste在你的野牛文件的顶部添加以下内容:

%code requires
  {
    #define YYSTYPE double
  }
Run Code Online (Sandbox Code Playgroud)

您还需要删除以下两行:

typedef double YYSTYPE;
#define YYSTYPE_IS_DECLARED
Run Code Online (Sandbox Code Playgroud)

请注意,据我所知,YYSTYPE_IS_DECLARED在任何地方都没有记录,因此仅供Bison内部使用.

如果您不熟悉使用Bison %code指令而不是简单的%{序言,您可能会发现本文档的这一部分很有趣.