C++ bison/flex:计算器将双精度值解释为整数,因此我添加了#define YYSTYPE double,但我发现了多个编译错误
我正在使用flex和bison实现计算器,但双值被解释为整数,然后我在互联网上寻找答案,我意识到错误可能是bison将数字解释为整数,所以如果我在*yylval=atof(yytext)中输入“1.2”,则是1而不是1.2。因此,我尝试在parser.ypp中添加#define YYSTYPE double,但出现编译错误。 我知道有几个类似的问题,但都没有真正帮助我。 这是我的lex和ypp文件以及我得到的编译错误C++ bison/flex:计算器将双精度值解释为整数,因此我添加了#define YYSTYPE double,但我发现了多个编译错误,c++,parsing,bison,flex-lexer,C++,Parsing,Bison,Flex Lexer,我正在使用flex和bison实现计算器,但双值被解释为整数,然后我在互联网上寻找答案,我意识到错误可能是bison将数字解释为整数,所以如果我在*yylval=atof(yytext)中输入“1.2”,则是1而不是1.2。因此,我尝试在parser.ypp中添加#define YYSTYPE double,但出现编译错误。 我知道有几个类似的问题,但都没有真正帮助我。 这是我的lex和ypp文件以及我得到的编译错误 提前谢谢 lexer.lex: %option noyywrap %optio
提前谢谢
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] ;
. {
}
%选项noyywrap
%无输入选项
%期权看跌期权
%{
#包括
#包括
#包括
#包括
#包括“parser.tab.hpp”
%}
%%
[0-9]+([.][0-9]+)? {
*yylval=atof(yytext);
返回号码;
}
罪{
归罪;
}
因为{
返回COS;
}
棕褐色{
返回TG;
}
甘油三酯{
返回TG;
}
ctan{
返回CTG;
}
ctg{
返回CTG;
}
阿辛{
返回ASIN;
}
acos{
返回ACOS;
}
阿坦{
返回ATG;
}
阿克坦{
返回ACTG;
}
项次{
返回项次;
}
日志{
返回日志;
}
经验{
返回经验;
}
sqrt{
返回SQRT;
}
腹肌{
返回ABS;
}
国防部{
返回模式;
}
[a-z]{
返回变量;
}
[-+*/^()%!,] {
返回*文本;
}
[\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;
}
%{
#定义YYSTYPE双精度
#包括
#包括
#包括
#包括
布尔指示符计算值;
extern int yylex();
无效错误(双*返回值,标准::字符串s);
%}
%解析参数{double*返回值}
%左'+''-'
%左'*''/''%
%左单轴TG CTG ASIN ACOS ATG ACTG LN LOG MOD
%左耳门
%左“^”EXP SQRT
%左腹肌
%左‘!’
%E型
%令牌号
%令牌变量;
%启动pocetak
%%
波切塔克
:E{
*返回值=1美元;
};
E
:E'+'E{
if(指示灯\计算\值){
$$ = $1 + $3;
}
}
|E'*'E{
if(指示灯\计算\值){
$$ = $1 * $3;
}
}
|E'-'E{
if(指示灯\计算\值){
$$ = $1 - $3;
}
}
|E'/'E{
if(指示灯\计算\值){
如果($3==0){
yyerror(0,“除以零”);
}
$$ = $1 / $3;
}
}
|MOD'('E','E')'{
if(指示灯\计算\值){
如果($5==0){
yyerror(0,“除以零”);
}
$$=静态演员阵容($3)%静态演员阵容($5);
}
}
|SIN'('E')'{
if(指示灯\计算\值){
$$=sin(3美元);
}
}
|COS'('E')'{
if(指示灯\计算\值){
$$=cos(3美元);
}
}
|TG'('E')'{
if(指示灯\计算\值){
$$=tan(3美元);
}
}
|CTG'('E')'{
if(指示灯\计算\值){
$$=1/吨(3美元);
}
}
|ASIN'('E')'{
if(指示灯\计算\值){
$$=asin(3美元);
}
}
|ACOS'('E')'{
if(指示灯\计算\值){
$$=ACO(3美元);
}
}
|ATG'('E')'{
if(指示灯\计算\值){
$$=atan(3美元);
}
}
|ACTG'('E')'{
if(指示灯\计算\值){
$$=1/澳大利亚元(3美元);
}
}
|LN'('E')'{
if(指示灯\计算\值){
$$=对数($3);
}
}
|日志'('E','E')'{
if(指示灯\计算\值){
$$=对数($5)/对数($3);
}
}
|EXP'('E')'{
if(指示灯\计算\值){
$$=exp(3美元);
}
}
|SQRT'('E')'{
if(指示灯\计算\值){
$$=平方米(3美元);
}
}
|"^"E{
if(指示灯\计算\值){
$$=战俘($1,$3);
}
}
|“-”E%前白蛋白{
if(指示灯\计算\值){
$$ = -$2;
}
}
|ABS'('E')'{
if(指示灯\计算\值){
$$=晶圆厂(3美元);
}
}
|E'!'{
if(指示灯\计算\值){
$$ = 1;
对于(inti=1;i,bison文件定义了两种不同类型的符号:
%type <double> E
%token <double> NUMBER
%token <char> VARIABLE;
通过该声明,bison将声明一个包含两个名为number
和id
的成员的union
类型。它将自动使$n
引用正确的成员(如果$n
引用的符号具有已知类型)通过附加成员选择器。换句话说,如果$1
引用了一个数字
,bison将在生成的代码中用类似于堆栈[top-2+1]的东西替换它。数字
(如果没有%union
和类型声明,替换将类似于堆栈[top-2+1]
)
Bison不要求您使用%union
。如果您不这样做,并且您仍然为您的令牌和非终端声明类型,Bison将假定您知道您在做什么,并且您以某种方式将YYSTYPE
声明为复合类型。它将执行完全相同的替换,向堆栈的引用添加成员选择器具有已知类型的值
因此,在您的例子中,您已经声明了%typee
,因此bison将在$1
引用符号E
的动作中替换$1
,类似于堆栈[top-4+1]。double
当然,这会导致编译器阻塞。double
是一个保留字,不能用作复合成员名,而且无论如何YYSTYPE
是一个标量(一个double
),因为这是您定义它的方式
您还没有尝试编译扫描仪,但在那里您将遇到类似的问题
%type <double> E
%token <double> NUMBER
%token <char> VARIABLE;
%union {
double number;
char id;
}
%token <number> NUMBER
#ifndef YYSTYPE
#define YYSTYPE int
#endif