2

これがサンプルコードです

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>

#include <iostream>
#include <string>

namespace qi = boost::spirit::qi;

    template <typename Iterator>
    struct input : qi::grammar<Iterator, unsigned()>
    {
        input() : input::base_type(start)
        {
            using qi::lit;
            using qi::double_;

            start = lit("ADD") 
                            >> +(
                                    +lit(" ")
                                    >> double_ 
                                    >> +lit(" ")
                                    >> double_
                                ); 
        }

        qi::rule<Iterator, unsigned()> start;
    };

int main()
{

    input<std::string::const_iterator> input_parser; // Our grammar
    std::string str = "ADD 1132.324 2342.234";
    unsigned result;

    std::string::const_iterator iter = str.begin();
    std::string::const_iterator end = str.end();

    bool r = qi::parse(iter, end, input_parser, result);

}

次のエラーが表示されます。

/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:201: 「boost::spirit::qi::rule& boost::spirit::qi::rule::」からインスタンス化operator=(const Expr&) [with Expr = boost::proto::exprns_::expr&, const boost::proto::exprns_::expr&>, 1l>&, const boost::spirit::terminal&>, 2l> &, const boost::proto::exprns_::expr&>, 1l>&>, 2l>&, const boost::spirit::terminal&>, 2l>&>, 1l>&>, 2l>, イテレータ = __gnu_cxx ::__normal_iterator, std::allocator > >, T1 = unsigned int ()(), T2 = boost::fusion::unused_type, T3 = boost::fusion::unused_type, T4 = boost::fusion::unused_type] mini.c++:34: 「input::input() [with Iterator = __gnu_cxx::__normal_iterator, std::allocator > >]」からインスタンス化された mini.c++:49: ここからインスタンス化 /usr/local/include/boost/spirit/home/qi/operator/plus.hpp:62: エラー: 「struct boost::spirit」に「type」という名前の型がありません::traits::container_valueâ€</p>

奇妙な部分は、マイナス (-) 演算を使用する場合、つまり

start = lit("ADD") 
                            >> -(
                                    +lit(" ")
                                    >> double_ 
                                    >> +lit(" ")
                                    >> double_
                                );

...それは完全にうまくコンパイルされます!

gcc 4.3.4 でコンパイルします。

4

1 に答える 1

2

開始ルールによって公開される属性は ですがunsigned、plus-parser はラップされた要素の属性を保持するコンテナー タイプを公開します。ドキュメントの属性伝播ルールは次のとおりです。

a: A --> +a: vector<A>

(つまり、パーサーが type の属性を公開する場合、パーサーはa、たとえば のインスタンスを保持する (標準) コンテナーを公開します)。A+aAstd::vector<A>

あなたの場合、埋め込みパーサーは を公開しdoubleます。このため、期待どおりに動作させるには、コードを変更する必要があります。

template <typename Iterator>
struct input : qi::grammar<Iterator, std::vector<double>()>
{
    input() : input::base_type(start)
    {
        using qi::lit;
        using qi::double_;
        start = lit("ADD") >> +(+lit(" ") >> double_ >> +lit(" ") >> double_);
    }

    qi::rule<Iterator, std::vector<double>()> start;
};

int main() 
{
    input<std::string::const_iterator> input_parser; // Our grammar
    std::string str = "ADD 1132.324 2342.234";

    std::vector<double> result;
    std::string::const_iterator iter = str.begin();
    std::string::const_iterator end = str.end();
    bool r = qi::parse(iter, end, input_parser, result);  
} 

しかし残念なことに、物事は思ったほど簡単ではありません。Spirit の現在のバージョンには、コードの動作を妨げるバグがあります (まもなくリリースされる Boost V1.46 にもまだこのバグがありますが、SVN トランクで修正されています)。問題は、 plus が埋め込まれた要素を提供されたコンテナーに「フラット化」しないため、上記のコードによって二重に解析されたすべての秒が失われることです。

回避策は、プラス内で複数の属性を公開するシーケンスを避けることです。

start = lit("ADD") >> +(+lit(" ") >> double_);

その後、解析された要素の数が偶数であることを確認します。

補足:入力の要素間の空白をスキップしたいようです。これは、スキップ パーサーを使用することで簡単に実現できます。

template <typename Iterator>
struct input : qi::grammar<Iterator, std::vector<double>(), qi::space_type>
{
    input() : input::base_type(start)
    {
        using qi::lit;
        using qi::double_;
        start = lit("ADD") >> +double_;
    }

    qi::rule<Iterator, std::vector<double>(), qi::space_type> start;
};

int main() 
{
    input<std::string::const_iterator> input_parser; // Our grammar
    std::string str = "ADD 1132.324 2342.234";

    std::vector<double> result;
    std::string::const_iterator iter = str.begin();
    std::string::const_iterator end = str.end();
    bool r = qi::phrase_parse(iter, end, input_parser, qi::space, result);  
} 

同時に、上記の問題を回避します。

于 2011-01-23T17:57:34.027 に答える