【问题标题】:Undefined reference to `yylex' in yyparse() while compiling using g++, bison and flex使用 g++、bison 和 flex 进行编译时,yyparse() 中未定义对“yylex”的引用
【发布时间】:2024-10-31 06:40:02
【问题描述】:

我在编译代码时遇到问题 (undefined reference to 'yylex')。让我们从 sn-p 开始,我将在下面描述细节:

弹性:

%{
#include <stdlib.h>
extern int yylex();
%}
%%
"=" {return EQ;}
"!="    {return NE;}
"<" {return LT;}
">" {return GT;}
":="    {return ASSIGN;}
";" {return SEMICOLON;}
"IF"    {return IF;}
"THEN"{return THEN;}

"END" {return END;}
[_a-z]+ {yylval.text = strdup(yytext); return IDENTIFIER;}
[ \t]+
[0-9]+          {
                yylval.var = atoi (yytext);
                return NUMBER;
                }
[-+/^*'%'()]    {
                return *yytext;
                }
\n              return RESULT;
%%

野牛:

%{
  extern "C"
  {
    int yyparse();
    int yylex(void);
    void yyerror(char *s){}
    int yywrap(void){return 1;}
  }

  #include <iostream>
  #include <vector>
  #include <string>
  #include <stdlib.h>
  #include <map>

  using namespace std;

  vector <string> instructions;
  map <> vars;
%}

%union{
  char* text;
  int var;
}


%token EQ
%token NE
%token ASSIGN
%token SEMICOLON
%token IF
%token THEN
%token <text> IDENTIFIER
%token <var> NUMBER
%token <var> RESULT

%left '+' '-'
%left '*' '/' '%'
%right '^'

%%

exp: NUMBER
| IDENTIFIER
| IDENTIFIER "+" IDENTIFIER
| IDENTIFIER "-" IDENTIFIER
;
%%

int main(void){
  yyparse();
} 

这是我用来编译和运行程序的 bash 脚本:

#!/bin/bash
clear
rm launcher lex.yy.cpp *.tab.cpp *.tab.hpp
bison  -d -o list.tab.cpp *.y
flex -o lex.yy.cpp *.l
g++ -o launcher *.cpp -lfl

为了清晰可见,我在这里只发布代码中最重要的部分,因为其余部分在这里并不是真正需要的。无论如何,如果有人想查看整个代码,请在此处发布:http://pastebin.com/1rS2FBJj。这是一个更大的代码块,但需要更多的地方。

当我尝试将所有文​​件编译为 *.c 文件然后使用 gcc 时,一切都很好。但是当我尝试将编译器切换到 g++ 并因此将文件切换到 cpp 时,我不断收到此错误:

list.tab.cpp:在函数“int yyparse()”中: list.tab.cpp:1397:警告:不推荐将字符串常量转换为“char*” list.tab.cpp:1540:警告:不推荐将字符串常量转换为“char*” /tmp/ccdqpQVx.o:在函数“yyparse”中: list.tab.cpp:(.text+0x252): undefined reference to `yylex' collect2: ld 返回 1 个退出状态

谁能给我一个提示,最好的方法是什么?

【问题讨论】:

  • 不能完全解决问题,但 -fno-const-strings 会消除警告。

标签: c++ compiler-construction g++ bison flex-lexer


【解决方案1】:

在您的 Flex 文件中,您声明:

extern int yylex();

当编译为 C++ 时,它声明了一个带有 C++ 链接 的函数。在您的 Bison 文件中,您声明:

extern "C" {
  int yylex();
}

这给了它C 链接。它们是两种不同的功能。您定义 C++ 版本(或者更确切地说,Flex 为您定义),但您声明 C 版本,C 版本是编译器认为您尝试的版本调用(在 Bison 生成的代码中)。链接器看到使用的是 C 版本,但找不到定义。

选择一个链接并始终如一地使用它。 (我会选择 C++,因为它允许完全从代码中省略“外部”内容。)

【讨论】:

  • 就是这个!:) 现在一切都好。非常感谢!