Question

I'm parsing some input that is vaguely structured like C-ish code. Like this:

Name0
{
 Name1
 {
  //A COMMENT!!

  Param0 *= 2
  Param2 = "lol"
 }
}

Part of that is comments, which I want to totally ignore (and it's not working). I consider two things to be a node, the named scopes (category rule) like Name0 {} and the values (param rule) like Param0 *= 2... then there is comment. I've tried setting things up like this:

typedef boost::variant<boost::recursive_wrapper<Category>, Param> Node;

qi::rule<Iterator, Node(), ascii::space_type> node;

So the node rule puts either a Category or a Param in a variant. Here are the other rules (I've omitted some rules that don't really matter for this):

qi::rule<Iterator> comment; //comment has no return type

qi::rule<Iterator, Category(), ascii::space_type> category;
qi::rule<Iterator, Param(), ascii::space_type> param;

And their actual code:

comment = "//" >> *(char_ - eol);

param %=
 tagstring
 >> operators
 >> value;

category %=
 tagstring
 >> '{'
 >> *node
 > '}';

node %= comment | category | param;

comment is setup to use = instead of %=, and it has no return type. However, comments end up creating null Categorys in my output Nodes wherever they show up. I've tried moving comment out of the node rule and into category like this:

category %=
 tagstring
 >> '{'
 >> *(comment | node)
 > '}';

And various other things, but those null entries keep popping up. I had to make comment output a string and put std::string in my Node variant just to sorta catch them, but that messes up my ability to stick in commenting in other parts of my rules (unless I actually grab the string in every location).

How can I completely ignore the comment and have it not show up in any output in any way?

edit: You'd think omit would do it, but didn't seem to change anything...

edit 2: Referencing this SO answer, I have a shaky solution in this:

node %= category | param;

category %=
 tagstring
 >> '{'
 >> *comment >> *(node >> *comment)
 > '}';

However, I want to try to stick comments into all sorts of places (between tagstring and {, in my unshown root rule between root categorys, etc). Is there a simpler method than this? I was hoping it could be done with a simple >> commentwrapper plugged into wherever I wanted...

Was it helpful?

Solution

Alright, so making your own skipper isn't too bad. And it elegantly solves this commenting problem, just as Mike M said. I define my rules in a struct called Parser that is templated with an Iterator. Had to make some adjustments to use the skipper. First, here is the skipper which is defined in Parser with all my other rules:

typedef qi::rule<Iterator> Skipper;
Skipper skipper;

So skipper is a rule of type Skipper. Here is what my Parser struct looked like originally, where it was using the ascii::space rule of type ascii::space_type as its skipper, which IS NOT the same type as qi::rule<Iterator> that skipper is based on!

struct Parser : qi::grammar<Iterator, std::vector<Category>(), ascii::space_type>
{
 qi::rule<Iterator, std::vector<Category>(), ascii::space_type> root;

 ...

So every instance of ascii::space_type in the rule templates must be replaced with Skipper! That includes other rules besides the root that is shown here, such as param and category from my question. Leaving any remnant of the old ascii::space_type behind gives cryptic compiler errors.

struct Parser : qi::grammar<Iterator, std::vector<Category>(), qi::rule<Iterator>>
{
 typedef qi::rule<Iterator> Skipper;
 Skipper skipper;

 qi::rule<Iterator, std::vector<Category>(), Skipper> root;

 ...

The original skipper was merely space, mine is now an alternative of space and comment. No old functionality (space skipping) is lost.

skipper = space | comment;

Then the phrase_parse call needs to be adjusted from this old version that used ascii::space:

bool r = phrase_parse(iter, end, parser, ascii::space, result);

to

bool r = phrase_parse(iter, end, parser, parser.skipper, result);

And now comments disappear as easily as white space. Awesome.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top