![]() |
Home | Libraries | People | FAQ | More |
Most grammars are a little more complicated than the one in the preceding section. For the sake of illustration, let's define a rather nonsensical grammar that matches any expression and recurses to the leftmost terminal and returns its value. It will demonstrate how two key concepts of Proto grammars -- alternation and recursion -- interact with transforms. The grammar is described below.
// A grammar that matches any expression, and a function object // that returns the value of the leftmost terminal. struct LeftmostLeaf : proto::or_< // If the expression is a terminal, return its value proto::when< proto::terminal< _ > , proto::_value > // Otherwise, it is a non-terminal. Return the result // of invoking LeftmostLeaf on the 0th (leftmost) child. , proto::when< _ , LeftmostLeaf( proto::_child0 ) > > {}; // A Proto terminal wrapping std::cout proto::terminal< std::ostream & >::type cout_ = { std::cout }; // Create an expression and use LeftmostLeaf to extract the // value of the leftmost terminal, which will be std::cout. std::ostream & sout = LeftmostLeaf()( cout_ << "the answer: " << 42 << '\n' );
We've seen proto::or_<>
before. Here it is serving two roles. First, it is a grammar that matches
any of its alternate sub-grammars; in this case, either a terminal or
a non-terminal. Second, it is also a function object that accepts an
expression, finds the alternate sub-grammar that matches the expression,
and applies its transform. And since LeftmostLeaf
inherits from proto::or_<>
,
LeftmostLeaf
is also
both a grammar and a function object.
![]() |
Note |
---|---|
The second alternate uses |
The next section describes this grammar further.