
Larry Evans wrote:
On 03/03/08 15:51, Eric Niebler wrote:
Larry Evans wrote:
or did you mean shift_right<L,R> is a grammar when L and R are grammars?
That is also true. This is a short-hand, provided for convenience.
shift_right<L,R>::type is *very* simple. It is expr<tag::shift_right, args2<L, R> >. Always.
Unexpected again. I jumped to the conclusion that expr was for expressions, not grammars.
A not unreasonable conclusion to jump to, considering that it's called "expr" and not "expr_or_grammar" or "tagged_heterogeneous_container". I feel the name "expr" is appropriate because it's more of an expression than anything else due to its operator overloads that build other expressions. The fact that Proto reuses this template as a grammar type is done mainly for a the deep symmetry that results: any expression type is also a grammar that matches itself -- matches<X,X> is trivially true, regardless of how complicated X is. See below.
So then is shift_right<L,R>::type, when L and R are grammars, the same as shift_right<L,R>?
Yes, they are equivalent.
It's just a 2-element container and a tag. If L and R are expressions, it is an expression. If they're grammars, it is a grammar, suitable for use as the second template parameter to proto::matches. It is simple, IMO, and leads to a very straightforward implementation of proto::matches<>. See, for instance, how the behavior of proto::matches<> is specified in terms of expr<> instantiations:
<http://boost-sandbox.sourceforge.net/libs/proto/doc/html/boost/proto/result_of/matches.html>
Ah ha! The fog begins to lift. I should have read that. I apologize. Maybe if near the beginning of the documentation the concepts of expressions, grammars, and transforms were introduced, and then mention that a grammar was a type of expression... or at least was formed with the same template as an expression... Hmm.. Getting confused again. How can one distinguish a grammar from an expression if both are formed from the same template, i.e. the expr template? Maybe by starting from the base case, the terminal template? IOW, is the following:
base_case)
For any type T: terminal<T> is a grammar type.
Yes. Also insert here, for any grammar types T0,T1,... and transform type X: posit<T0> is a grammar type shift_right<T0,T1> is a grammar type not_<T0> is a grammar type or_<T0,T1,...> is a grammar type and_<T0,T1,...> is a grammar type if_<X,T0,T1> is a grammar type etc....
terminal<T>::type is an expression type.
Yes. It's also a grammar type. It matches itself (more or less -- see the reference for proto::matches<>).
inductive_case)
If T0,T1,...,Tn are all grammar types, and Tag is an n-ary tag, then expr<Tag,T0,T2,...,Tn> is a grammar type.
Yes. (Minor correction, expr<Tag, argsN<T0,T1,...,Tn> > is a grammar type.) So by induction, you can say posit< not_<X> >, which matches a unary plus node whose operand does not match X. And posit< not_<X>
::type means the same thing.
If T0,T1,...,Tn are all expression types, and Tag is an n-ary tag, then expr<Tag,T0,T,...,Tn> is an expression type.
Yes. It is also a grammar type that matches itself.
Otherwise, expr<Tag,T0,T1,...,Tn> is meaningless (a.k.a. undefined).
Well, for instance expr<tag::posit, args1<int> > is neither a grammar nor an expression, that's true. But it's actually not meaningless or undefined. Such types are often intermediate when applying some transforms. But that's a separate issue.
a correct description of how to distinguish a grammar type from an expression type?
As I hope I've shown, these two are not mutually exclusive, but I think you've got the basic gist.
[snip]
What I can agree with is the following: the documentation currently doesn't say what right_shift<L,R>::type means when L and R are grammars. That is an oversight, and I'll fix it.
Thanks.
Glad I could clear this up. Thanks for raising the issue. -- Eric Niebler Boost Consulting www.boost-consulting.com