|
Proto : |
Subject: Re: [proto] Using Phoenix inside eUML: mixing grammars
From: Thomas Heller (thom.heller_at_[hidden])
Date: 2011-03-22 02:41:19
On Wed, Mar 16, 2011 at 9:56 PM, Christophe Henry
<christophe.j.henry_at_[hidden]> 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_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/proto
>
Proto list run by eric at boostpro.com