架构x86_64 flex/bison的未定义符号
我正在尝试使用flex/bison
作为练习来制作一个简单的玩具(LET
)语言。不过,我不断收到以下错误,当我运行命令g++ -Wall -std=c++11 repl.cpp -v -o LET
:架构x86_64 flex/bison的未定义符号
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); }
LET.l
:
%{
#include <iostream>
#include <cstdio>
#include "AST.hpp"
#include "GENERATED_CODE/LET_parser.hpp"
using namespace std;
int yylex();
void yyerror (char const *s) {
fprintf (stderr, "%s\n", s);
}
%}
%option c++
%option header-file = "./PARSER/GENERATED_CODE/LET_lexer.hpp"
%option outfile = "./PARSER/GENERATED_CODE/LET_lexer.cpp"
%option noyywrap
digit [0-9]
alpha [a-zA-Z]
ws [ \t\n]+
%%
"#".*[\n] { /* No Action Taken */ }
{ws} { /* No Action Taken */ }
"true" { return TTRUE; }
"false" { return TFALSE; }
"let" { return TLET; }
"in" { return TIN; }
"if" { return TIF; }
"then" { return TTHEN; }
"else" { return TELSE; }
"zero?" { return TISZERO; }
"=" { return TASSIGN; }
"(" { return TLPAREN; }
")" { return TRPAREN; }
"+" { return TPLUS; }
"-" { return TMINU; }
"*" { return TMULT; }
"/" { return TDIVI; }
"%" { return TREMI; }
"," { return TCOMMA; }
"-"?{digit}+ { return TNUM; }
[a-zA-Z][a-z|0-9|\_|\'|\-|\?]* { return TVAR; }
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;
}
最根本的问题是,你似乎并不被编译生成的扫描器和分析器,也不是你所链接的编译扫描器和分析器到你的可执行文件。因此,当您尝试创建可执行文件时,扫描仪(yy_scan_string
和yy_delete_buffer
)中或解析器(yyparse
)中定义的符号都不存在。
当您将编译行添加到您的Makefile中时,请记住扫描器依赖于解析器,因为它必须包含由bison生成的头文件以便定义标记类型。
既然如此,解析器就不能依赖扫描器,这就是为什么它不正确#include
扫描仪的头文件在野牛序言中。对于野牛序言中的解析器头文件#include
也是不正确的,因为野牛生成的解析器已经包含了必要的原型和定义。
最后,您要求flex生成一个C++词法分析器,但您的代码使用C接口(其中包括函数yy_scan_string
和yy_delete_buffer
)。就个人而言,我只是从您的扫描仪序言中删除%option c++
。如果您真的想使用C++ API,您需要仔细阅读flex manual chapter on C++ scanners,然后对您的bison定义进行适当的更改,以便知道如何调用词法分析器。
虽然这是不相关的你的问题,在一个解析器使用yytext
是几乎从来没有正确的,因为yytext
内容通常会对应于输入下一个令牌。 (LR(1)解析器总是向前看一个标记)。您应该在扫描器操作中进行必要的语义转换。
非常感谢你的回应!可能是我在网上看到的最有帮助的事情。我会看看并做适当的修改! –
[Can not compile flex&bison(Symbols not found x86 \ _64)]可能的重复](http://*.com/questions/28207339/cant-compile-flex-bison-symbols-not-found- x86-64) –