Search code examples
c++boost-spirit

Semantic Action Boost


This is taken from Boost Spirit ( a very watered down version )

template <typename Iterator>
    struct calculator : qi::grammar<Iterator, int(), ascii::space_type>
    {
        calculator() : calculator::base_type(expression)
        {
            qi::_val_type _val;
            qi::_1_type _1;
            qi::uint_type uint_;

            expression = term >> *('+' >> term)| ('-' >> term);
            term = uint_[&term_printer]


        qi::rule<Iterator, int(), ascii::space_type> term, expression;
    };
}

Now, normally, when you want to make use of semantic action, you'd write something like

expression = term >> *('+' >> term[&my_printer] | ('-' >> term[&my_other_printer]);

...

Now, let's say that when an instance of qi::rule term is found while parsing, there is a call to some other function term_printer(). Then, my_printer() will output whatever it's supposed to AFTER term_printer(). My question is, does anyone know of a way to make the call to my_printer() BEFORE term_printer(), upon the discovery of a '+' char (in this specific example)?

Some background if you are unfamiliar: http://boost-spirit.com/distrib/spirit_1_8_3/libs/spirit/doc/semantic_actions.html


Solution

  • You'll have to attach an action to the parser that is responsible for the +. Since a char is not a Spirit parser (making '+'[my_parser] invalid) this requires you to create the Spirit parser explicitly instead of relying on the shorthand notation. The shorthand notation is syntax sugar for qi::lit, so:

    //                     vvvvvvvvvvvv-- interesting part
    expression = term >> *(qi::lit('+')[my_printer] >> term) | ('-' >> term);
    

    The lit parser has no attribute, so my_printer has to be callable as my_printer() for this to work.