不能精确定位“不能将double”转换为std::string*“in assignment”,也可以是yyparse()和yylex()错误。

时间:2022-10-26 09:42:17

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]).

赋值的类型是 ,它是std::string*。exp的类型是 ,它是double。因此在上面的操作中,$$是一个std::string*, $3是一个double (as是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]).

赋值的类型是 ,它是std::string*。exp的类型是 ,它是double。因此在上面的操作中,$$是一个std::string*, $3是一个double (as是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版本避免了警告。