bison / flex:计算器将double值解释为整数,因此我添加了#define YYSTYPE double,但是我遇到了多个编译错误

问题描述 投票:0回答:1

我正在使用flex和bison实现计算器,但是将double值解释为整数,然后我在互联网上寻找答案,我意识到错误可能是bison将数字解释为整数,所以如果我输入“ 1.2”在* yylval = atof(yytext)中为1而不是1.2。因此,我尝试在parser.ypp中添加#define YYSTYPE double,但出现编译错误。我知道有几个类似的问题,但没有一个真正帮助过我。这是我的lex和ypp文件以及编译错误。提前致谢。

lexer.lex:

%option noyywrap
%option noinput
%option nounput

%{
    #include <iostream>
    #include <cstdlib>
    #include <string>
    #include <fstream>

    #include "parser.tab.hpp"

%}

%%

[0-9]+([.][0-9]+)? {
    *yylval = atof(yytext);
        return NUMBER;
}



sin {
    return SIN;
}

cos {
    return COS;
}

tan {
    return TG;
}

tg {
    return TG;
}

ctan {
    return CTG;
}

ctg {
    return CTG;
}

asin {
    return ASIN;
}

acos {
    return ACOS;
}

atan {
    return ATG;
}

actan {
    return ACTG;
}

ln {
    return LN;
}

log {
    return LOG;
}

exp {
    return EXP;
}

sqrt {
    return SQRT;
}

abs {
    return ABS;
}

mod {
    return MOD;
}

[a-z] {
    return VARIABLE;
}

[-+*/^()%!,] {
    return *yytext;
}


[ \t\n] ;

. {

}

parser.ypp:


%{

#define YYSTYPE double


#include <iostream>
#include <cstdlib>
#include <string>
#include <cmath>

 bool indicator_calculating_value ;

extern int yylex();

void yyerror(double *return_value, std::string s);

%}




%parse-param  { double *return_value}

%left '+' '-'
%left '*' '/' '%'
%left SIN COS TG CTG ASIN ACOS ATG ACTG LN LOG MOD
%left UMINUS
%left '^' EXP SQRT
%left ABS
%left '!'


%type <double> E
%token <double> NUMBER
%token <char> VARIABLE;
%start pocetak

%%
pocetak
    : E {
       *return_value = $1;

    };

E   
    : E '+' E {
        if (indicator_calculating_value) {
            $$ = $1 + $3;
        }
    } 
    | E '*' E {

        if (indicator_calculating_value) {
            $$ = $1 * $3;
        }
    }
    | E '-' E {
        if (indicator_calculating_value) {
            $$ = $1 - $3;
        }
    }
    | E '/' E {

        if(indicator_calculating_value) {
            if ($3 == 0) {
                yyerror(0, "divide by zero");
            }
            $$ = $1 / $3;
        }
    }
    | MOD '(' E ',' E ')' {
        if(indicator_calculating_value) {
            if ($5 == 0) {
                yyerror(0, "divide by zero");
            }
            $$ = static_cast<int>($3) % static_cast<int>($5);
        }
    }
    | SIN '(' E ')' {
        if(indicator_calculating_value) {
            $$ = sin($3);
        }
    }
    | COS '(' E ')' {
        if(indicator_calculating_value) {
            $$ = cos($3);
        }
    }
    | TG '(' E ')' {
        if(indicator_calculating_value) {
            $$ = tan($3);
        }
    }
    | CTG '(' E ')' {
        if(indicator_calculating_value) {
            $$ = 1 / tan($3);
        }
    }
    | ASIN '(' E ')' {
        if(indicator_calculating_value) {
            $$ = asin($3);
        }
    }
    | ACOS '(' E ')' {
        if(indicator_calculating_value) {
            $$ = acos($3);
        }
    }       
    | ATG '(' E ')' {
        if(indicator_calculating_value) {
            $$ = atan($3);
        }
    }
    | ACTG '(' E ')' {
        if(indicator_calculating_value) {
            $$ = 1 / atan($3);
        }
    }
    | LN '(' E ')' {
        if(indicator_calculating_value) {
            $$ = log($3);
        }
    }
    | LOG '(' E ',' E ')' {
        if(indicator_calculating_value) {
            $$ = log($5) / log($3);
        }
    }
    | EXP '(' E ')' {
        if(indicator_calculating_value) {
            $$ = exp($3);
        }
    }
    | SQRT '(' E ')' {
        if(indicator_calculating_value) {
            $$ = sqrt($3);
        }
    }
    | E '^' E {
        if(indicator_calculating_value) {
            $$ = pow($1, $3);
        }
    }
    | '-' E %prec UMINUS {
        if(indicator_calculating_value) {
            $$ = -$2;
        }
    } 
    | ABS '(' E ')' {
        if(indicator_calculating_value) {
            $$ = fabs($3);
        }
    }
    | E '!' {
        if(indicator_calculating_value) {
            $$ = 1;
            for (int i = 1; i <= static_cast<int>($1); i++) {
                $$ = $$ * i;
            }
        }
    }
    | '(' E ')' {
        if(indicator_calculating_value) {
            $$ = $2;
        }
    }
    | NUMBER {
        if(indicator_calculating_value) {
            $$ = $1;
        }
    }
    | VARIABLE {

    }
    ;
