[proto]purpose of binary_expr<T,L,R>::type ?

Just as: terminal<X>:;type is the type of expressions matching the grammar, terminal<X>, I would expect that binary_expr<T,L,R>::type would match binary_expr<T,L,R>. IOW, just as: matches<terminal<X>::type,terminal<X> > is true, should: matches<binary_expr<T,L,R>::type,binary_expr<T,L,R> > be true? If not, then what is the purpose of binary_expr<,,>::type? If yes, then why am I getting an error with the attached driver whose compilation output is also attached? gcc.compile.c++ ../../../../../bin.v2/sandbox/lje/libs/proto/experiments3/gram_type_test.test/gcc-4.1/debug/link-static/gram_type_test.o gram_type_test.cpp:29: error: conversion from ' boost::proto::exprns_::expr<boost::proto::tag::shift_right, boost::proto::argsns_::args2<boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::args0<ti<0> >, 0l>, boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::args0<ti<0> >, 0l> >, 2l> ' to non-scalar type ' boost::proto::exprns_::expr<boost::proto::tag::shift_right, boost::proto::argsns_::args2<boost::proto::op::terminal<ti<0> >, boost::proto::op::terminal<ti<0> > >, 2l> ' requested

Larry Evans wrote:
Just as:
terminal<X>:;type
is the type of expressions matching the grammar, terminal<X>, I would expect that binary_expr<T,L,R>::type would match binary_expr<T,L,R>. IOW, just as:
matches<terminal<X>::type,terminal<X> >
is true, should:
matches<binary_expr<T,L,R>::type,binary_expr<T,L,R> >
be true?
That is the intention, yes. More specifically, binary_expr<X,Y,Z> matches binary_expr<A,B,C>::type when Y matches B, Z matches C, and X is A or proto::_.
If not, then what is the purpose of binary_expr<,,>::type? If yes, then why am I getting an error with the attached driver whose compilation output is also attached?
Your problem distills down to: typedef terminal<x> GX; // grammar for x typedef GX::type EX; // expression for x typedef shift_right<GX, GX> SRGX; // grammar for x>>x typedef SRGX::type SREX; // OOPS! You then try to use SREX as a valid expression type, and it is not. It should be: typedef shift_right<EX, EX>::type SREX; The difference is that in the first case, you're creating the type of a right shift expression where the operands are grammars. You really want the operands to be expression types. HTH, -- Eric Niebler Boost Consulting www.boost-consulting.com

On 03/02/08 19:39, Eric Niebler wrote: [snip]
Your problem distills down to:
typedef terminal<x> GX; // grammar for x typedef GX::type EX; // expression for x
typedef shift_right<GX, GX> SRGX; // grammar for x>>x typedef SRGX::type SREX; // OOPS!
You then try to use SREX as a valid expression type, and it is not. It should be:
typedef shift_right<EX, EX>::type SREX;
The difference is that in the first case, you're creating the type of a right shift expression where the operands are grammars. You really want the operands to be expression types.
HTH,
Yes, thanks. I had actually concluded that, but then thought, in that case, the shift_right template arguments can be either grammar types or expression types and, depending on which they are, the nested type may or may not make sense. That kinda bothered me because it was confusing. Someone reading the code would have to realize this to avoid confusion. Here's actually part of what I had written before sent my post: b) operator expressions For each operator grammar instance (see above), O_inst, there's the corresponding type of expressions which match that grammar. For example, if: typedef O < T0 , T1 , ... , Tn > O_inst; typedef O < T0::type , T1::type , ... , Tn::type >::type O_expr; then: matches<O_expr,O_inst> OOPS. This doesn't make sense either because in one instance the the template args are grammar types and in the 2nd they're expressiont types. Looking at traits.hpp shows: template<typename Tag, typename T, typename U> struct binary_expr : pass_through<binary_expr<Tag, T, U> > { BOOST_PROTO_NOT_CALLABLE() typedef proto::expr<Tag, args2<T, U> > type; typedef type proto_base_expr; typedef Tag proto_tag; typedef T proto_arg0; typedef U proto_arg1; }; so the subexpression types are grammar types? I'd be more comfortable if the validity of the nested type didn't depend on particular type of the template parameter.

