[Boost-users] [Boost.Spirit] Skippers for sub-grammars

184 views
Skip to first unread message

Vitaly Budovski

unread,
Oct 22, 2010, 4:50:53 AM10/22/10
to boost...@lists.boost.org
Hello,

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

Bill Somerville

unread,
Oct 22, 2010, 5:08:37 AM10/22/10
to boost...@lists.boost.org
Vitaly Budovski wrote:
> Hello,
>
> 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.
>
I believe you need to make it a template argument and pass it on to each
of the rules in the sub-grammar.

HTH
Bill Somerville.

Ovanes Markarian

unread,
Oct 22, 2010, 6:10:28 AM10/22/10
to boost...@lists.boost.org
Hi!


On Fri, Oct 22, 2010 at 10:50 AM, Vitaly Budovski <vbudovs...@gmail.com> wrote:
qi::rule<Iterator/*, sub_grammar_skipper<Iterator> */> start;

Change this line to:
qi::rule<Iterator, void(), sub_grammar_skipper<Iterator> > start;

This should work. void() is needed if you grammar has no attributes. If your grammar expands into smth. meaningful, than you must pass the type of the associated attribute, e.g. if you grammar outputs string, you will write the line like:

qi::rule<Iterator, std::string(), sub_grammar_skipper<Iterator> > start;

With kind regards, 
Ovanes

Vitaly Budovski

unread,
Oct 22, 2010, 6:16:35 AM10/22/10
to boost...@lists.boost.org
On 22 October 2010 21:10, Ovanes Markarian <om_b...@keywallet.com> wrote:
>> qi::rule<Iterator/*, sub_grammar_skipper<Iterator> */> start;
>
> Change this line to:
> qi::rule<Iterator, void(), sub_grammar_skipper<Iterator> > start;
> This should work. void() is needed if you grammar has no attributes. If your
> grammar expands into smth. meaningful, than you must pass the type of the
> associated attribute, e.g. if you grammar outputs string, you will write the
> line like:
> qi::rule<Iterator, std::string(), sub_grammar_skipper<Iterator> > start;
> With kind regards,
> Ovanes
>

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> >&]

Hartmut Kaiser

unread,
Oct 22, 2010, 8:06:43 AM10/22/10
to boost...@lists.boost.org
> 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.

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

budovski.cpp

Vitaly Budovski

unread,
Oct 22, 2010, 8:58:03 AM10/22/10
to boost...@lists.boost.org

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

OvermindDL1

unread,
Nov 1, 2010, 12:20:05 AM11/1/10
to boost...@lists.boost.org
On Fri, Oct 22, 2010 at 6:58 AM, Vitaly Budovski
<vbudovs...@gmail.com> wrote:
> On 22 October 2010 23:06, Hartmut Kaiser <hartmut...@gmail.com> wrote:
>>> 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.
>>
>> 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?

They can, that is what the skip()[] directive is for (see docs).

Reply all
Reply to author
Forward
0 new messages