![]() |
Home | Libraries | People | FAQ | More |
Not all of C++'s overloadable operators are unary or binary. There is
the oddball operator()
-- the function call operator -- which can have any number of arguments.
Likewise, with Proto you may define your own "operators" that
could also take more that two arguments. As a result, there may be nodes
in your Proto expression tree that have an arbitrary number of children
(up to
,
which is configurable). How do you write a grammar to match such a node?
BOOST_PROTO_MAX_ARITY
For such cases, Proto provides the proto::vararg<>
class template. Its template argument is a grammar, and the proto::vararg<>
will match the grammar
zero or more times. Consider a Proto lazy function called fun()
that can take zero or more characters as arguments, as follows:
struct fun_tag {}; struct FunTag : proto::terminal< fun_tag > {}; FunTag::type const fun = {{}}; // example usage: fun(); fun('a'); fun('a', 'b'); ...
Below is the grammar that matches all the allowable invocations of fun()
:
struct FunCall : proto::function< FunTag, proto::vararg< proto::terminal< char > > > {};
The FunCall
grammar uses
proto::vararg<>
to match zero or
more character literals as arguments of the fun()
function.
As another example, can you guess what the following grammar matches?
struct Foo : proto::or_< proto::terminal< proto::_ > , proto::nary_expr< proto::_, proto::vararg< Foo > > > {};
Here's a hint: the first template parameter to proto::nary_expr<>
represents the node type, and
any additional template parameters represent child nodes. The answer
is that this is a degenerate grammar that matches every possible expression
tree, from root to leaves.