0

bisonC++ のユーザー定義クラスをパーサーに埋め込む方法がわかりません。これが私が持っているものです(必要な部分だけです。必要な場合は、すべてのコードを投稿できます)。

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

前もって感謝します!

4

2 に答える 2

2

コードを 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

これは、問題が何であるかを正確に示しています。コンパイラは、どの ctor/dtor を呼び出すべきかを判断できないため、非 POD 型を共用体に入れることはできません。C++ 11で実行できるというコメントに注意してください。ただし、その場合、ctor/dtorが自動的に呼び出されないため、実際には役に立たないため、適切に構築または破棄されません。

于 2012-10-24T22:20:46.273 に答える
2

本物のオブジェクトをスタックに置いて遊んでみたい場合は、Bison の現在の master ブランチを見てください。ここでは、次のような例を実行できます。

%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 の help-bison で。リポジトリへの Git アクセスについては、 https: //savannah.gnu.org/git/?group=bison を参照してください。

于 2012-10-25T07:54:22.183 に答える