Larry Evans wrote:
On 03/02/08 19:39, Eric Niebler wrote: [snip]
Your problem distills down to:
typedef terminal<x> GX; // grammar for x typedef GX::type EX; // expression for x
typedef shift_right<GX, GX> SRGX; // grammar for x>>x typedef SRGX::type SREX; // OOPS!
You then try to use SREX as a valid expression type, and it is not. It should be:
typedef shift_right<EX, EX>::type SREX;
The difference is that in the first case, you're creating the type of a right shift expression where the operands are grammars. You really want the operands to be expression types.
HTH,
Yes, thanks. I had actually concluded that, but then thought, in that case, the shift_right template arguments can be either grammar types or expression types and, depending on which they are, the nested type may or may not make sense.
That's not the case. In binary_expr<A,B,C>::type, if B and C are expressions, ::type is an expression. If they are grammars, ::type is a grammar. It is merely a matter of convenience that you can leave off the ::type when you want to use binary_expr<> as a grammar.
That kinda bothered me because it was confusing. Someone reading the code would have to realize this to avoid confusion.
Here's actually part of what I had written before sent my post:
b) operator expressions
For each operator grammar instance (see above), O_inst, there's the corresponding type of expressions which match that grammar. For example, if:
typedef O < T0 , T1 , ... , Tn > O_inst; typedef O < T0::type , T1::type , ... , Tn::type >::type O_expr;
then:
matches<O_expr,O_inst>
OOPS. This doesn't make sense either because in one instance the the template args are grammar types and in the 2nd they're expressiont types. Looking at traits.hpp shows:
There's lots of reasons why this generalization is untrue. You can't, in general, construct an expression type from a grammar type. First of all, these are recursive data structures. There is no operation you can apply at the root of such a type that achieves the effect you're after. But more importantly, most grammar elements (e.g., and_, or_, not_, if_, switch_, etc.) don't even have a nested ::type.
template<typename Tag, typename T, typename U> struct binary_expr : pass_through<binary_expr<Tag, T, U> > { BOOST_PROTO_NOT_CALLABLE() typedef proto::expr<Tag, args2<T, U> > type; typedef type proto_base_expr; typedef Tag proto_tag; typedef T proto_arg0; typedef U proto_arg1; };
so the subexpression types are grammar types?
Grammars or expressions, whichever. (Note: in the latest download, binary_expr looks different but behaves the same.)
I'd be more comfortable if the validity of the nested type didn't depend on particular type of the template parameter.
It doesn't. -- Eric Niebler Boost Consulting www.boost-consulting.com

On 03/02/08 20:19, Eric Niebler wrote:
Larry Evans wrote:
On 03/02/08 19:39, Eric Niebler wrote: [snip]
Your problem distills down to:
typedef terminal<x> GX; // grammar for x typedef GX::type EX; // expression for x
typedef shift_right<GX, GX> SRGX; // grammar for x>>x typedef SRGX::type SREX; // OOPS!
You then try to use SREX as a valid expression type, and it is not. It should be:
typedef shift_right<EX, EX>::type SREX;
The difference is that in the first case, you're creating the type of a right shift expression where the operands are grammars. You really want the operands to be expression types. [snip]
I'd be more comfortable if the validity of the nested type didn't depend on particular type of the template parameter.
It doesn't.
If the template arguments are grammars then shift_right<L,R>::type is not an expression type. AFAICT, it's of no use. OTOH, If the template arguments are expression types then shift_right<L,R>::type is an expression type, at least according to what you say above. So maybe I should have said the "usefulness" instead of "validity".

