
Larry Evans wrote:
On 04/04/2007 01:14 PM, Eric Niebler wrote:
They are part of proto's meta-grammar facility. If you want to know if an expression type E matches grammar G1 or G2, you use:
proto::matches<E, proto::or_<G1, G2> >
That's a compile-time boolean test. Proto::and_ behaves similarly. Like mpl::or_ and mpl::and_ (and like || and &&) these do short-circuit evaluation.
HTH,
That sort of helps. I guess I was just predisposed to thinking of them as doing something similar to spirit's alternative<L,R> and sequence<L,R> templates; however, I guess not. Maybe my confusion is somehow related to the possiblity of have placeholder's as arguments to the templates. I understand that this is related to proto's ability to do transform of the template expressions, OTOH, spirit doesn't transform templates, only runtime values (via the parse member function).
In short, I need to study proto some more :(
Proto has some novel ways of doing things, so your confusion is not surprising. But this is a good opportunity for me to dig into Proto's philosophy. In Spirit-1, alternate<> and sequence<> are containers. They *are* the expression template. They also have domain-specific behaviors (eg. parse() member functions) that make the expression template do that thing that Spirit does (parse). In proto, there is one container: expr<>. Proto's operator overloads glom smaller expr<>'s into larger ones, building a tree. By default, that tree has no behaviors (no parse() member function, for example).[*] So once you've built this tree, you'll need to do something with it. Proto gives you a couple of choices. One is proto::eval(), which lets you walk the tree and do domain-specific things at each node. Another choice is to transform the tree into another object that has the behaviors you want. For this, you write a domain-specific tree transformation by writing out your DSEL's grammar and attaching transforms to your grammar's rules. This is where proto::or_ and proto::and_ come in. Imagine in your DSEL, only terminals of type int and char* are allowed. Then you might define a Terminal rule in your grammar as follows: struct Terminal : proto::or_< proto::terminal<int> , proto::terminal<char*> > {}; When you write your tree transform, you might want to attach some transformation to the Terminal rule to, for example, turn char* into spirit::string_parser, or whatever. Proto's meta-grammar facilities are good for more than just tree transformations, by the way. You can use them with proto::matches<> to make compile-time decisions based on the structure of an expression. You can even use a proto meta-grammar to control proto's operator overloading! When you do that, only those operators which build valid expressions, as determined by your meta-grammar, are considered. [*] There is a way in proto to add domain-specific behaviors, like extra member functions, directly to the expression tree. It's called proto::extends<>. Just so you know. -- Eric Niebler Boost Consulting www.boost-consulting.com