2017-04-01 113 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

非常感謝你的迴應!可能是我在網上看到的最有幫助的事情。我會看看並做適當的修改! –

相關問題