Larry Evans wrote:
If the template arguments are grammars then shift_right<L,R>::type is not an expression type.
Correct, it's a grammar type.
AFAICT, it's of no use.
That's not true. The fact that shift_right<L,R>::type creates expressions when L and R are expressions, and grammars when L and R are grammars, is an important symmetry that is leveraged extensively within Proto. And what would the alternative be? To have two classes, expression::shift_right<> that generates expression types, and grammar::shift_right<> that creates grammar rules? This would surely be worse for users. Why have two when one works just as well? Or are you suggesting something else? -- Eric Niebler Boost Consulting www.boost-consulting.com

On 03/03/08 00:21, Eric Niebler wrote:
Larry Evans wrote:
If the template arguments are grammars then shift_right<L,R>::type is not an expression type.
Correct, it's a grammar type.
AFAICT, it's of no use.
That's not true. The fact that shift_right<L,R>::type creates expressions when L and R are expressions, and grammars when L and R are grammars,
Are you saying shift_right<L,R>::type is a grammar when L and R are grammars or did you mean shift_right<L,R> is a grammar when L and R are grammars? If the latter, then what is shift_right<L,R>::type when L and R are grammars? More specifically, is there any use (for example, in code you or anyone else has written) of shift_right<L,R>::type where L and R are grammars? If not, then, shift_right<L,R>::type, where L and R are grammars, obviously has no use. If yes, could you please post such code or give a link to it so that I can better understand your meaning?
is an important symmetry that is leveraged extensively within Proto. And what would the alternative be? To have two classes, expression::shift_right<> that generates expression types, and grammar::shift_right<> that creates grammar rules? This would surely be worse for users.
Could you explain why it would be worse? I can see that one downside of the two-class solution would be requiring the user to remember which of two namespaces to use under the two different circumstances. The upside is that, although the user would be required to remember two namespaces, he would only have to remember one in any particular circumstance: 1) circumstance 1: grammars: use grammar::shift_right<> with only grammar arguments. 2) circumstance 2: expressions: use expression::shift_right<>:: with only expression arguments. IOW, use different namespaces but the same template name for different circumstances. The different namespace name reinforces different circumstances so that the user doesn't inadvertently use the wrong template name. OTOH, for the current one-class solution, the user has to remember the "kind" of template argument to use depends on whether or not he intends to use the nested type or just the grammar itself: 1) circumstance 1: grammars: use proto::shift_right<> with only grammar arguments. 2) circumstance 2: expressions: use proto::shift_right<>::type with only expression arguments. Note, there is no clue in the proto::shift_right name as to which "kind" of template argument to use. This lack of any clues lead me to mistakenly use grammar arguments to produce a an expression type, and I don't remember seeing any documentation warning against this. In summary, it's just too easy for the user (in particular a novice user) to make the wrong assumption about what kind of argument to supply to the "grammar" template. As a side note: an alternative to using different namespaces in the two-class solution would be using the same template name but with an extra template parameter used to signal the intention. For example: enum grammar_or_expr { is_grammar , is_expr }; template<grammar_or_expr GorE, class Left, class Right> shift_right; Shift_right could then be specialized on is_expr to define the nested type, and on the is_grammar to *not* define the nested type. Of course that's not much different than the two-namespace approach; so, I'm not sure which would be better.
Why have two when one works just as well?
The one-class solution is likely to cause users to stumble (see my last paragraph).
Or are you suggesting something else?
I'm suggesting either the two class solution or (my 2nd choice) a prominent warning in the documentation of grammar classes explaining that the nested type is only useful when the actual template arguments are expression types. I believe this is important because I stumbled over this and had to decipher the compiler error messages before I could figure out that L and R in shift_right<L,R>::type had to be expression types. I believe it's likely that, without either such prominent warning documentation or a two-class template solution, other users (at least novice users) would also stumble like I did. -regards, Larry

