2017-08-01 2 views
1

私はスピリットパーサを使って、id 1234のような文字列を解析しています。それはインラインstart = qi::lit("id") >> qi::int_;と完全に動作しますが、それを別のqi :: grammar-based構造体に入れたいのではありません。失敗例についてブーストスピリットQiパーサーがqi :: grammarに組み込むときに機能しません

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

#include <iostream> 
#include <fstream> 

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

struct Context{}; 

template <typename Iterator, typename SkipParser> 
struct IdGrammar : qi::grammar<Iterator, SkipParser> 
{ 
    explicit IdGrammar(Context& out) : IdGrammar::base_type(start, "IdGrammar") 
    { 
     start = qi::lit("id") >> qi::int_; 
    } 

    qi::rule<Iterator, SkipParser> start; 
}; 

template <typename Iterator, typename SkipParser> 
struct MyGrammar : qi::grammar<Iterator, SkipParser> 
{ 
    explicit MyGrammar(Context& out) 
     : MyGrammar::base_type(start, "MyGrammar") 
    { 
     IdGrammar<Iterator, SkipParser> idGrammar(out); 
//  start = idGrammar >> *(',' >> idGrammar); // 1 = Parsing fails 
     start = idGrammar; // 2 = Parsing fails 
//  start = qi::lit("id") >> qi::int_; // 3 = Parsing succeeds 

     start.name("the start"); 
     qi::on_error<qi::fail>(
      start, 
      phoenix::ref(std::cout) << phoenix::val("Parsing error: expecting ") << qi::_4 // what failed? 
            << phoenix::val(" here: \"") 
            << phoenix::construct<std::string>(qi::_3, qi::_2) // iterators to error-pos, end 
            << phoenix::val("\"") 
            << std::endl); 
    } 

    qi::rule<Iterator, SkipParser> start; 
}; 

int main() 
{ 
    typedef std::string::const_iterator iterator_type; 
    Context ctx; 
    MyGrammar<iterator_type, qi::space_type> roman_parser(ctx); // Our grammar 

    std::string str = "id 5012"; 

    iterator_type iter = str.begin(), end = str.end(); 
    bool r = phrase_parse(iter, end, roman_parser, qi::space); 

    if (r && iter == end) 
    { 
     std::cout << "Parsing succeeded\n"; 
    } 
    else 
    { 
     std::string rest(iter, end); 
     std::cout << "Parsing failed\n"; 
     std::cout << "stopped at: \"" << rest << "\"\n"; 
    } 
} 

Run example on Coliru

出力(1および2)である:以下の例では例1、2及び3を参照してください

Parsing failed 
stopped at: "id 5012" 

は何ここに違いは?問題が無関係であると仮定して、整数の結果の割り当てを削除して、この例を最小限に保つことを念頭に置いてください。

答えて

1

idGrammarの有効期間は、コンストラクタスコープよりも長くする必要があります。 メンバー変数にする:

template <typename Iterator, typename SkipParser> 
struct MyGrammar : qi::grammar<Iterator, SkipParser> 
{ 
    explicit MyGrammar(Context& out) 
     : MyGrammar::base_type(start, "MyGrammar") 
      , idGrammar(out) 
    { 
     start = idGrammar >> *(',' >> idGrammar); // 1 = Now parsing succeeds 
//  start = idGrammar; // 2 = Now parsing succeeds 
//  start = qi::lit("id") >> qi::int_; // 3 = Parsing succeeds 

     start.name("the start"); 
     qi::on_error<qi::fail>(
      start, 
      phoenix::ref(std::cout) << phoenix::val("Parsing error: expecting ") << qi::_4 // what failed? 
            << phoenix::val(" here: \"") 
            << phoenix::construct<std::string>(qi::_3, qi::_2) // iterators to error-pos, end 
            << phoenix::val("\"") 
            << std::endl); 
    } 

    qi::rule<Iterator, SkipParser> start; 
    IdGrammar<Iterator, SkipParser> idGrammar; 
}; 
+0

もっと多くの選択肢で遊んでいる間、私は同じ結論に達しました。解析規則を構築するときには、一時的なものは存在しないかもしれません。例えば、私がやったもう1つの(馬鹿げた)試みは構造体フィールド 'qi :: rule idGrammar;' IdGrammar'インスタンスを割り当てようとしました。これは生涯の同じ問題です。 – AndiDog

関連する問題