0

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_INT8)
            ("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.

Hassan Syed
  • 20,075
  • 11
  • 87
  • 171
  • I have solved the problem by altering the expectation point of the data_identifier part, of the data_member_line rule, to a sequence operator. And it now works the way I want it to. I still want an explanation though, – Hassan Syed Feb 17 '11 at 12:59

1 Answers1

3

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).

hkaiser
  • 11,403
  • 1
  • 30
  • 35
  • Thanks Haimut, (rephrasing the answer for future reference) so because my sequence version says match 2. Whereas a kleene star and one-or-more operator, say match as much as you can, and because parser head moves forward to find the optional element(which in this case doesn't exist), and my expectation point prevents backtracking, backtracking is needed to exit with success. – Hassan Syed Feb 18 '11 at 12:33
  • Sorry for misspelling your name :D – Hassan Syed Feb 18 '11 at 13:38