Boost C++ Libraries Home Libraries People FAQ More

PrevUpHomeNext
Matching Vararg Expressions

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 BOOST_PROTO_MAX_ARITY, which is configurable). How do you write a grammar to match such a node?

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.


PrevUpHomeNext