2017-04-11 22 views
3

我是使用qi的新手,遇到了困難。我想解析等的輸入:使用boost解析兩個字符串向量:qi

X + Y + Z,A + B

成字符串的兩個向量。

我有代碼這樣做,但只有當語法解析單個字符。理想情況下,以下行應該是可讀的:

曦+葉+鄒敖+碧

使用簡單的更換,如elem = +(char_ - '+') % '+'無法解析,因爲它會消耗「」第一ELEM,但我還沒有找到一個簡單的方法來解決這個問題。

這是我的單字符代碼,以供參考:

#include <bits/stdc++.h> 

#define BOOST_SPIRIT_DEBUG 
#include <boost/fusion/adapted.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/phoenix.hpp> 

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

typedef std::vector<std::string> element_array; 

struct reaction_t 
{ 
    element_array reactants; 
    element_array products; 
}; 

BOOST_FUSION_ADAPT_STRUCT(reaction_t, (element_array, reactants)(element_array, products)) 

template<typename Iterator> 
struct reaction_parser : qi::grammar<Iterator,reaction_t(),qi::blank_type> 
{ 
    reaction_parser() : reaction_parser::base_type(reaction) 
    { 
     using namespace qi; 

    elem = char_ % '+'; 
    reaction = elem >> ',' >> elem; 

    BOOST_SPIRIT_DEBUG_NODES((reaction)(elem)); 
    } 
    qi::rule<Iterator, reaction_t(), qi::blank_type> reaction; 
    qi::rule<Iterator, element_array(), qi::blank_type> elem; 
}; 
int main() 
{ 

    const std::string input = "X + Y + Z, A + B"; 
    auto f = begin(input), l = end(input); 

    reaction_parser<std::string::const_iterator> p; 
    reaction_t data; 

    bool ok = qi::phrase_parse(f, l, p, qi::blank, data); 

    if (ok) std::cout << "success\n"; 
    else std::cout << "failed\n"; 

    if (f!=l) 
     std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n"; 
} 

回答

3

使用一個簡單的替換,如ELEM = +(char_ - '+')% '+',無法解析,因爲它會在第一個elem上消耗',',但我還沒有發現一個簡單的解決方法。

那麼,完整的(braindead)簡單的解決方案將使用+(char_ - '+' - ',')+~char_("+,")

真的,不過,我會做的規則element更具體的,如:

elem  = qi::lexeme [ +alpha ] % '+'; 

Boost spirit skipper issues約語義和船長

Live On Coliru

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

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

typedef std::vector<std::string> element_array; 

struct reaction_t 
{ 
    element_array reactants; 
    element_array products; 
}; 

BOOST_FUSION_ADAPT_STRUCT(reaction_t, (element_array, reactants)(element_array, products)) 

template<typename Iterator> 
struct reaction_parser : qi::grammar<Iterator,reaction_t(),qi::blank_type> 
{ 
    reaction_parser() : reaction_parser::base_type(reaction) { 
     using namespace qi; 

     elem  = qi::lexeme [ +alpha ] % '+'; 
     reaction = elem >> ',' >> elem; 

     BOOST_SPIRIT_DEBUG_NODES((reaction)(elem)); 
    } 
    qi::rule<Iterator, reaction_t(), qi::blank_type> reaction; 
    qi::rule<Iterator, element_array(), qi::blank_type> elem; 
}; 

int main() 
{ 
    reaction_parser<std::string::const_iterator> p; 

    for (std::string const input : { 
      "X + Y + Z, A + B", 
      "Xi + Ye + Zou , Ao + Bi", 
      }) 
    { 
     std::cout << "----- " << input << "\n"; 
     auto f = begin(input), l = end(input); 

     reaction_t data; 

     bool ok = qi::phrase_parse(f, l, p, qi::blank, data); 

     if (ok) { 
      std::cout << "success\n"; 
      for (auto r : data.reactants) { std::cout << "reactant: " << r << "\n"; } 
      for (auto p : data.products) { std::cout << "product: " << p << "\n"; } 
     } 
     else 
      std::cout << "failed\n"; 

     if (f != l) 
      std::cout << "Remaining unparsed: '" << std::string(f, l) << "'\n"; 
    } 
} 

打印:

----- X + Y + Z, A + B 
success 
reactant: X 
reactant: Y 
reactant: Z 
product: A 
product: B 
----- Xi + Ye + Zou , Ao + Bi 
success 
reactant: Xi 
reactant: Ye 
reactant: Zou 
product: Ao 
product: Bi