gpt4 book ai didi

c++ - bison/flex : calculator interprets double values as integers so I added #define YYSTYPE double, 但我有多个编译错误

转载 作者:太空宇宙 更新时间:2023-11-03 17:25:12 25 4
gpt4 key购买 nike

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

词法分析器.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] ;

. {

}

解析器.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

最佳答案

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

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

(第三行末尾的分号不正确,虽然我认为 Bison 会忽略它。)

正如在 bison manual 中讨论的那样,最常见的实现方式是使用 %union Bison 声明,它将声明 YYSTYPE成为C联盟。这与将预处理器用于 #define YYSTYPE 不兼容。作为单一类型。

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

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

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

Bison 不要求您使用 %union .如果你不这样做并且你仍然为你的 token 和非终端声明类型, Bison 会假设你知道你在做什么并且你已经以某种方式声明了YYSTYPE。作为复合类型。它将执行完全相同的替换,将成员选择器添加到对具有已知类型的堆栈值的引用。

所以在你的例子中,你已经声明了 %type <double> E , 所以 bison 将替换一个 $1在一个 Action 中 $1指代符号 E用类似 stack[top - 4 + 1].double 的东西.

当然,那会导致编译器卡住。 double是保留字,不能作为复合成员名,反正YYSTYPE是一个标量(double),因为这是您定义它的方式。

您还没有尝试编译您的扫描仪,但您会在那里遇到类似的问题。显然,YYSTYPE扫描器和解析器中的类型必须相同,它们是独立的 C 翻译单元。如果您使用了 %union声明, Bison 会把 C union进入 tje 生成的 header ,你 #include在生成的扫描仪中。这保证了一致性。如果你不使用 %union , 那么您必须确保扫描仪具有正确的定义。

因为您没有在 flex 文件中做任何事情来声明 YYSTYPE ,生成的代码将回退到 int .它通过包含这样的 block 来做到这一点:

#ifndef YYSTYPE
#define YYSTYPE int
#endif

bison 手册包含许多简单示例。选项比我在这里介绍的要多得多,建议您花点时间阅读手册。

关于c++ - bison/flex : calculator interprets double values as integers so I added #define YYSTYPE double, 但我有多个编译错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59518552/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com