2009-10-20 19 views
12

Ya busqué mi respuesta pero no obtuve ninguna respuesta rápida para un ejemplo simple.Simple Flex/Bison C++

Quiero compilar un escáner/analizador de flex/bison + usando g ++ solo porque quiero usar clases de C++ para crear AST y cosas similares.

Buscando en Internet He encontrado algunos exploits, todos diciendo que lo único que se necesita es declarar algunos prototipos de funciones usando extern "C" en el archivo lex.

Así que mi archivo shady.y es

%{ 
#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(); 
} 

mientras archivo shady.l es

%{ 
    #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); } 

%% 

Por último, en el makefile que utilizo g ++ en vez de 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 

flexión y el bisonte funcionan correctamente pero al vincularlo obtengo el siguiente error:

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

Por supuesto, si trato de cambiar algo sobre la función en el archivo bison, dice que yylex no está declarado en el ámbito de yyparse.

¿Estoy tratando de resolver simplemente algo que es más complejo de lo que parece? En realidad, no necesito una estructura cerrada para tener acceso a analizar y leer de una manera orientada a objetos, solo quiero que funcione.

Sólo quiero ser capaz de utilizar C++ en el archivo de bisontes (para crear AST) y llamar a yyparse() de los objetos C++ ..

Gracias de antemano

+0

Ambos flex y bison tienen banderas para generar C++, no C. – vonbrand

+1

Yuck. No es una buena idea utilizar analizadores de C impuros y no reentrantes con variables globales estáticas en C++. Es mucho más limpio usar flex y bison en los modos C++ respectivamente. https://www.gnu.org/software/bison/manual/bison.html#A-Complete-C_002b_002b-Example – Barry

Respuesta

10

Se necesita el extern "C" {} para yylex a estar en shady.l:

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

    #include "shady.tab.h" 
%} 

%% 

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

...etc... 

Además, después de la adición de una regla gramatical ficticia, que fue capaz de generar y ejecutar esto con solo:

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