2009-10-20 4 views
12

Я уже искал свой ответ, но я не получил быстрого ответа для простого примера.Простой Flex/Bison C++

Я хочу скомпилировать сканер flex/bison + parser с помощью g ++ только потому, что я хочу использовать классы C++ для создания AST и подобных вещей.

Поиск через Интернет Я нашел некоторые эксплойты, все из которых говорят, что единственная необходимая вещь - объявить некоторые прототипы функций, используя extern «C» в файле lex.

Так что мой файл shady.y является

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

в то время как shady.l файл

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

%% 

Наконец в Makefile я использую г ++ вместо 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 

прогибается и зубра работают правильно, но при связывании я получаю следующую ошибку:

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

Конечно, если я попытаюсь изменить что-либо о функции в файле бизонов, это говорит о том, что yylex не объявлен в области yyparse.

Я пытаюсь решить просто нечто более сложное, чем кажется? На самом деле мне не нужна закрытая структура, чтобы иметь доступ к анализу и лексеру объектно-ориентированным образом, я просто хочу заставить его работать.

Я просто хочу, чтобы иметь возможность использовать C++ в бизона файле (для создания AST) и вызвать yyparse() из объектов C++ ..

Заранее спасибо

+0

Оба гибких и бизона имеют флаги для генерации C++, а не C. – vonbrand

+1

Yuck. Не рекомендуется использовать нечистые, нереагентные C-парсеры со статическими глобальными переменными в C++. Гораздо чище использовать flex и bison в режимах C++ соответственно. https://www.gnu.org/software/bison/manual/bison.html#A-Complete-C_002b_002b-Example – Barry

ответ

10

Вам нужен extern "C" {} для yylex в быть в shady.l:

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

    #include "shady.tab.h" 
%} 

%% 

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

...etc... 

Кроме того, после добавления фиктивного правила грамматики, я был в состоянии построить и запустить это только с:

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