Boost logo

Boost Users :

Subject: Re: [Boost-users] [spirit][qi] Iteration / string iterator
From: Hartmut Kaiser (hartmut.kaiser_at_[hidden])
Date: 2010-10-03 10:55:34


> I have another question in general on Spirit.Qi. I read the manual many
> times and I still can't figure out how to read 'words' from the parser. In
> the following example I want to parse the name of something but I can not
> use the semantic assignment on std::string. ? The pattern is matched if I
> disable the assignment line but it doesn't compile with the line
> "[ref(name) = _1]". Again this is boost 1.43 with gcc 4.4.
>
> #include <boost/spirit/include/qi.hpp>
> #include <boost/spirit/include/phoenix_core.hpp>
> #include <boost/spirit/include/phoenix_operator.hpp>
>
> using boost::spirit::qi::double_;
> using boost::spirit::qi::int_;
> using boost::spirit::qi::lexeme;
> using boost::spirit::qi::char_;
> using boost::spirit::qi::_1;
> using boost::spirit::qi::phrase_parse;
> using boost::spirit::ascii::space;
> using boost::phoenix::ref;
>
> int main(){
> std::string test_line = " atom -1.4275 -1.84343 -1.9255 1
> center_atom 12";
> std::string::iterator first = test_line.begin(), last =
> test_line.end();
> double x=9999., y=9999., z=9999.; int type=-1;
> std::string name ;
> int index=-1;
> bool parsed = phrase_parse(first, last,
> (
> "atom" >> double_[ref(x) = _1] >> double_[ref(y) = _1] >>
> double_[ref(z) = _1] >> int_[ref(type) = _1] >>
> (+char_-' ')
> [ref(name) = _1] // < problem in this line, it

My guess is that you meant to write:

    lexeme[+(char_-' ') [phx::ref(name) += _1]]

adding the matched characters one by one to the string and avoiding to skip
the spaces in between characters. The expression +~char_(' ') is equivalent
but more efficient, btw. It means 'match everything but ' ' at least once'.

> doesn't compile
> >> int_[ref(index) = _1]
> ),
> space
> );
> if(not parsed) std::clog << "can not interpret line, values read can
> be incomplete" << std::endl;
> std::clog <<"just read: x = " << x << " y = " << y << " z = " << z <<
> " type = " << type << " name = " << name << " index = " << index <<
> std::endl;
> return 0;
> }

As a rule, I'd suggest to avoid semantic actions altogether. If you write:

    bool parsed = phrase_parse(first, last,
        "atom"
>> double_ >> double_ >> double_ >> int_ >> lexeme[+~char_(' ')] >>
int_,
        space,
        x, y, z, type, name, index
    );

you get the same result, just a lot simpler and cleaner.
Regards Hartmut
---------------
http://boost-spirit.com


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net