Простой Flex/Bison C++

Я уже искал свой ответ, но не получил быстрого ответа на простой пример.

Я хочу скомпилировать сканер + синтаксический анализатор flex/bison с помощью 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); }

%%

Наконец, в make-файле я использую g++ вместо gcc:

shady: shady.l shady.y
bison -d shady.y -o shady.tab.c
flex shady.l
g++ -o $@ shady.tab.c lex.yy.c -lfl

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

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

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

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

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

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


person Jack    schedule 20.10.2009    source источник
comment
И flex, и bison имеют флаги для генерации C++, а не C.   -  person vonbrand    schedule 23.01.2013
comment
Фу. Не рекомендуется использовать нечистые, нереентерабельные синтаксические анализаторы C со статическими глобальными переменными в C++. Гораздо чище использовать flex и bison в режимах C++ соответственно. gnu.org/software/bison/manual/   -  person    schedule 12.05.2014


Ответы (1)


Вам нужно, чтобы 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 
person DigitalRoss    schedule 20.10.2009