Search code examples
c++boostgrammarboost-spirit

c++,boost::spirit parse the text


everyone!

I want to use boost::spirit to parse some string in text file.

Here is the sample in the text file:

IF([banana] and [apple] and [yellow] or [green] or [red] and [!white])

THEN

do sth...;

ELSE

do  sth...;

When i parse the string in the "if" bracket i got a trouble.

Here is my code:

if_rule=str_p(IF)>>ch_p("(")>>if_mem>>*("and"|"or">>if_mem)>>ch_p(")");

if_mem=ch_p("[")>>*~ch_p("]")>>ch_p("]");

It dose not work.It just parse the two "and" of the beginning and ignore the "or".

I've try several different grammer and still didn't work.

Thank you for your help!


Solution

  • You need to keep in mind that ultimately a Spirit expression is simply a (really ugly) c++ expression and thus it must follow c++ rules. Independently of the meaning that Spirit gives to the operators, they still follow c++ operator precedence rules. And so the expression "and" | "or" >> if_mem is not the same as ("and" or "or") followed by if_mem but in fact is "and" or ("or" followed by if_mem) since >> has a higher precedence than |. If you use ("and"|"or")>>if_mem you face another separate problem: since none of its arguments is a Spirit expression, the operator | is not the alternative parser, but the default c++ bitwise_or operator and that, as you discovered, causes a compiler error. The solution in this case is to make at least one of the arguments a Spirit expression by using (I'm just guessing since I don't use Spirit.Classic) something like (str_p("and")|str_p("or"))>>if_mem. (I guess "and">>if_mem | "or">>if_mem should also work, but it's probably a worse alternative).

    As sehe points in his comment, if you have a choice (unless you need to work with legacy code basically) you should probably use Spirit v2 since it will be far easier to get help.