I've decided to break up my parser into sub-grammars to improve both
the readability and compile time. I'm now trying to specify a skip
parser for one of the sub-grammars, but I don't know how to do it. I'm
familiar with specifying a skip parser in the parse functions, but not
in the grammar itself. Could somebody please provide an example?
Thanks.
#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
using namespace boost::spirit;
using namespace boost::spirit::ascii;
template<class Iterator>
struct sub_grammar_skipper: qi::grammar<Iterator>
{
sub_grammar_skipper(): sub_grammar_skipper::base_type(start)
{
start =
(
*((char_ - eol) - lit(':')) >> lit(':') >> *blank >>
*(char_ - eol) >> eol
)
;
}
qi::rule<Iterator> start;
};
template<class Iterator>
struct sub_grammar: qi::grammar<Iterator>
{
sub_grammar(): sub_grammar::base_type(start)
{
string =
(
*(char_ - eol)
)
;
name %=
(
lit("NAME:") >> *blank >> string >> eol
)
;
start =
(
name
)
;
}
qi::rule<Iterator, std::string()> string;
qi::rule<Iterator, std::string()> name;
qi::rule<Iterator> start;
};
template<class Iterator>
struct test_grammar: qi::grammar<Iterator/*, sub_grammar_skipper<Iterator> */>
{
test_grammar(): test_grammar::base_type(start)
{
start =
(
sg >> int_
)
;
}
sub_grammar<Iterator> sg;
qi::rule<Iterator/*, sub_grammar_skipper<Iterator> */> start;
};
int main()
{
std::string str("NAME: John\nBLAH: blah\n10");
typedef std::string::const_iterator iterator;
iterator first = str.begin();
iterator last = str.end();
test_grammar<iterator> tg;
bool r = parse(first, last, tg);
if(r && first == last)
{
std::cout << "Success!\n";
}
else
{
std::cerr << "Failed to parse at: " << std::string(first, last) <<
std::endl;
return 1;
}
return 0;
}
_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users
HTH
Bill Somerville.
qi::rule<Iterator/*, sub_grammar_skipper<Iterator> */> start;
Hi,
using struct sub_grammar: qi::grammar<Iterator, void(),
sub_grammar_skipper<Iterator> > with or without the void() produces a
compilation error in gcc:
include/boost/spirit/home/qi/nonterminal/rule.hpp:280: error: no match
for call to ‘(const
boost::function<bool(__gnu_cxx::__normal_iterator<const char*,
std::basic_string<char, std::char_traits<char>, std::allocator<char> >
>&, const __gnu_cxx::__normal_iterator<const char*,
std::basic_string<char, std::char_traits<char>, std::allocator<char> >
>&, boost::spirit::context<boost::fusion::cons<boost::fusion::unused_type&,
boost::fusion::nil>, boost::fusion::vector0<void> >&, const
boost::spirit::qi::reference<const
boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*,
std::basic_string<char, std::char_traits<char>, std::allocator<char> >
>, boost::fusion::unused_type, boost::fusion::unused_type,
boost::fusion::unused_type, boost::fusion::unused_type> >&)>)
(__gnu_cxx::__normal_iterator<const char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >&, const
__gnu_cxx::__normal_iterator<const char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >&,
boost::spirit::context<boost::fusion::cons<boost::fusion::unused_type&,
boost::fusion::nil>, boost::fusion::vector0<void> >&, const
boost::fusion::unused_type&)’
/usr/include/boost/function/function_template.hpp:1006: note:
candidates are: R boost::function4<R, T1, T2, T3, T4>::operator()(T0,
T1, T2, T3) const [with R = bool, T0 =
__gnu_cxx::__normal_iterator<const char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >&, T1 = const
__gnu_cxx::__normal_iterator<const char*, std::basic_string<char,
std::char_traits<char>, std::allocator<char> > >&, T2 =
boost::spirit::context<boost::fusion::cons<boost::fusion::unused_type&,
boost::fusion::nil>, boost::fusion::vector0<void> >&, T3 = const
boost::spirit::qi::reference<const
boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*,
std::basic_string<char, std::char_traits<char>, std::allocator<char> >
>, boost::fusion::unused_type, boost::fusion::unused_type,
boost::fusion::unused_type, boost::fusion::unused_type> >&]
You need to pass the skipper type to the subgrammar (see attached).
Additionally you need to utilize phrase_parse() instead of parse to hand
down a skipper instance.
Regards Hartmut
---------------
http://boost-spirit.com
Hi Hartmut,
Thank you very much for the reply. I do have another question though:
Is it possible for the top level grammar to have its own skipper? If
there are multiple sub-grammars, can they also have a different
skipper each? If not, I guess I would have to put all the possible
alternatives into the one skipper grammar, right?
Regards,
Vitaly
They can, that is what the skip()[] directive is for (see docs).