2016-08-20 2 views
0

Ich versuche, Flex und Bison zu verwenden, um einen Compiler zu erstellen. Aber ich erhalte Fehler, wenn ich versuche zu kompilieren.
Hier ist der Fehler:undefined Verweis auf `yylex '&& undefined Verweis auf` yyin'

flex --header-file=lex.h --outfile=lex.cc lex.ll 
g++ -w -Wall -Wextra -ansi -g -c -o lex.o lex.cc -lm -ll 
bison -v --output-file=parse.cc --defines=parse.hh --warnings=all --feature=all parse.yy 
g++ -w -Wall -Wextra -ansi -g -c -o parse.o parse.cc 
g++ -w -Wall -Wextra -ansi -g -c -o main.o main.cc 
g++ -w -Wall -Wextra -ansi -g -fkeep-inline-functions -o LFIO lex.o parse.o function.o main.o -lfl -lm -ll 
parse.o: In function `yyparse()': 
/root/LFIO-combine/parse.cc:1199: undefined reference to `yylex' 
main.o: In function `main': 
/root/LFIO-combine/main.cc:21: undefined reference to `yyin' 
/root/LFIO-combine/main.cc:21: undefined reference to `yyin' 
collect2: error: ld returned 1 exit status 
make: *** [LFIO] Error 1 

Hier mein Make-Datei ist:

CXXFLAGS = -w -Wall -Wextra -ansi -g 
OBJECTS = lex.o parse.o function.o main.o 


LFIO : $(OBJECTS) 
     g++ $(CXXFLAGS) -fkeep-inline-functions -o LFIO $(OBJECTS) -lfl -lm -ll 

clean : 
     rm -f *.o 

lex.cc : lex.ll 
     flex --header-file=lex.h --outfile=lex.cc lex.ll 

parse.hh : parse.cc 

parse.cc : parse.yy function.h algorithm.h 
     bison -v --output-file=parse.cc --defines=parse.hh --warnings=all --feature=all parse.yy 

%.o: %.cc %.h 
     g++ $(CXXFLAGS) -c -o [email protected] $< -lm -ll 

main.o : main.cc lex.h parse.hh function.h algorithm.h 

function.o : function.h function.cc 

parse.o : parse.cc parse.hh function.h algorithm.h 

lex.o :lex.h algorithm.h function.h 

Hier ist meine lex.ll

%option c++ 
%option ecs 
%option nodefault 
%option stack 
%option warn 
%option yylineno 

%{ 
#include "function.h" 
#include "parse.hh" 
#include <limits.h> 
#include <iostream> 
#include <sstream> 
#include <string.h> 
#include <unistd.h> 
#include <stdlib.h> 
int yyFlexLexer::yywrap() { return 1; } 
%} 

ATOM [A-Z][a-zA-Z0-9_']* 
VARIABLE  [a-z][a-zA-Z0-9_']* 

%% 
[ \t\n]   ; 
{VARIABLE} { return (TOK_VARIABLE);} 
{ATOM} { return (TOK_ATOM);} 
":-" {} 
"," {} 
"." {} 
<<EOF>> {yyterminate();} 
%% 

parse.yy ist wie folgt:

%defines 
%define api.token.prefix {TOK_} 

%{ 
#include "function.h" 
#include "lex.h" 
#include <stdlib.h> 
#include <string.h> 
#include <stdio.h> 

#ifdef MS_WINDOWS 
#include <malloc.h> 
#define alloca_alloca 
#endif 
void yyerror(const char *s) 
{ 
    fprintf (stderr, "%s\n", s); 
} 
extern "C" int yylex(void); 

%} 

%union{ 
...... 
} 

%type ...... 


%% 
...... 

Und dann ist main.cc wie folgt:

#include "function.h" 
#include "algorithm.h" 
#include "parse.hh" 
#include "lex.h" 
extern "C" int yylex(void); 
extern FILE *yyin; 
extern FILE *yyout; 
extern int fopen(); 
extern int yyparse(void *); 

int main(int argc, char **argv){ 

if(argc > 1){ 
if(!(yyin = fopen(argv[1], "r"))) { 
perror(argv[1]); 
return (1); 
} 
} 
//yylex(); 
yyparse(); 
...... 
return 0; 
} 

Weiß jemand, was diese Fehler verursacht und wie man sie löst? Ich wäre dankbar, wenn sich jemand Zeit nehmen könnte, diese Fehler zu überprüfen.

+1

Bitte zeigen Sie die * full * Ausgabe von 'make', so dass wir sehen können, ob es versucht, mit' lex.o' zu verbinden. –

+0

Ich habe die Ausgabe von 'make' aktualisiert. –

+0

Nur eine Ahnung ... Sie kompilieren den Lexer als C++, haben aber immer noch "extern" C "int yylex (void);". Versuchen Sie, den "externen" C-Teil zu entfernen. –

Antwort

1

Sammeln meiner Kommentare in eine Antwort.

Es gibt zwei Probleme:

Die erste ist, dass der Code als C++ kompiliert wird, das heißt, die Definition von yylex werden auch als C++ kompiliert werden. Das heißt, es ist nicht extern "C". Um dieses Problem zu beheben, entfernen Sie die extern "C" aus allen Deklarationen.

Das zweite Problem ist zweifach: Das erste ist, dass das Symbol yyin scheint nirgendwo definiert zu sein, so dass Sie es selbst tun müssen. Die zweite Sache ist, dass es ein Zeiger auf ein std::istream Objekt sein sollte, und nicht ein FILE *.

das zweite Problem zu lösen, mit yyin, empfehle ich Ihnen die Definition Ihres Lexer Deklarationsblock hinzu:

%{ 
// Your includes... 
int yyFlexLexer::yywrap() { return 1; } 

// Add definition of yyin 
std::istream* yyin; 
%} 

Dann in Ihrer main.cc Datei die extern Erklärung aktualisieren, um die Definition zu entsprechen.

+0

Danke. Es gibt jetzt keine yyin und yylex Fehler. Aber durch Hinzufügen von 'std :: isotream * yyin;' Es gibt neue Fehler wie diese 'main.cc: In der Funktion 'int main (int, char **)': main.cc:23:11: Fehler: kann nicht konvertieren 'FILE * {aka _IO_FILE *}' zu 'std :: istream * {aka std :: basic_istream *}' in der Zuweisung if (! (Yyin = fopen (argv [1], "r"))) { ^ make: *** [main.o] Fehler 1' –

+0

@XuWang Sie müssen natürlich einen normalen [C++ Eingabedatei-Stream] erstellen (http://en.cppreference.com/w/cpp/io/basic_ifstream) und mache 'yyin' darauf aufmerksam. –

+0

OK, ich werde versuchen, dies zu erstellen. –