![]() |
Home | Libraries | People | FAQ | More |
We've already seen how to use expression generators like proto::terminal<>
and proto::shift_right<>
as grammars. We've also seen proto::or_<>,
which we can use to express a set of alternate grammars. There are a
few others of interest; in particular, proto::if_<>,
proto::and_<> and proto::not_<>.
The proto::not_<> template is the simplest.
It takes a grammar as a template parameter and logically negates it;
not_<Grammar>
will match any expression that Grammar
does not match.
The proto::if_<> template is used
together with a Proto transform that is evaluated against expression
types to find matches. (Proto transforms will be described later.)
The proto::and_<> template is like
proto::or_<>, except that each
argument of the proto::and_<> must match in order
for the proto::and_<> to match. As an example,
consider the definition of CharString
above that uses proto::exact<>. It could have been
written without proto::exact<> as follows:
struct CharString : proto::and_< proto::terminal< proto::_ > , proto::if_< boost::is_same< proto::_value, char const * >() > > {};
This says that a CharString
must be a terminal, and its value type must be the
same as char const
*. Notice the template argument
of proto::if_<>: boost::is_same< proto::_value, char const * >(). This is Proto transform that compares
the value type of a terminal to char
const *.
The proto::if_<> template has a couple
of variants. In addition to if_<Condition> you can also say if_<Condition, ThenGrammar> and if_<Condition, ThenGrammar, ElseGrammar>. These let you select one sub-grammar
or another based on the Condition.