Boost logo

Boost Users :

Subject: Re: [Boost-users] [Spirit] question about alternative list expressions
From: Hartmut Kaiser (hartmut.kaiser_at_[hidden])
Date: 2010-05-13 19:39:34


> /*
> Hello,
>
> This code (second copy attached) compiles to recognize dotlists, ie "a",
> "a.b", etc.
> I want to report on incomplete list errors of the following kind
>
> a.
> a.#
>
> The parser now detects such errors by failing to parse them completely.
> Instead I want to expect an id after a '.'.
>
> In dotlist_grammar() I wanted to replace this expression
>
> start %= (id % '.') ;
>
> with this one
>
> start %= (id >> (*('.' > id))) ; // XXX

'>>' has difference operator precedence than '>', which means that Spirit is
not able to flatten the whole expression leading to the attribute type
mismatch you're seeing.

> but it won't compile. Neither will this
>
> start %= (id >> (*('.' >> id))) ; // XXX

Attribute-wise this will work. The problem is that the function signature
you're attaching doesn't match the attribute type exposed by the expression
it is attached to. It now exposes a fusion::vector<std::string,
std::vector<std::string> >.

> What's wrong? Is there a difference between the synthesized attributes of
> the two alternative list expressions? Or is it a different bug?
>
> P.S. Both expressions seem to work for int_ instead of id.

HTH
Regards Hartmut

---------------
Meet me at BoostCon
www.boostcon.com

>
> Thanks.
>
> */
> #include <boost/config/warning_disable.hpp>
> #include <boost/spirit/include/qi.hpp>
> #include <boost/fusion/include/adapt_struct.hpp>
> #include <boost/spirit/include/phoenix_core.hpp>
> #include <boost/spirit/include/phoenix_operator.hpp>
> #include <boost/spirit/include/phoenix_fusion.hpp>
> #include <boost/spirit/include/phoenix_stl.hpp>
> #include <boost/spirit/include/phoenix_object.hpp>
> #include <boost/fusion/include/adapt_struct.hpp>
> #include <boost/fusion/include/io.hpp>
> #include <boost/fusion/sequence.hpp>
> #include <boost/fusion/include/sequence.hpp>
>
> #include <boost/algorithm/string/trim.hpp>
>
> #include <iostream>
>
> namespace ecgp
> {
> using namespace std;
>
> namespace qi = boost::spirit::qi;
> namespace ascii = boost::spirit::ascii;
> namespace fusion = boost::fusion;
> namespace phoenix = boost::phoenix;
>
> typedef ascii::space_type space;
>
> // structures, etc.
> struct structure
> {
> vector<string> dotlist;
> int filler; // fusion requires >1 members?!
>
> void print(ostream& o) const
> {
> int i=0;
> BOOST_FOREACH(string s, dotlist)
> {
> if(++i > 1) o << '.';
> o << s;
> }
> }
> };
>
> ostream& operator<<(ostream& o, structure const & c)
> {
> c.print(o);
> return o;
> };
> }
>
> BOOST_FUSION_ADAPT_STRUCT(
> ecgp::structure,
> (std::vector<std::string>, dotlist)
> (int, filler) // fusion requires >1 members?!
> )
>
> namespace ecgp
> {
> // actions
>
> void print_str(string const & v)
> {
> cout << "str: ";
> cout << v << endl;
> }
>
> void print_dotlist(vector<string> const & v)
> {
> cout << "dotlist: ";
> int i=0;
> BOOST_FOREACH(string s, v)
> {
> if(++i > 1) cout << '.';
> cout << s;
> }
> cout << endl;
> }
>
> void print_structure(structure const & v)
> {
> cout << "structure: ";
> print_dotlist(v.dotlist);
> cout << endl;
> }
>
> // grammars
>
> template <typename Iterator> // recognize an identifier
> struct id_grammar : qi::grammar<Iterator, string(), space>
> {
> id_grammar() : id_grammar::base_type(start)
> {
> using ascii::alpha;
> using qi::lexeme;
>
> start
> %=
> lexeme[ +alpha ]
> [ &print_str ]
> ;
> }
> qi::rule<Iterator, string(), space> start;
> };
>
> template <typename Iterator> // recognize a dotlist, ie (string %
> '.')
> struct dotlist_grammar : qi::grammar<Iterator, vector<string>(),
> space>
> {
> dotlist_grammar() : dotlist_grammar::base_type(start)
> {
> using qi::int_;
> using qi::lexeme;
>
> start %=
> // (id >> (*('.' > id))) // XXX
> (id % '.')
> [ &print_dotlist ]
> ;
> }
> id_grammar<Iterator> id;
> qi::rule<Iterator, vector<string>(), space> start;
> };
>
> template <typename Iterator>
> struct structure_grammar : qi::grammar<Iterator,structure(),space>
> {
> structure_grammar() : structure_grammar::base_type(start)
> {
> using qi::eps;
> using qi::int_;
>
> start
> %=
> ( dotlist
> >>
> (int_ | eps) // filler
> )
> [ &print_structure ]
> ;
> }
> dotlist_grammar<Iterator> dotlist;
> qi::rule<Iterator, structure(), space> start;
> };
> }
>
> int
> main()
> {
> using namespace std;
> using namespace ecgp;
> using namespace boost;
>
> typedef string::const_iterator string_iterator;
>
> string s;
>
> cout << "enter a dotlist:\n";
>
> while (getline(cin, s))
> {
> trim(s);
>
> string_iterator iter = s.begin();
> string_iterator end = s.end();
>
> string target(iter, end);
>
> structure list_container;
> structure_grammar<string_iterator> g;
>
> bool r = phrase_parse(iter, end, g, boost::spirit::ascii::space,
> list_container);
>
> if (r && iter == end) {
> cout << "OK: " << target;
> cout << endl << endl;
> }
> else {
> cout << "FAIL";
>
> if(! r) cout << "(p)";
> if(iter != end) cout << "(e)";
>
> cout << ": " << target;
> cout << endl << endl;
> }
> cout << "enter a dotlist:\n";
> }
> return 0;
> }


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