Flex和Bison似乎不匹配

Flex和Bison似乎不匹配,bison,flex-lexer,Bison,Flex Lexer,我正在尝试构建一个简单的计算器,比如键入一个算术表达式,然后按Enter键解析表达式并计算结果 下面的代码(只是野牛)是一个朋友给我的: %{ #include<stdio.h> #include <math.h>

我正在尝试构建一个简单的计算器,比如键入一个算术表达式,然后按Enter键解析表达式并计算结果

下面的代码(只是野牛)是一个朋友给我的:

%{                
   #include<stdio.h>                                                                   
   #include <math.h>                                                       
   #define YYSTYPE double

   extern int line_number;                                                            
   int line_number=0;                                                                     
void yyerror(char *err)
{
   printf("Error: %s\n", err);
}
%}                                                                                   

%token NUMBER        /* define token type for numbers */
%token PLUS
%token MINUS
%token MULT
%token DIV
%token NEWLINE
%token LPAR
%token RPAR

%%     /* Bison grammar rules */
input   : /* empty production to allow an empty input */
        | line input  
        ;
line    : expr NEWLINE   { printf("Result is %f\n", $1); }
expr    : expr PLUS term   { $$ = $1 + $3; }
        | expr MINUS term   { $$ = $1 - $3; }
        | term            { $$ = $1; }
        ;
term    : term MULT factor { $$ = $1 * $3; }
        | term DIV factor { $$ = $1 / $3; }
        | factor          { $$ = $1; }
        ;
factor  : LPAR expr RPAR    { $$ = $2; }
        | NUMBER          { $$ = $1; }
        ;
;                                                                                    
%%                                                                                   

int yylex( void ) {
    int c = getchar();      /* read from stdin */
    if (c < 0) return 0;        /* end of the input*/
    while ( c == ' ' || c == '\t' ) c = getchar( );
    if ( isdigit(c) || c == '.' ) {
    ungetc(c, stdin);    /* put c back into input */
    scanf_s ("%lf", &yylval); /* get value using scanf */
    return NUMBER;       /* return the token type */
    }
    if(c=='+')
        return PLUS;
    if(c=='-')
        return MINUS;
    if(c=='*')
        return MULT;
    if(c=='/')
        return DIV;
    if(c=='\n')
        return NEWLINE;
    if(c=='(')
        return LPAR;
    if(c==')')
        return RPAR;
    return c; /* anything else... return char itself */
}

main ()                                                                              
{
  yyparse ();
}
计算y:

%{
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define YYSTYPE double

%}

%token NUM
%token PLUS
%token MINUS
%token MUL
%token DIV
%token LP
%token RP
%token NL

%%

Input   :
    | Line Input
    ;

Line    : Exp NL        { printf("Result = %f\n", $1); }


Exp : Exp PLUS Term     { $$ = $1 + $3; }
    | Exp MINUS Term    { $$ = $1 - $3; }
    | Term          { $$ = $1; }
    ;

Term    : Term MUL Fact     { $$ = $1 * $3; }
    | Term DIV Fact     { $$ = $1 / $3; }
    | Fact          { $$ = $1; }
    ;

Fact    : LP Exp RP         { $$ = $2; }
    | NUM           { $$ = $1; }
    ;

%%
int yyerror(char *err)
{
   printf("Error: %s\n", err);
}

int main()
{
    printf("Hello\n");
    yyparse();
}

我哪里出错了?

这里有两个问题

首先,您指定:

%option never-interactive
一旦您这样做了,您就不应该期望能够以交互方式使用该程序
never interactive
有效地保证了程序不会以交互方式使用,它允许
flex
生成稍微高效的代码,缓冲输入,而不是逐个字符读取。因此,在键入大量表达式或通过输入文件结束标记终止程序之前,您不会看到任何输出

第二个问题是,您没有在
calc.l
中尽早定义
YYSTYPE

%{
#include "calc.tab.h"
#include "stdlib.h"
#define YYSTYPE double
%}
yylval
calc.tab.h
中声明为
YYSTYPE-yylval;如果
YYSTYPE
未定义为宏(当包含
calc.tab.h
时),则将其类型定义为
int
,其效果是将
yylval
声明为flex生成的C文件中的
int
。但是,在由
bison
生成的C文件中,
yylval
被声明为
double
。这是未定义的行为,gcc不会检测到,因为这两个翻译单元是独立编译的,链接器对类型一无所知

该错误的后果是打印的结果将不正确。(它可能打印为0.0,但由于它是未定义的行为,因此任何结果都是可能的。)

因此,您需要将
#define
放在
#include
之前:

%{
#define YYSTYPE double
#include <stdlib.h>
#include <unistd.h>
#include "calc.tab.h"
%}
%{
#定义YYSTYPE双精度
#包括
#包括
#包括“计算表h”
%}

你太棒了,非常感谢!!在您回复之前,我确实尝试过通过文件提供输入,但我认为所有数字都是0.0,除非我更改整个程序,将它们视为整数。你能告诉我除了
ctrl-d
,还有什么方法可以输入文件结束标记吗?@Maverick:输入文件结束标记的唯一方法是ctrl-d。我建议您删除
从不交互
选项;执行时间的差异很小。
%{
#include "calc.tab.h"
#include "stdlib.h"
#define YYSTYPE double
%}
%{
#define YYSTYPE double
#include <stdlib.h>
#include <unistd.h>
#include "calc.tab.h"
%}