2017-04-11 65 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