boost spirit std :: vector <unsigned>已解析但未捕获</unsigned>

时间:2012-11-22 06:24:06

标签: c++ boost-spirit

我正在尝试解析并将此字符串"{ABC,HIJ}:{10,15,20}"捕获到struct indicator_rec中。

解析成功,但只有第一组{ABC,HIJ}被捕获到std::vector<std::string>字段中。

第二部分{10,15,20}被正确解析,但无法进入第二个字段std::vector<unsigned>

我做错了什么?

输出:

<equation>
  <try>{ABC,HIJ}:{10,15,20}</try>
  <indicator>
    <try>{ABC,HIJ}:{10,15,20}</try>
    <fail/>
  </indicator>
  <indicators>
    <try>{ABC,HIJ}:{10,15,20}</try>
    <indicator>
      <try>ABC,HIJ}:{10,15,20}</try>
      <success>,HIJ}:{10,15,20}</success>
      <attributes>[[A, B, C]]</attributes>
    </indicator>
    <indicator>
      <try>HIJ}:{10,15,20}</try>
      <success>}:{10,15,20}</success>
      <attributes>[[H, I, J]]</attributes>
    </indicator>
    <success>:{10,15,20}</success>
    <attributes>[[[A, B, C], [H, I, J]]]</attributes>
  </indicators>
  <parameters>
    <try>{10,15,20}</try>
    <parameter>
      <try>10,15,20}</try>
      <success>,15,20}</success>
      <attributes>[]</attributes>
    </parameter>
    <parameter>
      <try>15,20}</try>
      <success>,20}</success>
      <attributes>[]</attributes>
    </parameter>
    <parameter>
      <try>20}</try>
      <success>}</success>
      <attributes>[]</attributes>
    </parameter>
    <success></success>
    <attributes>[[]]</attributes>
  </parameters>
  <success></success>
  <attributes>[[[[A, B, C], [H, I, J]], []]]</attributes>
</equation>

代码:

#define BOOST_SPIRIT_DEBUG
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/classic_symbols.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>

#include <boost/algorithm/string.hpp>
#include <boost/regex.hpp>   // std::regex not fully implemented in stdc++ yet

#include <string>
#include <map>
#include <utility>
#include <functional>

// -----------------------------------------------------------------------------
namespace client
{
    namespace qi      = boost::spirit::qi;
    namespace ascii   = boost::spirit::ascii;
  namespace spirit  = boost::spirit;
    namespace phoenix = boost::phoenix;

    // ---------------------------------------------------------------------------
    struct indicator_rec
    {
    public:
        indicator_rec() { }

        std::vector<std::string>  m_indicators;
        std::vector<unsigned>     m_parameters;
    };
}

BOOST_FUSION_ADAPT_STRUCT(
    client::indicator_rec,
    (std::vector<std::string>,  m_indicators)
    (std::vector<unsigned>,     m_parameters)
)

namespace client
{
    // ---------------------------------------------------------------------------
    template <typename Iterator>
    struct system_parser : 
        qi::grammar<Iterator, ascii::space_type, indicator_rec()>
    {
            system_parser() : 
                system_parser::base_type(equation)
            {
                    using qi::double_;
                    using qi::_val;
                    using qi::_1;
                    using boost::spirit::ascii::string;

                    equation %=
                            (indicator | indicators)                      
                            >> ':'
                            >> (parameters | parameter)
                            ;

                    indicator %= (string("ABC")|string("HIJ"))
                            ;

                    indicators %= '{' >> (indicator % ',') >> '}'
                            ;

                    parameter %= qi::uint_
                            ;

                    parameters %= '{' >> (parameter % ',') >> '}'
                            ;

                    BOOST_SPIRIT_DEBUG_NODE(equation);
                    BOOST_SPIRIT_DEBUG_NODE(parameter);
                    BOOST_SPIRIT_DEBUG_NODE(parameters);
                    BOOST_SPIRIT_DEBUG_NODE(indicator);
                    BOOST_SPIRIT_DEBUG_NODE(indicators);
            }

            qi::rule<Iterator, ascii::space_type, indicator_rec()>
                equation;

            qi::rule<Iterator, ascii::space_type, std::vector<std::string>()> 
                indicators;

            qi::rule<Iterator, ascii::space_type, std::string()> 
                designator, indicator;

            qi::rule<Iterator, ascii::space_type, unsigned> 
                parameter;

            qi::rule<Iterator, ascii::space_type, std::vector<unsigned>()> 
                parameters;
    };

    template <typename Iterator>
    bool parse_system( Iterator first, Iterator last, client::indicator_rec& rec )
    {
        system_parser<Iterator> parser;
        bool r = qi::phrase_parse( first, last, parser, ascii::space, rec );
        if (first != last) // fail if we did not get a full match
            return false;
        return r;
    }

    template <typename Iterator>
    bool parse_universe(Iterator first, Iterator last, std::vector<std::string>& v)
    {
        bool r = qi::phrase_parse(first, last,
                              //  Begin grammar -------------------------------------
                              (
                                                        (+(qi::alpha|qi::char_( "_" ))) >> ':' >> '{' >>
                                                            (+~qi::char_(",}")) % ','
                                                            >> '}'
                              )
                              ,
                              //  End grammar ---------------------------------------
                              ascii::space, v);

        if (first != last) // fail if we did not get a full match
            return false;
        return r;
    }
}

main( int argc, char* argv[] )
{
    std::string calculator( "{ABC,HIJ}:{10,15,20}" );
    client::indicator_rec rec;
    client::parse_system( calculator.begin(), calculator.end(), rec );
}

1 个答案:

答案 0 :(得分:2)

从昨天开始,{p> This question大致相同。每个规则的签名都需要使用此函数声明符语法。括号前的类型是规则中的“返回”属性(其合成属性),里面的类型是继承的属性(您可以找到使用它们的简单示例here)。

因此,如果您不使用这些继承的属性,则必须在规则声明中使用rule_attribute_type()。理想情况下,如果不这样做会导致编译器错误,但显然由于rule's template parameters的异构性质,很遗憾不会发生这种情况。