は本当に必要なく、fusion::vector<bool,bool,bool>
ただ機能させたいだけだと思います。この仮定が間違っている場合は、コメントで何か言ってください。
ドキュメントでわかるように、順列パーサーの属性はtuple<optional<A>,optional<B>>
. あなたの場合、これは に変換されfusion::vector<optional<bool>,optional<bool>,optional<bool>>
ます。Spirit がアトリビュートを操作する方法のおかげで、このベクトルは単純な と互換性がありfusion::vector<bool,bool,bool>
ます。この場合、これは、オプションのベクトルのすべての空でないコンポーネント (順列パーサーによって実際に一致するもの) が対応する単純な bool ベクトルの 1 つに割り当てられ、この後者のベクトルの残りのコンポーネントが残ることを意味します。変更なし。
あなたの例で見られる問題は、qi::matches
ディレクティブ(常に成功する)と順列パーサー(順列セットの各要素は最大で1回発生する可能性がある)が機能する方法にあります。この問題は、以下のプログラムの出力で確認できます。
USING MATCHES: final abstract static
<abstract1>
<try>final abstract stati</try>
<success>final abstract stati</success>
<attributes>[0]</attributes>
</abstract1>
<static1>
<try>final abstract stati</try>
<success>final abstract stati</success>
<attributes>[0]</attributes>
</static1>
<final1>
<try>final abstract stati</try>
<success> abstract static</success>
<attributes>[1]</attributes>
</final1>
最初に試行するルールは ですabstract1
。その時点での入力は「最終」であるため、 の引数はqi::matches
失敗し、qi::matches
成功して false が返されます。はすでに成功しているためabstract1
、順列パーサーは再試行しません。Nextstatic1
が試行され、まったく同じ結果が得られます。その後、入力はまだ「最終」であり、試行されたルールは でありfinal1
、成功して true を返します。3 つの引数すべてが成功したため、順列パーサーは終了し、「abstract static」は解析されません。
あなたが望むことを行う1つの方法は、seheが回答で推奨する2番目のオプションに似たものを使用することです. を使用する必要があります(qi::raw_token(ABSTRACT) >> qi::attr(true)) ^ (qi::raw_token(STATIC) >> qi::attr(true)) ^ (qi::raw_token(FINAL) >> qi::attr(true))
。一致する場合はKEYWORD >> qi::attr(true)
true を返すことに成功し、それ以外の場合は失敗します。KEYWORD
前に述べたように、空のオプションに対応する最終ベクトルのコンポーネントは変更されないままなので、それらが false に初期化されていることを確認する必要があります (たとえば、デフォルト コンストラクターを使用)。
Coliru での実行:
#include <iostream>
#include <string>
#include <vector>
#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
struct class_info
{
class_info():abstract_(),static_(),final_(){}
bool abstract_;
bool static_;
bool final_;
};
BOOST_FUSION_ADAPT_STRUCT
(
class_info,
(bool, abstract_)
(bool, static_)
(bool, final_)
)
namespace qi=boost::spirit::qi;
template <typename Parser>
void parse_triplet(const std::string& test, const Parser& parser)
{
std::string::const_iterator iter=test.begin(), end=test.end();
class_info parsed_class;
bool result=qi::phrase_parse(iter,end,parser,qi::space,parsed_class);
if(!result)
{
std::cout << "The triplet could not be parsed. Unparsed: " << std::string(iter,end) << std::endl;
}
else
{
if(iter==end)
{
std::cout << "A triplet was parsed." << std::endl;
std::cout << parsed_class.abstract_ << parsed_class.static_ << parsed_class.final_ << std::endl;
}
else
{
std::cout << "A triplet was parsed, but part of the input remained unparsed." << std::endl;
std::cout << parsed_class.abstract_ << parsed_class.static_ << parsed_class.final_ << std::endl;
std::cout << "Unparsed: " << std::string(iter,end) << std::endl;
}
}
}
int main()
{
std::vector<std::string> tests;
tests.push_back("final abstract static");
tests.push_back("final abstract");
tests.push_back("static");
tests.push_back("static abstract");
qi::rule<std::string::const_iterator,bool(),qi::space_type> abstract1, abstract2, static1, static2, final1, final2;
abstract1 = qi::matches[qi::lit("abstract")];
abstract2 = qi::lit("abstract") >> qi::attr(true);
static1 = qi::matches[qi::lit("static")];
static2 = qi::lit("static") >> qi::attr(true);
final1 = qi::matches[qi::lit("final")];
final2 = qi::lit("final") >> qi::attr(true);
BOOST_SPIRIT_DEBUG_NODES( (abstract1)(abstract2)(static1)(static2)(final1)(final2) );
for(std::size_t cont=0; cont < tests.size(); ++cont)
{
//THIS IS WRONG
std::cout << "USING MATCHES: " << tests[cont] << std::endl;
parse_triplet(tests[cont],abstract1 ^ static1 ^ final1);
//THIS WORKS
std::cout << "USING EXPLICIT ATTRIBUTE: " << tests[cont] << std::endl;
parse_triplet(tests[cont],abstract2 ^ static2 ^ final2);
}
}