2

boost::spirit grammar; 内に次のルールがあります。

rule = (qi::token(ABSTRACT) ^ qi::token(STATIC) ^ qi::token(FINAL))

このコンストラクトのタイプは次のとおりです。

boost::fusion::vector3<boost::optional<boost::iterator_range<std::string::iterator>>, boost::optional<boost::iterator_range<std::string::iterator>>, boost::optional<boost::iterator_range<std::string::iterator>>>

しかし、私がむしろ持っているのは;

boost::fusion::vector3<bool, bool, bool>

それぞれboolが対応する の値を持っている場合、ここで提案されているboost::optional<...> operator bool() constように、単一のケースで を使用します。ただし、このアプローチを適用すると、結果が得られます。qi::matches

(qi::matches[qi::raw_token(ABSTRACT)] ^ qi::matches[qi::raw_token(STATIC)] ^ qi::matches[qi::raw_token(FINAL)])

タイプはどれですか。

boost::fusion::vector3<boost::optional<bool>, boost::optional<bool>, boost::optional<bool>>

これら 3 つのトークンをランダムな順序で照合し、それらがブール値として一致したかどうかを取得するにはどうすればよいでしょうか?

4

1 に答える 1

2

は本当に必要なく、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);


    }
}
于 2013-09-10T14:57:29.320 に答える