【发布时间】:2026-02-12 22:45:02
【问题描述】:
我正在使用 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
【问题讨论】:
-
在一些与你得到的错误无关的注释上,我建议你阅读生成的头文件
"parser.tab.hpp",因为这样你会看到yylval不是一个指针。此外,您链接的库应该是 last 在您构建时(或至少在所有源文件和目标文件之后),并且您不需要在生成对象时添加链接器库文件。
标签: c++ parsing bison flex-lexer