%%

void yyerror(double *return_value, std::string s)
{
   std::cout << s << std::endl;

}

int main() {

    indicator_calculating_value = true;

    double value = 0.0;
    yyparse(&value);

    std::cout << value << std::endl;



    return 0;
}








错误:

make
bison -d -v parser.ypp
g++ -Wall -L/usr/local/lib -lmgl-qt5 -lmgl -lm  -c -o parser.tab.o parser.tab.cpp
parser.ypp: In function ‘int yyparse(double*)’:
parser.ypp:42:34: error: expected unqualified-id before ‘double’
        *return_value = $1;
                                  ^     
parser.ypp:42:34: error: expected ‘)’ before ‘double’
parser.ypp:49:20: error: expected unqualified-id before ‘double’
             $$ = $1 + $3;
                    ^~~~~~
parser.ypp:49:20: error: expected ‘)’ before ‘double’
parser.ypp:55:20: error: expected unqualified-id before ‘double’
             $$ = $1 * $3;
                    ^~~~~~
parser.ypp:55:20: error: expected ‘)’ before ‘double’
parser.ypp:60:20: error: expected unqualified-id before ‘double’
             $$ = $1 - $3;
                    ^~~~~~
parser.ypp:60:20: error: expected ‘)’ before ‘double’
parser.ypp:66:27: error: expected unqualified-id before ‘double’
             if ($3 == 0) {
                           ^     
parser.ypp:66:27: error: expected ‘)’ before ‘double’
parser.ypp:69:20: error: expected unqualified-id before ‘double’
             $$ = $1 / $3;
                    ^~~~~~
parser.ypp:69:41: error: expected unqualified-id before ‘double’
             $$ = $1 / $3;
                                         ^     
parser.ypp:69:41: error: expected ‘)’ before ‘double’
parser.ypp:69:68: error: expected ‘)’ before ‘;’ token
             $$ = $1 / $3;
                                                                    ^
parser.ypp:74:28: error: expected unqualified-id before ‘double’
             if ($5 == 0) {
                            ^     
parser.ypp:74:28: error: expected ‘)’ before ‘double’
parser.ypp:77:20: error: expected unqualified-id before ‘double’
             $$ = static_cast<int>($3) % static_cast<int>($5);
                    ^~~~~~
parser.ypp:77:58: error: expected unqualified-id before ‘double’
             $$ = static_cast<int>($3) % static_cast<int>($5);
                                                          ^~~~  
parser.ypp:77:58: error: expected ‘)’ before ‘double’
parser.ypp:77:105: error: expected ‘)’ before ‘;’ token
             $$ = static_cast<int>($3) % static_cast<int>($5);
                                                                                                         ^
parser.ypp:77:105: error: expected ‘)’ before ‘;’ token
parser.ypp:82:20: error: expected unqualified-id before ‘double’
             $$ = sin($3);
                    ^~~~~~
parser.ypp:82:20: error: expected ‘)’ before ‘double’
parser.ypp:87:20: error: expected unqualified-id before ‘double’
             $$ = cos($3);
                    ^~~~~~
parser.ypp:87:20: error: expected ‘)’ before ‘double’
parser.ypp:92:20: error: expected unqualified-id before ‘double’
             $$ = tan($3);
                    ^~~~~~
parser.ypp:92:20: error: expected ‘)’ before ‘double’
parser.ypp:97:20: error: expected unqualified-id before ‘double’
             $$ = 1 / tan($3);
                    ^~~~~~
parser.ypp:97:20: error: expected ‘)’ before ‘double’
parser.ypp:102:20: error: expected unqualified-id before ‘double’
             $$ = asin($3);
                    ^~~~~~
parser.ypp:102:20: error: expected ‘)’ before ‘double’
parser.ypp:107:20: error: expected unqualified-id before ‘double’
             $$ = acos($3);
                    ^~~~~~
parser.ypp:107:20: error: expected ‘)’ before ‘double’
parser.ypp:112:20: error: expected unqualified-id before ‘double’
             $$ = atan($3);
                    ^~~~~~
parser.ypp:112:20: error: expected ‘)’ before ‘double’
parser.ypp:117:20: error: expected unqualified-id before ‘double’
             $$ = 1 / atan($3);
                    ^~~~~~
parser.ypp:117:20: error: expected ‘)’ before ‘double’
parser.ypp:122:20: error: expected unqualified-id before ‘double’
             $$ = log($3);
                    ^~~~~~
