![]() |
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 proto::_ as its grammar. Recall that proto::_ is the wildcard grammar that matches any expression. Since alternates in proto::or_<> are tried in order, and since the first alternate handles all terminals, the second alternate handles all (and only) non-terminals. Often enough, proto::when< _, some-transform > is the last alternate in a grammar, so for improved readability, you could use the equivalent proto::otherwise< some-transform >. | |
The next section describes this grammar further.