2017-02-20 6 views
0

ブースト::スピリットを習得しようとしていて、Cスタイルの識別子の簡単な例に取り掛かりたい。以下の文法は、 'incompatible_start_rule'と主張してコンパイルしません。目標は、この文法が、デフォルトの属性伝播ルールのように、文字列のベクトルの代わりに文字列を返すことです。ブーストスピリット文法のカスタム属性

template <typename IT> 
struct cppIdentifier : qi::grammar<IT, std::string, space_type()> 
{ 

    cppIdentifier() : cppIdentifier::base_type(start) 
    { 
     start = char_("a-zA-Z_")[boost::phoenix::push_back(_val, _1)] 
       >> *(char_("a-zA-Z0-9_")[boost::phoenix::push_back(_val, _1)]); 
    } 

    qi::rule<IT, std::string, space_type> start; 
}; 

これを達成するためには何が必要ですか?

また、私は、この特定の問題のための代替的で便利なオプションが多数存在することはよく知っていますが、私は学問的にカスタム文法の属性タイプを操作する方法に興味がありますので、答えの代わりにコメントに。事前に

おかげで、

答えて

2

まず第一に、あなたは(もしあれば、と継承された属性タイプ)規則の出力属性タイプを指定するには、関数の署名スタイルのテンプレートパラメータを使用する必要があります。 qi::grammar<IT, std::string, space_type()>の代わりにqi::grammar<IT, std::string(), space_type>を試してください。

第二には、あなたが本当にここセマンティックアクションは必要ありません - しかし、あなたはフレーズパーサーを使用することを計画している場合、あなたはlexeme[]ディレクティブが必要になります:

template <typename IT> 
struct cppIdentifier : qi::grammar<IT, std::string(), qi::space_type> 
{ 
    cppIdentifier() : cppIdentifier::base_type(start) 
    { 
     start = qi::lexeme[char_("a-zA-Z_") >> *(char_("a-zA-Z0-9_"))]; 
    } 

    qi::rule<IT, std::string(), qi::space_type> start; 
}; 

最後に、あなたが渡していることを確認してくださいフレーズに対応するスキッパーオブジェクト:

std::string s = "HELLO 123"; 

cppIdentifier < std::string::const_iterator> id; 

std::string ident; 

qi::phrase_parse(s.cbegin(), s.cend(), id, qi::space_type(), ident); 

// without lexeme[], ident becomes "HELLO123", not "HELLO" 
+1

[タグ:boost-spirit]の[SO]タグに追加されました。あなたの助けが大いにありがとう! – sehe

+1

ありがとうございました!私はあなたの答えを含め、サイトから多くを学んだので、私が少しでも手助けができたら、私は試してみる。私は自分の答えを書くことからかなり学ぶことも知っています。 –

+0

はい!それはうまくいく、ありがとう。明らかに、ルールと文法のテンプレートの引数を詳しく調べる必要があります。 –