
This one took me a long time to understand, and now that I think I understand it, I'm pretty sure I don't like Apparently (at least in the situation shown below, with user defined domain and expressions) unary_expr matches terminal< >. This was surprising to me because I was working under the assumption that unary_expr matched only bona-fide unary C++ operators. Ordering should have solved the problem in my real code, so I still have investigations to do. In my case I need to match both things, but threat the case separately (e.g. a terminal<foo> will be transfromed differently from a terminal<bar> and even more differently from ++a). Now, I can certainly (I think, not tested) wrap unary_expr in a proto::and_ that tests the tag, but it seems such a common occurrence that I'd like it to be the default proto behaviour. Unless I'm doing something stupid. Regards, Maurizio ===File ~/dev/proto_pdl/pe4.cpp============================= #define BOOST_PROTO_MAX_ARITY 10 #define BOOST_MPL_LIMIT_METAFUNCTION_ARITY 10 #include <iostream> #include <boost/xpressive/proto/proto.hpp> #include <boost/xpressive/proto/debug.hpp> namespace proto=boost::proto; template<typename> struct meta_expression; struct meta_domain : proto::domain<proto::generator<meta_expression> > {}; template <typename Expr> struct meta_expression : proto::extends<Expr, meta_expression<Expr>, meta_domain> { typedef proto::extends<Expr, meta_expression<Expr>, meta_domain> base_type; meta_expression (Expr const& expr = Expr()) : base_type (expr) {} using base_type::operator =; }; #define META_TERMINAL(NAME) \ struct NAME##_tag {}; \ inline char const* proto_tag_name (NAME##_tag) { return #NAME; } \ std::ostream& operator << (std::ostream& os, const NAME##_tag) { os << "[" #NAME "]" ; return os; } \ meta_expression<proto::terminal<NAME##_tag>::type> NAME struct _5_tag {}; inline const char* proto_tag_name (_5_tag) {return "_5"; } meta_expression<proto::terminal<_5_tag>::type> _5; // std::ostream& operator << (std::ostream& os, const _5_tag) { os << "[_5]" ; return os; } \ META_TERMINAL (_1); META_TERMINAL (_2); META_TERMINAL (_3); struct meta_grammar : proto::or_ < proto::terminal<_1_tag>, // proto::terminal<_2_tag>, proto::terminal<_3_tag>, proto::unary_expr<proto::_, proto::_>
{}; template<typename Expr> void is_meta_expression (const Expr& expr) { std::cout << "Expression:\n"; proto::display_expr (expr); if (proto::matches<Expr, meta_grammar>::value) std::cout << "matches meta grammar\n\n"; else std::cout << "doesn't matches meta grammar\n\n"; } int main (int,char**) { is_meta_expression (_2); } /// Local Variables: /// mode:c++ /// comment-column:60 /// fill-column:150 /// compilation-read-command:nil /// compile-command:"g++ -I. -ope4 pe4.cpp" /// End: ============================================================