开发者

boost spirit expectation failure

开发者 https://www.devze.com 2023-02-11 05:34 出处:网络
I want to parse a vector of the following struct: BOOST_FUSION_ADAPT_STRUCT( event_model::OTNDescriptor,

I want to parse a vector of the following struct:

BOOST_FUSION_ADAPT_STRUCT(
    event_model::OTNDescriptor,
    (int32_t, qualifier)
    (int32_t, ordinal)
    (std::string, name)
    (int32_t, type)
)

My grammer looks as follows:

struct swat_types_ : qi::symbols<char, unsigned>
{
    swat_types_()
    {
        using namespace event_model;

        add
            ("int", SWAT_INT4)
            ("int4", SWAT_INT4)
            ("int8", SWAT_IN开发者_StackOverflowT8)
            ("bigint", SWAT_INT8)
            ("string", SWAT_STRING)
        ;
    } 
} swat_types;

template<typename Iterator>
struct Rules
{
    qi::rule<Iterator, event_model::OTNDescriptor(), ascii::space_type>
        data_member_line;
    qi::rule<Iterator, std::string()> data_name;
    qi::rule<Iterator, void(int&, std::string&)> data_identifier_pair;
    qi::rule<   Iterator,
                std::vector< event_model::OTNDescriptor>(),
                ascii::space_type> dm_lines;

    Rules() {
        data_name =
            + (char_("a","z") | char_("A","Z") | char_('_'));

        data_identifier_pair =
            lexeme[int_ [ _r1 = _1] > ':' > data_name [ _r2 = _1]];

        data_member_line =
            eps [ at_c<0>(_val) = event_model::OTN_REQUIRED ]
            >>  -( no_case[lit("optional")]
                        [at_c<0>(_val) = event_model::OTN_OPTIONAL]
                |   no_case[lit("required")]
                        [at_c<0>(_val) = event_model::OTN_REQUIRED])
            > data_identifier_pair( at_c<1>(_val), at_c<2>(_val) )
            > no_case[swat_types [at_c<3>(_val) = _1]]

            > ';'
        ;
        //dm_lines = data_member_line >> data_member_line;
        dm_lines = data_member_line >> *(data_member_line);
    }
};

My Harnass looks like this:

std::string str4("REquireD 0:lala int4; REquireD 1:googoo int4; ");

std::string::const_iterator iter4=str4.begin();
std::string::const_iterator end4=str4.end();

std::vector<event_model::OTNDescriptor> res4;

r = phrase_parse(iter4, end4, rules.dm_lines, boost::spirit::ascii::space, res4);

for(std::vector<event_model::OTNDescriptor>::iterator it = res4.begin(); it < ires4.end(); it++)
{
    std::cout << it->name << "\n";
}

If I switch the rule specification from a kleene star specification to a sequence match no errors.

//dm_lines = data_member_line >> data_member_line;
dm_lines = data_member_line >> *(data_member_line);

otherwise I get an expectation error when trying to parse my example sentence (shown in harnass).

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::spirit::qi::expectation_failure<__gnu_cxx::__normal_iterator<char const*, std::string> > > >'
  what():  boost::spirit::qi::expectation_failure
Aborted

Ideally I want to write the rule like this dm_lines = +(data_member_line) (this doesn't work either). What is going on that causes the expectation failure when using '*' and '+' operators ? but NOT when matching a sequence ?. And how do I fix it.


The reason for the expectation failure is that as soon as you start using plus or Kleene, the embedded parser (data_member_line) will be invoked more than once. Its last invocation will naturally fail as no more input is available. In your case this event will be 'recognized' as late as by the first expectation point only as all components before that are optional (they never fail).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号