I'm trying to pinpoint these error messages, but even when I move code around the error shows up at the same line.
我正在尝试找出这些错误消息,但是即使我在错误中移动代码,也会出现在同一条线上。
Also why am I still getting "calc.y: In function 'int yyparse()':" and "calc.l: In function 'int yylex()':" even though I have it in my calc.y.
还有,为什么我仍然得到“calc.y: In function 'int yyparse()”和“calc.l: In function 'int yylex()”:“即使我在calc.y中有它”。
Error Messages
错误消息
flex calc.l
bison -d calc.y
g++ -o calc calc.tab.c lex.yy.c
calc.y: In function 'int yyparse()':
calc.y:35: error: cannot convert 'double' to 'std::string*' in assignment
calc.tab.c:1490: warning: deprecated conversion from string constant to 'char*'
calc.tab.c:1633: warning: deprecated conversion from string constant to 'char*'
calc.l: In function 'int yylex()':
calc.l:17: error: 'yyerror' was not declared in this scope
calc.l
calc.l
%{
#include <cstdlib>
#include <string>
#include <string.h>
#include "calc.tab.h"
%}
%%
"print" {return print;}
"exit" {return exit_command;}
[0-9]+ {yylval.num = atof(yytext); return number;}
[_[:alpha:]][_[:alnum:]]* {yylval.index = new std::string(yytext); return identifier; }
[ \t] ;
[\n] {return(CR);}
[-()+*/;=] {return yytext[0];}
. {ECHO; yyerror ("unexpected character");}
%%
int yywrap (void) {return 1;}
calc.y
calc.y
%{
void yyerror (char *s);
int yylex(void);
#include <stdio.h> /* C declarations used in actions */
#include <stdlib.h>
#include <string>
#include <string.h>
#include <map>
static std::map<std::string, double> vars;
%}
%union {double num; std::string *index;} /* Yacc definitions */
%start line
%token print
%token CR
%token exit_command
%token <num> number
%token <index> identifier
%type <num> line exp term
%type <index> assignment
%%
/* descriptions of expected inputs corresponding actions */
line : assignment CR {;}
| exit_command CR {exit(EXIT_SUCCESS);}
| print exp CR {printf("Printing %f\n", $2);}
| line assignment CR {;}
| line print exp CR {printf("Printing %f\n", $3);}
| line exit_command CR {exit(EXIT_SUCCESS);}
;
assignment : identifier '=' exp {$$ = vars[*$1] = $3; delete $1; }
;
exp : term {$$ = $1;}
| exp '+' term {$$ = $1 + $3;}
| exp '-' term {$$ = $1 - $3;}
| exp '*' term {$$ = $1 * $3;}
| exp '/' term {$$ = $1 / $3;}
| '(' exp ')' {$$ = $2;}
;
term : number {$$ = $1;}
| identifier {$$ = vars[*$1]; delete $1; }
;
%%
int main (void) {
return yyparse();
}
extern int yyparse();
void yyerror (char *s)
{
extern int yylineno; // defined and maintained in lex
extern char *yytext; // defined and maintained in lex
fprintf (stderr, "%s\n", s);
}
1 个解决方案
#1
1
Here's one place where the double
to std::string*
error will be produced:
这里有一个地方,双重的std::字符串*错误将产生:
assignment : identifier '=' exp {$$ = vars[*$1] = $3; delete $1; }
The type of assignment
is <index>
, which is std::string*
. The type of exp
is <num>
, which is double
. So in the action above, $$
is a std::string*
, and $3
is a double
(as is vars[*$1]
).
赋值的类型是
My best guess is that you didn't intend the semantic type of assignment
to be <index>
.
我最好的猜测是,您不打算将赋值的语义类型设置为
As for the fact that yyerror
isn't defined in calc.l
, that is clearly true. yyerror
is defined in calc.y
, and the declaration is also in calc.y
. The C programs produced by (f)lex and yacc/bison are different programs, and they are compiled independently, so the fact that yyerror
is declared in the yacc/bison-generated program does not make it's declaration visible to the (f)lex-generated program. If you need to use it from a (f)lex action, you'll need to declare it in both files.
关于yyerror没有在calc中定义的事实,这显然是正确的。yyerror定义在calc.y中,声明也在calc.y中。由(f)lex和yacc/bison生成的C程序是不同的程序,它们是独立编译的,所以yyerror在yacc/bison生成程序中声明的事实并不能使它的声明对(f)lex生成的程序可见。如果您需要从(f)lex操作中使用它,那么您需要在两个文件中声明它。
These warnings:
这些警告:
calc.tab.c:1490: warning: deprecated conversion from string constant to 'char*'
suggest that you should find a newer version of bison
. If that is impossible, you can just ignore them; g++
is complaining that the bison template is not C++-clean, because it is assigning a string literal (which is a const char*
) to a char*
variable without a cast. Newer bison versions avoid the warning.
建议您找到一个更新版本的bison。如果这是不可能的,你可以忽略它们;g++抱怨bison模板不是c++ -clean,因为它将一个字符串文本(这是一个const char*)分配给一个没有cast的char*变量。更新的bison版本避免了警告。
#1
1
Here's one place where the double
to std::string*
error will be produced:
这里有一个地方,双重的std::字符串*错误将产生:
assignment : identifier '=' exp {$$ = vars[*$1] = $3; delete $1; }
The type of assignment
is <index>
, which is std::string*
. The type of exp
is <num>
, which is double
. So in the action above, $$
is a std::string*
, and $3
is a double
(as is vars[*$1]
).
赋值的类型是
My best guess is that you didn't intend the semantic type of assignment
to be <index>
.
我最好的猜测是,您不打算将赋值的语义类型设置为
As for the fact that yyerror
isn't defined in calc.l
, that is clearly true. yyerror
is defined in calc.y
, and the declaration is also in calc.y
. The C programs produced by (f)lex and yacc/bison are different programs, and they are compiled independently, so the fact that yyerror
is declared in the yacc/bison-generated program does not make it's declaration visible to the (f)lex-generated program. If you need to use it from a (f)lex action, you'll need to declare it in both files.
关于yyerror没有在calc中定义的事实,这显然是正确的。yyerror定义在calc.y中,声明也在calc.y中。由(f)lex和yacc/bison生成的C程序是不同的程序,它们是独立编译的,所以yyerror在yacc/bison生成程序中声明的事实并不能使它的声明对(f)lex生成的程序可见。如果您需要从(f)lex操作中使用它,那么您需要在两个文件中声明它。
These warnings:
这些警告:
calc.tab.c:1490: warning: deprecated conversion from string constant to 'char*'
suggest that you should find a newer version of bison
. If that is impossible, you can just ignore them; g++
is complaining that the bison template is not C++-clean, because it is assigning a string literal (which is a const char*
) to a char*
variable without a cast. Newer bison versions avoid the warning.
建议您找到一个更新版本的bison。如果这是不可能的,你可以忽略它们;g++抱怨bison模板不是c++ -clean,因为它将一个字符串文本(这是一个const char*)分配给一个没有cast的char*变量。更新的bison版本避免了警告。