3

global解析中に、セマンティック アクションでのみ設定する必要があるいくつかの属性があります (それらは解析対象のデータから派生したものであり、変数と依存関係を回避したいBOOST_FUSION_ADAPT_STRUCTだけでなく、複数のコードで再利用できるようにコードを汎用にする必要があるため)種類)。渡された複数の変数を使用するqi::phrase_parse と、コンパイル エラーのリストが非常に長くなります。私はひどく助けが必要です:-)

#define BOOST_RESULT_OF_USE_DECLTYPE
#define BOOST_SPIRIT_USE_PHOENIX_V3

#include <boost/function.hpp>
#include <boost/phoenix/fusion.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>

#include <iostream>
#include <string>
#include <climits>

namespace qi = boost::spirit::qi;
namespace ph = boost::phoenix;
namespace ascii = boost::spirit::ascii;

int main( int argc, char**argv )
{
    bool rc;
    std::string input("");

    //Test case 1 works fine
    {
        auto iter( input.begin() );
        auto last( input.end() );
        int val1=33;
        rc = qi::phrase_parse( iter, last, qi::eps[ qi::_val=11 ] , 
                   ascii::space, val1 ) && iter==last;
        if( rc )
            std::cout << "val1=" << val1 << std::endl; 
    }
    //Test case 2 does not compile
    {
        auto iter( input.begin() );
        auto last( input.end() );
        int val1=33;
        int val2=0;
        rc = qi::phrase_parse( iter, last, 
                qi::eps[ ph::at_c<0>(qi::_val)=1,ph::at_c<1>(qi::_val)=2 ],
                ascii::space, val1,val2 ) && iter==last;
        if( rc )
            std::cout << "val1=" << val1 << 
                         " val2=" << val2 << std::endl;         
    }
    //Test case 3 works fine
    {
        auto iter( input.begin() );
        auto last( input.end() );
        int val1=33;
        int val2=0;
        rc = qi::phrase_parse( iter, last,
                qi::attr(1)>>qi::attr(2),
                ascii::space, val1,val2 ) && iter==last;
        if( rc )
            std::cout << "val1=" << val1 <<
                         " val2=" << val2 << std::endl;
    }

    return 0;
}

「カスタマイズされた」 my_phrase_parsecv_and_heを取得しましたが、実行したい完全なテスト ケースでコンパイルが中断されます。

template<typename T,typename R>
void testParser( R rule )
{
    for ( const auto input : std::vector< std::string >{ "5 1.0 2.0 3.0 4.0 5.0", "1 1.0", "0" , "", "2 3 ab" } )
    {
        bool rc;
        T maxValue;
        T minValue;
        auto iter( input.begin() );
        auto last( input.end() );
        std::vector< T > v;
        rc = my_phrase_parse( iter, last,
            qi::eps[
                     ph::at_c<0>(qi::_val)=std::numeric_limits<T>::max(),
                     ph::at_c<1>(qi::_val)=std::numeric_limits<T>::min()
                   ]
            >> -( qi::omit[ qi::int_] 
            >> *rule[ ph::if_(ph::at_c<0>(qi::_val)>qi::_1)[ ph::at_c<0>(qi::_val)=qi::_1 ],
                      ph::if_(ph::at_c<1>(qi::_val)<qi::_1)[ ph::at_c<1>(qi::_val)=qi::_1 ]
                    ] )
                ,ascii::space, minValue, maxValue,v ) && iter==last;
        std::cout << ( rc ? "ok :`" : "err:`" ) << input << "` -> ";
        if( rc )
        {
            std::cout << "min=" << minValue << " max=" << maxValue << "\t";
            std::copy( v.begin(), v.end(), std::ostream_iterator<T>( std::cout," " ));
        }
        else
            std::cout << *iter;
        std::cout << std::endl;
    }
}
...
    testParser<double>( qi::double_ );
4

3 に答える 3

1

これはworkaround私の最初の問題です:

#define BOOST_RESULT_OF_USE_DECLTYPE
#define BOOST_SPIRIT_USE_PHOENIX_V3

#include <boost/function.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>

#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
#include <climits>

namespace qi = boost::spirit::qi;
namespace ph = boost::phoenix;
namespace ascii = boost::spirit::ascii;

template<typename T,typename R>
void testParser( R rule )
{
    for ( const auto &input : std::vector< std::string >{ "5 1.0 2.0 3.0 4.0 5.0" } )
    {
        bool rc=false;
        T maxValue, minValue;
        auto iter( input.begin() ), last( input.end() );
        std::vector< T > data;

        qi::rule< decltype(iter),std::vector<T>( T&, T& ),qi::space_type > mrule;

        mrule %=
            qi::eps[ qi::_r1=std::numeric_limits<T>::max(),
                     qi::_r2=std::numeric_limits<T>::min() ] >>
             -( qi::omit[ qi::int_[ ph::reserve( qi::_val,qi::_1 ) ] ]
                >> *rule[ ph::if_(qi::_r1>qi::_1)[ qi::_r1=qi::_1 ],
                          ph::if_(qi::_r2<qi::_1)[ qi::_r2=qi::_1 ]
                        ] );

        rc = qi::phrase_parse( iter, last, mrule( ph::ref(minValue), ph::ref(maxValue) ), qi::space, data ) && iter==last;

    std::cout << ( rc ? "ok :`" : "err:`" ) << input << "` -> ";
    if( rc )
    {
        std::cout << "min=" << minValue << " max=" << maxValue << "\t";
        std::copy( data.begin(), data.end(), std::ostream_iterator<T>( std::cout," " ));
        }
        else
            std::cout << *iter;
        std::cout << std::endl;
    }
}

int main( int argc, char**argv )
{
    testParser<double>( qi::double_ );
    return 0;
}
于 2013-08-25T23:02:51.747 に答える
0

問題が正しく表示されることを願っていますが、それが少し異なる場合でも、手間をかけずにいくつかの値を保存できます。

struct data {
  int _a;
  int _b;
  data(int a, int b) : _a(a), _b(b) {};
};

そしてそれを構築します:

qi::eps[qi::_val = phx::construct<data>(1, 2)]
于 2013-08-25T21:40:52.637 に答える