4

spirit::lexertlで定義されたトークンを生成するベースのレクサーがありlex::token_def<std::string>ます。qi::symbols<>シンボルテーブルの関連データをルールの属性として使用して、テーブルを使用してそのテーブルのトークンを照合したいと思います。このようなもの[実際のコードから要約]:

qi::symbols<char, int> mode_table;
mode_table.add("normal", 0)("lighten", 1)("darken", 2);

rule<Iterator, int()> mode = raw_token(tok.kMode) >> ':' >> ascii::no_case[mode_table];

ただし、これをコンパイルすると、次のエラーが発生します。

/Users/tim/Documents/src/tr_libs/boost/boost_1_49_0/boost/spirit/home/qi/string/detail/tst.hpp:80:エラー:「char」から非スカラー型への変換'boost :: spirit :: lex :: lexertl :: token <boost :: spirit :: line_pos_iterator <boost :: spirit :: multi_pass <std :: istreambuf_iterator <char、std :: char_traits <char>>、boost :: spirit :: iterator_policies :: default_policy <boost :: spirit :: iterator_policies :: ref_counted、boost :: spirit :: iterator_policies :: buf_id_check、boost :: spirit :: iterator_policies :: buffering_input_iterator、boost :: spirit :: iterator_policies :: split_std_deque >>>、boost :: mpl :: vector <std :: basic_string <char、std :: char_traits <char>、std :: allocator <char>>、boost :: spirit :: basic_string <std :: basic_string < char、std :: char_traits <char>、std :: allocator <char>>、symbol_type>、double、mpl _ :: na、mpl _ :: na、mpl _ :: na、mpl _ :: na、mpl _ :: na、mpl_ :: na、mpl _ :: na、mpl _ :: na、mpl _ :: na、mpl _ :: na、mpl _ :: na、mpl _ :: na、mpl _ :: na、mpl _ :: na、mpl _ :: na、mpl _ :: na、mpl _ :: na>、mpl _ :: bool_ <true>、long unsigned int> '要求された

tst.hppの80行目は次のとおりです。

                c = filter(*i);

レクサートークンをに変換しようとしているように見えます。これは、テーブルcharの文字タイプであると理解しています。symbols<char, int>気まぐれに、私は試しましたsymbols<ident, int>—トークンタイプはどこにidentありますか—しかし、それは明らかに文書化されたsymbols<>APIではなく、予想通り機能しませんでした。

(上記のサンプルのように、レクサーにこれらの識別子をトークンIDとして出力させないのはなぜかと疑問に思われるかもしれません。この特定のケースではそうすることができますが、シンボルを統合する一般的なkModeケースについては本当に興味があります。レクサーを使用した文法のテーブル。)

基本的に、私の質問はこれだと思います。qi::symbols<>このように使用して、Spiritレクサーからのトークンを照合することは可能ですか?

4

1 に答える 1

2

インスタンスを直接使用することはできませんsymbols...しかし、Phoenixセマンティックアクションを使用することで、冗長性を犠牲にしてインスタンスを実行できます。シンボルテーブルで検索したい値を表す場合はtoken_def<std::string>、次のようなルールに統合できます。

qi::rule<Iterator, locals<int const*>, int()> modename;
using namespace boost::phoenix;
// disambiguate symbols::find method (there are two!)
typedef const symtab_t::value_type * (symtab_t::*findfn_t)(std::string const&) const;
modename = tok.modeName[_a = bind(static_cast<findfn_t>(&symtab_t::find),
                                  cref(mode_table), _1),
                        _pass = _a,
                        if_(_a)[_val = *_a]];

これは、シンボルテーブルでトークンの文字列値を手動で検索し、存在しない場合は失敗し、それ以外の場合は、見つかった整数値をルールの結果属性にコピーします。

大文字と小文字を区別しない処理は、パーサーで(ルックアップを実行する前に小文字に変換することにより)、またはトークンがレクサーで作成されるときに変換することにより、セマンティックアクションを介して実行することもできます。後者のアプローチは次のように処理できます。

this->self +=
     modeName[ 
        let(_a = construct<std::string>(_start, _end)) [
            bind(&to_lower<std::string>, ref(_a),
                 // must supply even defaulted arguments
                 construct<std::locale>()),
            _val = _a
            ]
         ];

これにより、基になる範囲のコピーが作成されて呼び出さto_lowerれ、結果がトークン値として提供されます。

完全な例はここにあります

于 2015-04-11T20:40:25.843 に答える