On Wed, Mar 16, 2011 at 9:56 PM, Christophe Henry <christophe.j.he...@googlemail.com> wrote: > Hi,
Sorry for the late reply ... > I have my eUML grammar, defing, for example a transition as: > > SourceState+ Event [some_guard] == TargetState > > I want to write for some_guard an expression of a phoenix grammar. The > relevant part of the expression is: > Event [some_guard] > > Where the corresponding part of my grammar is: > > struct BuildEventPlusGuard > : proto::when< > proto::subscript<proto::terminal<event_tag>,BuildGuards >, > TempRow<none,proto::_left,none,none,BuildGuards(proto::_right)>() > > > {}; > > BuildGuards is, at the moment, a proto::switch_ grammar, which I want > to replace with something matching a phoenix grammar and returning me > a phoenix::actor<Expr>, which I will then save into TempRow. > I suppose I could typeof/decltype the phoenix expression but it > doesn't seem like the best solution, I'd prefer to delay this. > Is there something like a phoenix grammar which I can call to check if > the expression is valid, and if yes, which will return me the correct > phoenix::actor? There is boos::phoenix::meta_grammar which can be used to check for valid phoenix expressions. It is really just the grammar, you can't use it as a transform. In your case you can reuse the meta grammar in a great way to restrict certain constructs: struct my_custom_phoenix_grammar : proto::switch_<my_custom_phoenix_grammar> { template <typename Tag> struct case_ : meta_grammar::case_<Tag> {}; }; The above, by default allows everything that's in meta_grammar with the ability to override some of meta_grammar's rules. If you want to use it as a transform you need the evaluator with an appropriate action that does the desired transform... here is an example: struct BuildEventPlusGuard : proto::when< proto::subscript<proto::terminal<event_tag>, phoenix::meta_grammar >, TempRow<none,proto::_left,none,none, phoenix::evaluator(proto::_right, some_cool_action())>() > {}; Now, some_cool_action can do the transform that BuildGuards was doing. > Second question. Now it's becoming more "interesting". And not easy to > explain :( > > For eUML, a guard can be defined as "g1 && g2", where g1 and g2 are > functors, taking 4 arguments. For example (to make short): > struct g1_ > { > template <class FSM,class EVT,class SourceState,class TargetState> > void operator()(EVT const& ,FSM&,SourceState& ,TargetState& ) > { > ... > } > }; > g1_ g1; > > The fact that there are 4 arguments is the condition to make this work > without placeholders. > > I 'm pretty sure that, while this clearly should be a function for > phoenix, I would not like the syntax: > g1(arg1,arg2,arg3,arg4) && g2(arg1,arg2,arg3,arg4). > > Is it possible to define g1 and g2 as custom terminals, but still get > them treated like functions? Yes! Here is an example: template <typename G> struct msm_guard {}; template <typename Expr> struct msm_guard_actor; template <typename G> struct msm_guard_expression : phoenix::terminal<msm_guard<G>, msm_guard_actor> {}; template <typename Expr> struct msm_guard_actor { typedef actor<Expr> base_type; base_type expr; msm_guard_actor(base_type const & base) : expr(base) {} // define the operator() overloads here to allow something // that michael suggested. The result should be full blown phoenix // expressions (BOOST_PHOENIX_DEFINE_EXPRESSION) }; namespace boost { namespace phoenix { namespace result_of { template <template G> is_nullary<custom_terminal<msm_guard<G> > : mpl::false_ {}; } template <typename G> struct is_custom_terminal<msm_guard<G> > : mpl::true_ {}; template <typename G> struct custom_terminal<msm_guard<G> > : proto::call< G( proto::functional::at(_env, mpl::int_<1>()) , proto::functional::at(_env, mpl::int_<2>()) , proto::functional::at(_env, mpl::int_<3>()) , proto::functional::at(_env, mpl::int_<4>()) ) > {}; }} I hope that above example helps you and clarifies how to customize phoenix V3 even further. Note on that terminal thing: It's not in trunk yet ... I did on another computer, cause the spirit port needed it ... I don't have access to that computer right now ... I will commit it later today. > (To solve the problem, my current implementation generates me a > functor of type And_<g1,g2> which has an operator () with 4 > arguments). > > Thanks, > Christophe > _______________________________________________ > proto mailing list > proto@lists.boost.org > http://lists.boost.org/mailman/listinfo.cgi/proto > _______________________________________________ proto mailing list proto@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/proto