Larry Evans wrote:
On 03/03/08 00:21, Eric Niebler wrote:
Larry Evans wrote:
If the template arguments are grammars then shift_right<L,R>::type is not an expression type.
Correct, it's a grammar type.
AFAICT, it's of no use.
That's not true. The fact that shift_right<L,R>::type creates expressions when L and R are expressions, and grammars when L and R are grammars,
Are you saying shift_right<L,R>::type is a grammar when L and R are grammars
Yes! :-)
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. 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>
If the latter, then what is shift_right<L,R>::type when L and R are grammars? More specifically, is there any use (for example, in code you or anyone else has written) of shift_right<L,R>::type where L and R are grammars?
It is used in the implementation of proto::matches<>, not that users should care how matches<> is implemented. (OK, matches uses ::proto_base_expr, which is a typedef for ::type, but that's just a detail.) But they care how matches is specified, and specifying it in terms of expr<> instantiations makes it simple and clear. (I hope!) <snip>
I'm suggesting either the two class solution or (my 2nd choice) a prominent warning in the documentation of grammar classes explaining that the nested type is only useful when the actual template arguments are expression types.
I don't agree that a two class solution is an improvement because it forces users to draw an artificial distinction in their code between two things that are not actually different, and it makes Proto's interface needlessly bloated by duplicating a large number of Proto's metafunctions for (IMO) no good reason. 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. -- Eric Niebler Boost Consulting www.boost-consulting.com

On 03/03/08 15:51, Eric Niebler wrote:
Larry Evans wrote:
On 03/03/08 00:21, Eric Niebler wrote:
Larry Evans wrote:
If the template arguments are grammars then shift_right<L,R>::type is not an expression type.
Correct, it's a grammar type.
AFAICT, it's of no use.
That's not true. The fact that shift_right<L,R>::type creates expressions when L and R are expressions, and grammars when L and R are grammars,
Are you saying shift_right<L,R>::type is a grammar when L and R are grammars
Yes! :-)
Ah! Not what I expected. The fog around my brain is thickening :(
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. So then is shift_right<L,R>::type, when L and R are grammars, the same as shift_right<L,R>?
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. terminal<T>::type is an expression type. 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. 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. Otherwise, expr<Tag,T0,T1,...,Tn> is meaningless (a.k.a. undefined). a correct description of how to distinguish a grammar type from an expression type? [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.

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

On 03/03/08 19:29, Eric Niebler wrote:
Larry Evans wrote: [snip]
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. [snip] 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.) [snip]
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.
[snip] Hmm... So a grammar is an expression and an expression is a grammar. Sorta like lisp where a program is data and data is a program. I guess proto::matches is like lisp eval. Is that sorta right?

Larry Evans wrote:
On 03/03/08 19:29, Eric Niebler wrote:
Larry Evans wrote:
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.
[snip] Hmm... So a grammar is an expression and an expression is a grammar. Sorta like lisp where a program is data and data is a program. I guess proto::matches is like lisp eval. Is that sorta right?
An expression is a grammar, but a grammar is not an expression. For example, not_<X> is only a grammar and not an expression. There's a similarity between lisp macros and proto transforms. They both operate on executable code in the form of expression trees. We haven't spoken about transforms yet, but just as there is a relation between expressions and grammars, there's also a relation between grammars and transforms. I certainly feel like there needs to be a section in Proto's docs that calls out these relationships explicitly. -- Eric Niebler Boost Consulting www.boost-consulting.com

On 03/04/08 11:38, Eric Niebler wrote:
Larry Evans wrote:
On 03/03/08 19:29, Eric Niebler wrote:
Larry Evans wrote:
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.
[snip] Hmm... So a grammar is an expression and an expression is a grammar. Sorta like lisp where a program is data and data is a program. I guess proto::matches is like lisp eval. Is that sorta right?
An expression is a grammar, but a grammar is not an expression. For example, not_<X> is only a grammar and not an expression.
The following grammar I think summarizes the difference between grammar and expression: expr //describes an expression. = terminal | expr+ //i.e. 1 or more expressions (e.g. expr<tag::plus,expr0,expr1>) ; gram //describes a grammar = expr | wildcard //struct wildcardns_::_ in matches.hpp | control //any struct or class template in namespace control in //matches.hpp ; control = not_ >> gram | or_ >> gram >> gram+ | and_ >> gram >> gram+ | if_ >> gram >> gram ; The '= expr' as first alternate of gram reflects the statement 'an expression is a grammar'. The absence of gram on the rhs of the expr equation reflects the statement 'a grammar is not an expression'. Is that about right?

Larry Evans wrote:
On 03/04/08 11:38, Eric Niebler wrote:
An expression is a grammar, but a grammar is not an expression. For example, not_<X> is only a grammar and not an expression.
The following grammar I think summarizes the difference between grammar and expression:
expr //describes an expression. = terminal | expr+ //i.e. 1 or more expressions (e.g. expr<tag::plus,expr0,expr1>) ;
OK.
gram //describes a grammar = expr | wildcard //struct wildcardns_::_ in matches.hpp | control //any struct or class template in namespace control in //matches.hpp ;
OK.
control = not_ >> gram | or_ >> gram >> gram+ | and_ >> gram >> gram+ | if_ >> gram >> gram ;
I may have an issue with your notation here. control = not_<gram> | or_<gram+> | and_<gram+> | if_<trans, gram, gram> // or a vararg expr, or switch_, or ... ;
The '= expr' as first alternate of gram reflects the statement 'an expression is a grammar'. The absence of gram on the rhs of the expr equation reflects the statement 'a grammar is not an expression'.
Is that about right?
Yes, you have it. -- Eric Niebler Boost Consulting www.boost-consulting.com

On 03/22/08 22:12, Eric Niebler wrote:
Larry Evans wrote: [snip]
The following grammar I think summarizes the difference between grammar and expression:
expr //describes an expression. = terminal | expr+ //i.e. 1 or more expressions (e.g. expr<tag::plus,expr0,expr1>) ;
In addition, I wanted some way to tell what's a valid 1st arg to matches. The above description of expr is for a grammar. Now a valid 1st arg to matches would apply ::type to each node in the above tree, AFAICT. At first, I thought of: expr_type = terminal::type | expr_type+ ; but that would make: ( terminal::type, terminal::type, terminal::type ) a valid expresion when what's needed is: ( terminal::type, terminal::type, terminal::type )::type OK, it's getting too abstract to make it clear; so I'll have to make it more concrete: expr_gram = expr<tag::terminal> //Args argument not included intentionally | expr<Tag,expr_gram+> ; and expr_type would have to be a kinda algebraic homomorphism: expr_type(expr<tag::terminal>) -> expr<tag::terminal>::type; expr_type(expr<Tag,expr_gram_1, ... expr_gram_n>) -> expr<Tag,expr_type(expr_gram_1), ... expr_type(expr_gram_n)>::type For example, in the case of a_expr_gram == expr<tag::shift_right,expr<tag::terminal>,expr<tag::terminal> > the morphism "trace" would be: expr_type(a_expr_gram) -> expr < tag::shift_right , expr_type(expr<tag::terminal>) , expr_type(expr<tag::terminal>)
::type -> expr < tag::shift_right , expr<tag::terminal>::type , expr<tag::terminal>::type ::type
The definition of algebraic homomorphism I'm using is at planetmath: http://planetmath.org/encyclopedia/HomomorphismBetweenAlgebraicSystems.html The planetmath f corresponds to above the expr_type. The planetmath operators, w_A and w_B, correspond to the above expr<Tag, ...> and expr<Tag, ...>::type, respectively. Is that about right? Also, I've got the feeling that the pass_through transform is similar to a homomorphism. Is that about right?

On 03/23/08 16:02, Larry Evans wrote:
On 03/22/08 22:12, Eric Niebler wrote:
Larry Evans wrote: [snip]
The following grammar I think summarizes the difference between grammar and expression:
expr //describes an expression. = terminal | expr+ //i.e. 1 or more expressions (e.g. expr<tag::plus,expr0,expr1>) ;
In addition, I wanted some way to tell what's a valid 1st arg to matches. The above description of expr is for a grammar. Now a valid 1st arg to matches would apply ::type to each node in the above tree, AFAICT. At first, I thought of:
expr_type = terminal::type | expr_type+ ;
but that would make:
( terminal::type, terminal::type, terminal::type )
a valid expresion when what's needed is:
( terminal::type, terminal::type, terminal::type )::type
OOPS (again). I guess this would produce what's needed: expr_type = terminal::type | (expr_type+)::type ;

Larry Evans wrote:
On 03/23/08 16:02, Larry Evans wrote:
On 03/22/08 22:12, Eric Niebler wrote:
Larry Evans wrote: [snip]
The following grammar I think summarizes the difference between grammar and expression:
expr //describes an expression. = terminal | expr+ //i.e. 1 or more expressions (e.g. expr<tag::plus,expr0,expr1>) ;
In addition, I wanted some way to tell what's a valid 1st arg to matches. The above description of expr is for a grammar. Now a valid 1st arg to matches would apply ::type to each node in the above tree, AFAICT. At first, I thought of:
expr_type = terminal::type | expr_type+ ;
but that would make:
( terminal::type, terminal::type, terminal::type )
a valid expresion when what's needed is:
( terminal::type, terminal::type, terminal::type )::type
OOPS (again). I guess this would produce what's needed:
expr_type = terminal::type | (expr_type+)::type ;
I'm confused by your syntax, so I can't say whether this is right or not. I'm pretty sure the use of ::type is wrong. Let me see if I can put in words what an expression is, and what a grammar is, and what the relationship is between the two. Maybe you can combine this with your understanding of morphisms to formulate this. An expression is one of: * expr<tag::terminal, args0<X> > * expr<Tag, argsN<A0,A1,...> > where A0,A1,... are expressions * ref_<E> where E is an expression * Some class type T that inherits from extends<E,T,D>, where E is an expression, and D is the domain of T. * Some class type T that uses BOOST_PROTO_EXTENDS(E,T,D) to extend an expression type E in the domain D. A grammar is: * _ * An expression * expr<tag::terminal, args0<exact<X> > > * expr<tag::terminal, args0<convertible_to<X> > > * expr<Tag, argsN<A0,A1,...> > where A0,A1,... are grammars * expr<_, argsN<A0,A1,...> > where A0,A1,... are grammars * expr<Tag, argsN<A0,A1,...,vararg<B> > > where A0,A1,... are grammars, and B is a grammar. * expr<_, argsN<A0,A1,...,vararg<B> > > where A0,A1,... are grammars, and B is a grammar. * or_<A0,A1,...> where A0,A1,... are grammars * and_<A0,A1,...> where A0,A1,... are grammars * switch_<C> where C is class type representing a set of grammars. * if_<T> where T is a transform that yields a compile-time Boolean * if_<T,Then> where T is a transform that yields a compile-time Boolean and Then is a grammar * if_<T,Then,Else> where T is a transform that yields a compile- time Boolean and Then and Else are grammars * not_<A> where A is a grammar * Some type T for which T::proto_base_expr is a grammar (e.g., negate<X>) -- Eric Niebler Boost Consulting www.boost-consulting.com

On 03/24/08 15:40, Eric Niebler wrote: [snip]
not. I'm pretty sure the use of ::type is wrong. Let me see if I can put in words what an expression is, and what a grammar is, and what the relationship is between the two. Maybe you can combine this with your understanding of morphisms to formulate this.
An expression is one of: * expr<tag::terminal, args0<X> > ... [snip]
But isn't terminal<X> the same as expr<tag::terminal,args0<X> >? So, if terminal<X> is an expression (type), then the following: terminal<int> t_int={{1}}; should compile, but it doesn't. Instead, the ::type has to be appended to it. That's the reason for the ::type in the formula I gave in immediately previous post. I think what you're calling expression I'm calling expr_gram here: http://archives.free.net.ph/message/20080323.205859.65a40e5e.en.html

Larry Evans wrote:
On 03/24/08 15:40, Eric Niebler wrote: [snip]
not. I'm pretty sure the use of ::type is wrong. Let me see if I can put in words what an expression is, and what a grammar is, and what the relationship is between the two. Maybe you can combine this with your understanding of morphisms to formulate this.
An expression is one of: * expr<tag::terminal, args0<X> > ... [snip]
But isn't terminal<X> the same as expr<tag::terminal,args0<X> >?
No, it's not. terminal<X> is a metafunction. terminal<X>::type is expr<tag::terminal, args0<X> >. IN ADDITION, terminal<X> is a grammar (see my other message). The one thing terminal<X> is NOT is an expression. -- Eric Niebler Boost Consulting www.boost-consulting.com

On 03/03/08 15:51, Eric Niebler wrote: [snip]
shift_right<L,R>::type is *very* simple. It is expr<tag::shift_right, args2<L, R> >. Always. 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
So why is there expr<Tag,Args,Arity>::type if it's always the same as its enclosing class, expr<Tag,Args,Arity>. IIRC, mpl requires it for some metaprogramming reason, but it seems that's an implementation detail; consequently, although the user can use it, there's no need for the user to use it. If so, then why do many of the examples have: terminal<...>::type a_term_expr={{}}; instead of just: terminal<...> a_term_expr={{}}; ?

On 03/22/08 10:29, Larry Evans wrote:
On 03/03/08 15:51, Eric Niebler wrote: [snip]
shift_right<L,R>::type is *very* simple. It is expr<tag::shift_right, args2<L, R> >. Always. 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
So why is there expr<Tag,Args,Arity>::type if it's always the same as its enclosing class, expr<Tag,Args,Arity>. IIRC, mpl requires it for some metaprogramming reason, but it seems that's an implementation detail; consequently, although the user can use it, there's no need for the user to use it. If so, then why do many of the examples have:
terminal<...>::type a_term_expr={{}};
instead of just:
terminal<...> a_term_expr={{}};
? OOPS, I misread. I read "shift_right<L,R>::type is shift_right<L,R>" not "shift_right<L,R>::type is expr<tag::shift_right,args2<L,R> >". I guess I misread because shift_right<L,R> is a grammar; so, I assumed that when L and R are grammars, the expr<shift_right,args2<L,R> grammar would be shirt_right<L,R>.
Sorry.

Larry Evans wrote:
On 03/22/08 10:29, Larry Evans wrote:
On 03/03/08 15:51, Eric Niebler wrote: [snip]
shift_right<L,R>::type is *very* simple. It is expr<tag::shift_right, args2<L, R> >. Always. 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 So why is there expr<Tag,Args,Arity>::type if it's always the same as its enclosing class, expr<Tag,Args,Arity>. IIRC, mpl requires it for some metaprogramming reason, but it seems that's an implementation detail; consequently, although the user can use it, there's no need for the user to use it. If so, then why do many of the examples have:
terminal<...>::type a_term_expr={{}};
instead of just:
terminal<...> a_term_expr={{}};
? OOPS, I misread. I read "shift_right<L,R>::type is shift_right<L,R>" not "shift_right<L,R>::type is expr<tag::shift_right,args2<L,R> >". I guess I misread because shift_right<L,R> is a grammar; so, I assumed that when L and R are grammars, the expr<shift_right,args2<L,R> grammar would be shirt_right<L,R>.
Sorry.
You've got it now. In addition, when L and R are grammars, shift_right<L,R> and expr<tag::shift_right, args2<L,R> > describe the same set of expressions, even though they are different types. The first is the short form for the other. -- Eric Niebler Boost Consulting www.boost-consulting.com
participants (2)
-
Eric Niebler
-
Larry Evans