2

私は、セマンティック アクションのない単純なコマンド ライン パーサーを SPIRIT でまとめようとしています。BOOST 1.52 を使用していますが、C++11 の機能は使用したくありません。文法の構文は次のとおりです。

[-p num1] [-j] [--jobs num2] str1 str2

オプションのパラメーターは任意の順序で指定できます。オプションのパラメーターのみを正常に解析しました。追加の必須の 2 つの文字列パーサーを追加すると、壊れます。「rstart」属性を明示的に書き留めて、「auto」を使用して型推定を回避しようとしても壊れます。どんな助けや提案も大歓迎です!

#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <boost/spirit/include/qi.hpp>
#include <boost/optional.hpp>
#include <boost/fusion/include/boost_tuple.hpp>

bool parse_line( const std::string&str,bool useStart1 )
{
    bool rc=false;
    namespace qi = boost::spirit::qi;

    using boost::spirit::ascii::space_type;
    using boost::spirit::ascii::space;
    using boost::spirit::ascii::char_;

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

    std::size_t num1    =88;
    bool        bool1   =false;
    std::size_t num2    =88;
    std::string str1,str2;

    qi::rule< std::string::const_iterator,std::string() > rstring=+~space;
    qi::rule< std::string::const_iterator,std::size_t() ,space_type > 
        rOption1=qi::lit( "-p" ) >> qi::int_;
    qi::rule< std::string::const_iterator,bool()        ,space_type >
        rOption2=qi::lit( "-j" ) >> qi::attr(true);
    qi::rule< std::string::const_iterator,std::size_t() ,space_type >
        rOption3=qi::lit( "--jobs" ) >> qi::int_;

#if defined(AAA)
    qi::rule<   std::string::const_iterator,
                boost::spirit::ascii::space_type,
                boost::tuple<   boost::optional<std::size_t>,
                                boost::optional<bool>,
                                boost::optional<std::size_t >
                >
            >
#endif

    auto rstart1 = ( rOption1 ^ rOption2 ^ rOption3 ) ;
    auto rstart2 = ( rOption1 ^ rOption2 ^ rOption3 ) >> rstring >> rstring;

    if( useStart1 )
        qi::phrase_parse( iter,str.end(),
            ( qi::lit( "-p" ) >> qi::int_ ) ^
            ( qi::lit( "-j" ) >> qi::attr(true) ) ^
            ( qi::lit( "--jobs" ) >> qi::int_ ),space,num1,bool1,num2);
    else
    {
    //  qi::phrase_parse(
    //      iter,str.end(),rstart2,space,num1,bool1,num2,str1,str2);
    }

    if(iter==str.begin())
        iter=str.begin(); //NOP
    else
    if(iter!=str.end())
        std::cerr<<"syntax error: "<<std::string(iter,str.end())<<"!\n\n";
    else
        rc=true;

    std::cout << "num1:" << num1 << std::endl;
    std::cout << "bool1:"<< bool1  << std::endl;
    std::cout << "num2:" << num2 << std::endl;
    std::cout << "str1:" << str1 << std::endl;
    std::cout << "str2:" << str2 << std::endl;

    return rc;
}

int main( int argc,char**argv )
{
    std::vector< std::string > testData1;
    testData1.push_back( "-p 100 -j" );
    testData1.push_back( "-j -p 100 --jobs 16" );
    testData1.push_back( "--jobs 16 -j -p 100" );

    for( std::vector< std::string >::const_iterator it=testData1.begin();
         it!=testData1.end(); ++it )
    {
        std::cout << "\nparsing string:" << *it << std::endl;
        parse_line( *it,true );
    }

    std::vector< std::string > testData2;
    testData2.push_back( "-p 100 -j ifile ofile" );
    testData2.push_back( "-j -p 100 --jobs 16 ifile ofile" );
    testData2.push_back( "--jobs 16 -j -p 100 ifile ofile" );

    for( std::vector< std::string >::const_iterator it=testData2.begin();
         it!=testData2.end(); ++it )
    {
        std::cout << "\nparsing string:" << *it << std::endl;
        parse_line( *it,false );
    }

    return 0;
}
4

1 に答える 1