flex и bison: пользовательский класс C ++

Я не могу понять, как встроить пользовательский класс C ++ в bison синтаксический анализатор. Вот что у меня есть (только некоторые необходимые кусочки; если вам нужно, я могу опубликовать весь код).

scanner.l

%{
#include "parser.tab.h"#include "types.h"#include <iostream>
#include <string>
#define YY_DECL extern "C" int yylex()
using namespace std;
int chars = 0;
int words = 0;
int lines = 0;
extern "C" {
int yylex(void);
} /* extern "C" */
%}

%%
"none" {
yylval.none_value = none_type();
return NONE;
} /* none type */

{DIGIT_BIN}|{DIGIT_OCT}|{DIGIT_DEC}|{DIGIT_HEX} {
yylval.int_value = atoi(yytext);
return INT;
} /* int type */

parser.y

%{
#include "types.h"#include <iostream>
using namespace std;
void yyerror(const char *error) {
cerr << error << endl;
} /* error handler */
extern "C" {
int yylex(void);
int yyparse(void);
int yywrap() { return 1; }
} /* extern "C" */
%}

%union {
none_type   none_value; /* HERE IS WHAT I WANT */
int         int_value;
} /* union */

%token <none_value>      NONE
%token <int_value>       INT

types.h

#include <iostream>

class none_type {
public:
none_type(void);
~none_type();
}; /* none_type */

Как видите, код здесь не полный, но этого должно быть достаточно, чтобы описать то, что я хочу. Все, что я делаю с типами C ++ по умолчанию, работает хорошо; я могу реализовать свои собственные классы?

Компилятор возвращает такие ошибки:

parser.y:20:3: error: 'none_value' does not name a type
In file included from scanner.l:3:0:
parser.y:20:3: error: 'none_value' does not name a type
scanner.l: In function 'int yylex()':
scanner.l:54:32: error: cannot convert 'none_type' to 'int' in assignment
make: *** [caesar] Error 1

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

0

Решение

Когда я компилирую ваш код с помощью bison / g ++, я получаю ошибки:

parser.y:16:15: error: member ‘none_type YYSTYPE::none_value’ with constructor not allowed in union
parser.y:16:15: error: member ‘none_type YYSTYPE::none_value’ with destructor not allowed in union
parser.y:16:15: note: unrestricted unions only available with -std=c++0x or -std=gnu++0x

которая точно говорит вам, в чем проблема — вы не можете поместить в объединение не-POD-тип, потому что компилятор не может сказать, какой ctor / dtor вызывать для этого. Обратите внимание на комментарий о том, что вы МОЖЕТЕ сделать это в C ++ 11, но это не очень помогает, так как в этом случае он не будет автоматически вызывать ctor / dtor, поэтому вещи просто не будут созданы или уничтожены должным образом.

2

Другие решения

Если вы хотите поиграть с помещением подлинных объектов в свой стек, пожалуйста, взгляните на текущую основную ветку Bison, где вы можете запустить примеры, такие как

%token <::std::string> TEXT;
%token <int> NUMBER;
%token END_OF_FILE 0;
%type <::std::string> item;
%type <::std::list<std::string>> list;
%printer { yyoutput << $$; } <int> <::std::string> <::std::list<std::string>>;

%%

result:
list  { std::cout << $1 << std::endl; }
;

list:
/* nothing */ { /* Generates an empty string list */ }
| list item     { std::swap ($$, $1); $$.push_back ($2); }
;

item:
TEXT          { std::swap ($$, $1); }
| NUMBER        { $$ = string_cast ($1); }
;
%%

// The yylex function providing subsequent tokens:
// TEXT         "I have three numbers for you:"// NUMBER       1
// NUMBER       2
// NUMBER       3
// TEXT         " and that's all!"// END_OF_FILE

static
yy::parser::symbol_type
yylex ()
{
static int stage = -1;
++stage;
yy::parser::location_type loc(0, stage + 1, stage + 1);
switch (stage)
{
case 0:
return yy::parser::make_TEXT ("I have three numbers for you.", loc);
case 1:
case 2:
case 3:
return yy::parser::make_NUMBER (stage, loc);
case 4:
return yy::parser::make_TEXT ("And that's all!", loc);
default:
return yy::parser::make_END_OF_FILE (loc);
}
}

Наличие мнения от возможных пользователей этой функции было бы наиболее полезным. Например, о помощи зубров на gnu.org. Увидеть https://savannah.gnu.org/git/?group=bison для Git доступ к хранилищу.

2