Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext

4.2. Evaluating the expression

[Note] Note

Note that you can find everything that has been included and defined so far here.

It would be nice if we could evaluate the expression as well. Instead of returning a vector as the result of parsing, we should return the evaluated expression. For example the result of parsing "11 + 2" should be mpl_::integral_c<int, 13>.

Metaparse provides transform which we can use to implement this:

> #include <boost/metaparse/transform.hpp>

This can be used to transform the result of a parser. For example we have the sequence<int_token, plus_token, int_token> parser which returns a vector. We want to transform this vector into a number, which is the result of evaluating the expression. We need to pass transform the sequence<...> parser and a function which turns the vector into the result we need. First let's create this metafunction:

> #include <boost/mpl/plus.hpp>
> #include <boost/mpl/at.hpp>
> template <class Vector> \
...> struct eval_plus : \
...>   boost::mpl::plus< \
...>     typename boost::mpl::at_c<Vector, 0>::type, \
...>     typename boost::mpl::at_c<Vector, 2>::type \
...>   > {};

copy-paste friendly version

[Note] Note

Note that if the last character of your command is the \ character in Metashell, then the shell assumes that you will continue typing the same command and waits for that before evaluating your command. When Metashell is waiting for the second (or third, or fourth, etc) line of a command, it uses a special prompt, ...>.

What it does is that using boost::mpl::at_c it takes the first (index 0) and the third (index 2) elements of the vector that is the result of parsing with sequence<...> and adds them. We can try it out with an example vector:

> eval_plus< \
...>  boost::mpl::vector< \
...>    mpl_::integral_c<int, 11>, \
...>    mpl_::char_<'+'>, \
...>    mpl_::integral_c<int, 2> \
...>  >>::type
mpl_::integral_c<int, 13>

copy-paste friendly version

We can use eval_plus to build a parser that evaluates the expression it parses:

> #include <boost/mpl/quote.hpp>
> using exp_parser6 = \
...> build_parser< \
...>   transform< \
...>     sequence<int_token, plus_token, int_token>, \
...>     boost::mpl::quote1<eval_plus> \
...>   > \
...> >;

copy-paste friendly version

[Note] Note

Note that we have to use boost::mpl::quote1 to turn our eval_plus metafunction into a metafunction class.

transform parses the input using sequence<int_token, plus_token, int_token> and transforms the result of that using eval_plus. Let's try it out:

> exp_parser6::apply<BOOST_METAPARSE_STRING("11 + 2")>::type
mpl_::integral_c<int, 13>

We have created a simple expression parser. The following diagram shows how it works:

The rounded boxes in the diagram are the parsers parsing the input, which are functions (template metafunction classes). The arrows represent how the results are passed around between these parsers (they are the return values of the function calls).

It uses sequence to parse the different elements (the first number, the + symbol and the second number) and builds a vector. The final result is calculated from that vector by the transform parser.


PrevUpHomeNext