parser.ypp:122:20: error: expected ‘)’ before ‘double’
parser.ypp:127:20: error: expected unqualified-id before ‘double’
             $$ = log($5) / log($3);
                    ^~~~~~
parser.ypp:127:20: error: expected ‘)’ before ‘double’
parser.ypp:132:20: error: expected unqualified-id before ‘double’
             $$ = exp($3);
                    ^~~~~~
parser.ypp:132:20: error: expected ‘)’ before ‘double’
parser.ypp:137:20: error: expected unqualified-id before ‘double’
             $$ = sqrt($3);
                    ^~~~~~
parser.ypp:137:20: error: expected ‘)’ before ‘double’
parser.ypp:142:20: error: expected unqualified-id before ‘double’
             $$ = pow($1, $3);
                    ^~~~~~
parser.ypp:142:20: error: expected ‘)’ before ‘double’
parser.ypp:147:20: error: expected unqualified-id before ‘double’
             $$ = -$2;
                    ^~    
parser.ypp:147:20: error: expected ‘)’ before ‘double’
parser.ypp:152:20: error: expected unqualified-id before ‘double’
             $$ = fabs($3);
                    ^~~~~~
parser.ypp:152:20: error: expected ‘)’ before ‘double’
parser.ypp:157:20: error: expected unqualified-id before ‘double’
             $$ = 1;
                    ^     
parser.ypp:157:20: error: expected ‘)’ before ‘double’
parser.ypp:158:62: error: expected unqualified-id before ‘double’
             for (int i = 1; i <= static_cast<int>($1); i++) {
                                                              ^     
parser.ypp:158:62: error: expected ‘)’ before ‘double’
parser.ypp:158:70: error: expected ‘)’ before ‘;’ token
             for (int i = 1; i <= static_cast<int>($1); i++) {
                                                                      ^
parser.ypp:159:24: error: expected unqualified-id before ‘double’
                 $$ = $$ * i;
                        ^~~~~ 
parser.ypp:159:24: error: expected ‘)’ before ‘double’
parser.ypp:165:20: error: expected unqualified-id before ‘double’
             $$ = $2;
                    ^     
parser.ypp:165:20: error: expected ‘)’ before ‘double’
parser.ypp:170:20: error: expected unqualified-id before ‘double’
             $$ = $1;
                    ^     
parser.ypp:170:20: error: expected ‘)’ before ‘double’
Makefile:15: recipe for target 'parser.tab.o' failed
make: *** [parser.tab.o] Error 1
c++ parsing bison flex-lexer
1个回答
1
投票

您的野牛文件定义了两种不同类型的符号:

%type <double> E
%token <double> NUMBER
%token <char> VARIABLE;

((第三行末尾的分号是错误的,尽管我认为野牛只会忽略它。)

bison manual中所述,最常见的实现方法是使用%union野牛声明,该声明将YYSTYPE声明为C并集。这与使用预处理器将#define YYSTYPE作为单一类型不兼容。

如果使用%union声明,则为YYSTYPE的每个变体指定C类型和标记。然后放在尖括号之间的是tag,而不是类型。例如,

%union {
     double number;
     char id;
}
%token <number> NUMBER

[使用该声明,野牛将声明一个具有两个名为unionnumber的成员的id类型。通过附加成员选择器,它将自动使$n引用正确的成员(如果符号$n所指的类型已知)。换句话说,如果$1指向NUMBER,野牛将在生成的代码中将其替换为stack[top - 2 + 1].number。 (如果没有%union和类型声明,则替换将类似于stack[top - 2 + 1]。)

野牛不需要您使用%union。如果您不这样做,但仍然声明令牌和非终结符的类型,那么bison会假设您知道自己在做什么,并且已经以某种方式声明了YYSTYPE作为复合类型。它将执行完全相同的替换,将成员选择器添加到引用中以使用已知类型的堆栈值。

因此,在您的情况下,您已声明%type <double> E,因此在$1指向符号$1的动作中,例如E,野牛将替换stack[top - 4 + 1].double

当然,这将导致编译器阻塞。 double是保留字,不能用作复合成员名称,并且无论如何YYSTYPE是标量(double),因为这是您定义它的方式。

您尚未尝试编译扫描仪,但是在那里您会遇到类似的问题。显然,YYSTYPE在扫描器和解析器中必须是相同的类型,它们是独立的C转换单元。如果您使用了%union声明,那么bison会将C union放入生成的标头中,您在生成的扫描器中将其标为#include。这样可以保证一致性。如果不使用%union,则必须确保扫描仪具有正确的定义。

由于您在flex文件中不执行任何操作来声明YYSTYPE,因此生成的代码将回退到int。它通过包含如下代码块来做到这一点:

#ifndef YYSTYPE
#define YYSTYPE int
#endif

《野牛手册》包含许多简单的示例。除了我在此提供的选项外,还有很多其他选择,建议您花一些时间阅读本手册。

© www.soinside.com 2019 - 2024. All rights reserved.