2017-04-01 45 views
0

我正在尝试使用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; 
} 
+0

[Can not compile flex&bison(Symbols not found x86 \ _64)]可能的重复](http://stackoverflow.com/questions/28207339/cant-compile-flex-bison-symbols-not-found- x86-64) –

回答

2

最根本的问题是,你似乎并不被编译生成的扫描器和分析器,也不是你所链接的编译扫描器和分析器到你的可执行文件。因此,当您尝试创建可执行文件时,扫描仪(yy_scan_stringyy_delete_buffer)中或解析器(yyparse)中定义的符号都不存在。

当您将编译行添加到您的Makefile中时,请记住扫描器依赖于解析器,因为它必须包含由bison生成的头文件以便定义标记类型。

既然如此,解析器就不能依赖扫描器,这就是为什么它不正确#include扫描仪的头文件在野牛序言中。对于野牛序言中的解析器头文件#include也是不正确的,因为野牛生成的解析器已经包含了必要的原型和定义。

最后,您要求flex生成一个C++词法分析器,但您的代码使用C接口(其中包括函数yy_scan_stringyy_delete_buffer)。就个人而言,我只是从您的扫描仪序言中删除%option c++。如果您真的想使用C++ API,您需要仔细阅读flex manual chapter on C++ scanners,然后对您的bison定义进行适当的更改,以便知道如何调用词法分析器。

虽然这是不相关的你的问题,在一个解析器使用yytext是几乎从来没有正确的,因为yytext内容通常会对应于输入下一个令牌。 (LR(1)解析器总是向前看一个标记)。您应该在扫描器操作中进行必要的语义转换。

+0

非常感谢你的回应!可能是我在网上看到的最有帮助的事情。我会看看并做适当的修改! –

相关问题