2009-10-20 17 views
12

Już szukałem odpowiedzi, ale nie otrzymałem szybkiej odpowiedzi na prosty przykład.Simple Flex/Bison C++

Chcę skompilować skaner flex/bison + parser za pomocą g ++ tylko dlatego, że chcę używać klas C++ do tworzenia AST i podobnych rzeczy.

Wyszukiwanie przez internet Znalazłem kilka exploitów, wszystkie stwierdzające, że jedyną potrzebną rzeczą jest deklarowanie prototypów funkcji za pomocą zewnętrznego "C" w pliku lex.

Więc mój plik shady.y jest

%{ 
#include <stdio.h> 
#include "opcodes.h" 
#include "utils.h" 

void yyerror(const char *s) 
{ 
    fprintf(stderr, "error: %s\n", s); 
} 

int counter = 0; 

extern "C" 
{ 
     int yyparse(void); 
     int yylex(void); 
     int yywrap() 
     { 
       return 1; 
     } 

} 

%} 

%token INTEGER FLOAT 
%token T_SEMICOL T_COMMA T_LPAR T_RPAR T_GRID T_LSPAR T_RSPAR 
%token EOL 

%token T_MOV T_NOP 


%% 

... GRAMMAR OMITTED ... 

%% 

main(int argc, char **argv) 
{ 
    yyparse(); 
} 

podczas shady.l plik jest

%{ 
    #include "shady.tab.h" 
%} 

%% 

"MOV"|"mov" { return T_MOV; } 
"NOP"|"nop" { return T_NOP; } 

";" { return T_SEMICOL; } 
"," { return T_COMMA; } 
"(" { return T_LPAR; } 
")" { return T_RPAR; } 
"#" { return T_GRID; } 
"[" { return T_LSPAR; } 
"]" { return T_RSPAR; } 
[1-9][0-9]? { yylval = atoi(yytext); return INTEGER;} 
[0-9]+"."[0-9]+ | "."?[0-9]? { yylval.d = atof(yytext); return FLOAT; } 
\n { return EOL; } 
[ \t] { /* ignore whitespace */ } 
. { printf("Mystery character %c\n", *yytext); } 

%% 

Wreszcie w makefile używam g ++ zamiast gcc:

shady: shady.l shady.y 
bison -d shady.y -o shady.tab.c 
flex shady.l 
g++ -o [email protected] shady.tab.c lex.yy.c -lfl 

Flex i żubr działają poprawnie, ale po połączeniu pojawia się następujący błąd:

Undefined symbols: 
    "_yylex", referenced from: 
    _yyparse in ccwb57x0.o 

Oczywiście, jeśli spróbuję coś zmienić w funkcji pliku żubra, oznacza to, że yylex nie jest zadeklarowany w zakresie yyparse.

Czy próbuję rozwiązać po prostu coś, co jest bardziej skomplikowane, niż się wydaje? Właściwie nie potrzebuję zamkniętej struktury, aby mieć dostęp do analizowania składni i leksyki w sposób zorientowany na obiekt, po prostu chcę, żeby to działało.

Chcę tylko, aby móc korzystać z C++ w żubrów pliku (aby utworzyć AST) i zadzwonić yyparse() z C++ obiektów ..

góry dziękuję

+0

Zarówno flex jak i żubr mają flagi generujące C++, a nie C. – vonbrand

+1

Yuck. Nie jest dobrym pomysłem użycie nieczytelnych, nierecentrantowych analizatorów składni C ze statycznymi zmiennymi globalnymi w C++. Znacznie czystsze jest używanie flex i bison w trybach C++. https://www.gnu.org/software/bison/manual/bison.html#A-Complete-C_002b_002b-Przykład – Barry

Odpowiedz

10

Musisz extern "C" {} dla yylex do być w shady.l:

%{ 
    extern "C" 
    { 
     int yylex(void); 
    } 

    #include "shady.tab.h" 
%} 

%% 

"MOV"|"mov" { return T_MOV; } 
"NOP"|"nop" { return T_NOP; } 

...etc... 

Ponadto, po dodaniu reguły gramatyki atrapę, udało mi się zbudować i uruchomić z tego właśnie:

559 flex shady.l 
    560 bison -d shady.y 
    561 g++ shady.tab.c lex.yy.c 
Powiązane problemy