C++ 架构x86_64 flex/bison的未定义符号
我正在尝试制作一个简单的玩具(C++ 架构x86_64 flex/bison的未定义符号,c++,bison,flex-lexer,let,C++,Bison,Flex Lexer,Let,我正在尝试制作一个简单的玩具(LET)语言,作为使用flex/bison的练习。但是,当我运行命令g++-Wall-std=c++11 repl.cpp-v-o LET时,我不断收到以下错误: Undefined symbols for architecture x86_64: "yy_scan_string(char const*)", referenced from: _main in repl-030403.o "yy_delete_buffer(yy_buffer_s
LET
)语言,作为使用flex/bison
的练习。但是,当我运行命令g++-Wall-std=c++11 repl.cpp-v-o LET
时,我不断收到以下错误:
Undefined symbols for architecture x86_64:
"yy_scan_string(char const*)", referenced from:
_main in repl-030403.o
"yy_delete_buffer(yy_buffer_state*)", referenced from:
_main in repl-030403.o
"yyparse()", referenced from:
_main in repl-030403.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
我定义了以下文件
LET.y
:
%{
#include <iostream>
#include <cstdio>
#include <string>
#include "AST.hpp"
#include "GENERATED_CODE/LET_parser.hpp"
#include "GENERATED_CODE/LET_lexer.hpp"
using namespace std;
extern int yylex();
extern char* yytext;
extern int yyparse();
extern Pgm* prog;
void yyerror (char const *s) {
fprintf (stderr, "%s\n", s);
}
%}
%output "./PARSER/GENERATED_CODE/LET_parser.cpp"
%defines "./PARSER/GENERATED_CODE/LET_parser.hpp"
%union {
Pgm* prog;
int value;
char* var;
char cval;
Exp* exp;
string* str;
}
%token TTRUE
%token TFALSE
%token TLET
%token TIN
%token TIF
%token TTHEN
%token TELSE
%token TISZERO
%token TASSIGN
%token TLPAREN
%token TRPAREN
%token TPLUS
%token TMINU
%token TMULT
%token TDIVI
%token TREMI
%token TCOMMA
%token <value> TNUM
%token <var> TVAR
%type <prog> Prog
%type <exp> Exp
%type <str> Vari
/* Causes Bison to give more detailed error messages when parsing */
%error-verbose
%%
/* Bison Grammar Declarations */
Prog: Exp { prog = new Pgm($1); }
Vari: TVAR { $$ = new string(yytext);}
Exp: TNUM { $$ = new ConstExp(atoi(yytext)); }
| TVAR { $$ = new VarExp(yytext); }
| TTRUE { $$ = new TrueExp; }
| TFALSE { $$ = new FalseExp; }
| TISZERO TLPAREN Exp TRPAREN { $$ = new IsZeroExp($3); }
| TMINU TLPAREN Exp TCOMMA Exp TRPAREN { $$ = new DiffExp($3, $5); }
| TPLUS TLPAREN Exp TCOMMA Exp TRPAREN { $$ = new SumExp($3, $5); }
| TMULT TLPAREN Exp TCOMMA Exp TRPAREN { $$ = new MultExp($3, $5); }
| TDIVI TLPAREN Exp TCOMMA Exp TRPAREN { $$ = new QuotExp($3, $5); }
| TREMI TLPAREN Exp TCOMMA Exp TRPAREN { $$ = new RemiExp($3, $5); }
| TIF Exp TTHEN Exp TELSE Exp { $$ = new IfExp($2, $4, $6); }
| TLET Vari TASSIGN Exp TIN Exp { $$ = new LetExp(*$2, $4, $6); }
Makefile
:
generate-parser: clean flex bison
clean:
rm -rf PARSER/GENERATED_CODE
mkdir -p PARSER/GENERATED_CODE
flex:
flex PARSER/LET.l
bison:
bison -d PARSER/LET.y
repl.cpp
:
#include <cstdio>
#include "./PARSER/AST.hpp"
#include "./PARSER/GENERATED_CODE/LET_parser.hpp"
#include "./PARSER/GENERATED_CODE/LET_lexer.hpp"
using namespace std;
extern YY_BUFFER_STATE yy_scan_string(const char * str);
extern void yy_delete_buffer(YY_BUFFER_STATE buffer);
int main() {
char input[] = "RAINBOW UNICORN 1234 UNICORN";
YY_BUFFER_STATE state = yy_scan_string(input);
yyparse();
yy_delete_buffer(state);
return 0;
}
#包括
#包括“/PARSER/AST.hpp”
#包括“/PARSER/GENERATED_CODE/LET_PARSER.hpp”
#包括“/PARSER/GENERATED_CODE/LET_lexer.hpp”
使用名称空间std;
外部YY_缓冲区_状态YY_扫描_字符串(const char*str);
外部无效yy_删除_缓冲区(yy_缓冲区\状态缓冲区);
int main(){
字符输入[]=“彩虹独角兽1234独角兽”;
YY_缓冲区_状态=YY_扫描_字符串(输入);
yyparse();
yy_删除_缓冲区(状态);
返回0;
}
基本问题是,您似乎没有编译生成的扫描程序和解析器,也没有将编译后的扫描程序和解析器链接到可执行文件中。因此,当您尝试创建可执行文件时,扫描器(yy_scan_string
和yy_delete_buffer
)和解析器(yy parse
)中定义的符号都不存在
在将编译行添加到Makefile时,请记住扫描程序依赖于解析器,因为它必须包含bison生成的头文件,才能定义令牌类型
在这种情况下,解析器不能依赖于扫描器,这就是为什么在bison序言中包含扫描器的头文件是不正确的。在bison序言中包含解析器头文件也是不正确的,因为bison生成的解析器已经包含了必要的原型和定义
最后,你要求Flex生成一个C++ Listor,但是你的代码使用C接口(包括函数<代码> YyyScIxSype字符串和
。如果您真的想使用C++ API,您需要仔细阅读,然后对BISY定义进行适当的更改,以便它知道如何调用Listor。p>
%选项c++
尽管这与您的问题无关,但在解析器中使用
几乎从来都不正确,因为yytext
的内容通常与输入中的下一个标记相对应。(LR(1)解析器总是向前看一个标记。)您应该在扫描仪操作中进行必要的语义转换。yytext
yy_scan_string
和yy_delete_buffer
)和解析器(yy parse
)中定义的符号都不存在
在将编译行添加到Makefile时,请记住扫描程序依赖于解析器,因为它必须包含bison生成的头文件,才能定义令牌类型
在这种情况下,解析器不能依赖于扫描器,这就是为什么在bison序言中包含扫描器的头文件是不正确的。在bison序言中包含解析器头文件也是不正确的,因为bison生成的解析器已经包含了必要的原型和定义
最后,你要求Flex生成一个C++ Listor,但是你的代码使用C接口(包括函数<代码> YyyScIxSype字符串和
。如果您真的想使用C++ API,您需要仔细阅读,然后对BISY定义进行适当的更改,以便它知道如何调用Listor。p>
%选项c++
尽管这与您的问题无关,但在解析器中使用
几乎从来都不正确,因为yytext
的内容通常与输入中的下一个标记相对应。(LR(1)解析器总是向前看一个标记。)您应该在扫描仪操作中进行必要的语义转换。yytext
#include <cstdio>
#include "./PARSER/AST.hpp"
#include "./PARSER/GENERATED_CODE/LET_parser.hpp"
#include "./PARSER/GENERATED_CODE/LET_lexer.hpp"
using namespace std;
extern YY_BUFFER_STATE yy_scan_string(const char * str);
extern void yy_delete_buffer(YY_BUFFER_STATE buffer);
int main() {
char input[] = "RAINBOW UNICORN 1234 UNICORN";
YY_BUFFER_STATE state = yy_scan_string(input);
yyparse();
yy_delete_buffer(state);
return 0;
}