Boost::Spirit 2 Redux
Last dog watch, 8 bells (8:27 pm)

Well if you stopped by yesterday you may have read my post about Boost::Spirit 2 and the trouble I had converting to the new Spirit 2 library. Fortunately, Hartmut Kaiser, one of the Boost::Spirit authors must have a Google blog notification when Spirit is mentioned in a blog, because he left a comment with a suggestion for me earlier!

Unfortunately, I still can't seem to get qi::phrase_parse to work right. The problem is that I'm trying to match one of a set of increasingly complicated grammar structures (perhaps starting at the most complicated and working backwards would fix this issue…). So, here is my problem in gruesome detail:

I'm implementing a get command for a MUD, an online text-only game system. Since I'm writing it from scratch, I decided to use some of the most up-to-date tools I could find to do so, and Boost has some terrific libraries that make this possible. As far as I can discern, the get command can come in the following forms:

  1. get hammer
  2. get 20 nails
  3. get hammer 2 (the second hammer)
  4. get 20 nails 3 (20 of the 3rd type of nails visible)
  5. get hammer from toolbelt
  6. get 20 nails from bucket
  7. get hammer from toolbox 2 (the hammer from the second toolbox)
  8. get 20 nails from bucket 3 (you get the idea)
  9. get hammer 3 from toolbox 2
  10. get 20 nails 2 from bucket 3

The problem comes when using phrase_parse with an empty space skip-parser. Given the two rules:

bool res = qi::phrase_parse(first, str.end(),
				(
					+qi::alpha
				),
				' ',
				item
);

And

bool res = qi::phrase_parse(first, str.end(),
					(
						+qi::alpha
						>> "from"
						>> +qi::alpha
					),
					' ',
					item,
					container
);

If I check the phrase get hammer from bucket it matches rule one, because after you remove all the spaces from the string it's just one long word! This is an unexpected result, and even if I check rule two before rule one I only match rule one!

And now I'm really lost. I imagine there's a better way to do this, but I can't seem to figure it out. Also, since my allergies are going crazy, I've got to take the night off anyway. Anybody out there know of a solution?

3 Comments »

3 Responses to “Boost::Spirit 2 Redux”

  1. Sarah teh Crocheter says:

    I don't know exactly how boost spirit works or how you use it, but I know how compilers work! They were greedy... as in, the input would match up with the rule that GOT THE MOST STUFF.

    Maybe there's something you need to specify in your rule to avoid grabbing ALL TEH TEXTS. ???

  2. Sarah teh Crocheter says:

    I think Hartmut's article may be of assistance for you: http://boost-spirit.com/home/2010/02/24/parsing-skippers-and-skipping-parsers/

  3. Hey,

    well, I'm sorry I was inconcise in my comment yesterday. Surely, the Kleene operator (i.e. the '+') in +qi::alpha will invoke the skip parser in between matching every single character, which results in pulling together all input. What you need is lexeme[], a directive temporarily disabling skipping (http://tinyurl.com/35gbqj8):

    bool res = qi::phrase_parse(first, str.end(),
    qi::lexeme[+qi::alpha], ' ', item);

    which will match the first word as expected, stopping at the first space.

    Consequently, your second grammar needs to look like:

    qi::lexeme[+qi::alpha] >>
    "from" >> qi::lexeme[+qi::alpha]

    which will allow an arbitrary number of spaces in between the 3 elements.

    Regards Hartmut

Leave a Reply