blob: 49ad3dd8b06a1bd816a85751069dbbb6db63e915 [file] [log] [blame]
// Copyright 2008 Christophe Henry
// henry UNDERSCORE christophe AT hotmail DOT com
// This is an extended version of the state machine available in the boost::mpl library
// Distributed under the same license as the original.
// Copyright for the original version:
// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
// under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_MSM_FRONT_EUML_STT_GRAMMAR_H
#define BOOST_MSM_FRONT_EUML_STT_GRAMMAR_H
#include <boost/msm/front/euml/common.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/msm/front/euml/operator.hpp>
#include <boost/msm/front/euml/guard_grammar.hpp>
#include <boost/msm/front/euml/state_grammar.hpp>
namespace proto = boost::proto;
namespace boost { namespace msm { namespace front { namespace euml
{
template <class SOURCE,class EVENT,class TARGET,class ACTION=none,class GUARD=none>
struct TempRow
{
typedef SOURCE Source;
typedef EVENT Evt;
typedef TARGET Target;
typedef ACTION Action;
typedef GUARD Guard;
};
template <class TEMP_ROW>
struct convert_to_row
{
typedef Row<typename TEMP_ROW::Source,typename TEMP_ROW::Evt,typename TEMP_ROW::Target,
typename TEMP_ROW::Action,typename TEMP_ROW::Guard> type;
};
template <class TEMP_ROW>
struct convert_to_internal_row
{
typedef Internal<typename TEMP_ROW::Evt,
typename TEMP_ROW::Action,typename TEMP_ROW::Guard> type;
};
// explicit + fork + entry point + exit point grammar
struct BuildEntry
: proto::when<
proto::function<proto::terminal<proto::_>,proto::terminal<state_tag>,proto::terminal<state_tag> >,
get_fct<proto::_child_c<0>,proto::_child_c<1>,proto::_child_c<2> >()
>
{};
// row grammar
struct BuildNextStates
: proto::or_<
proto::when<
proto::terminal<state_tag>,
proto::_
>,
proto::when<
BuildEntry,
BuildEntry
>,
proto::when<
proto::comma<BuildEntry,BuildEntry >,
::boost::mpl::push_back<
make_vector_one_row<BuildEntry(proto::_left)>(),
BuildEntry(proto::_right)>()
>,
proto::when <
proto::comma<BuildNextStates,BuildEntry >,
::boost::mpl::push_back<
BuildNextStates(proto::_left),
BuildEntry(proto::_right) >()
>
>
{};
template <class EventGuard,class ActionClass>
struct fusion_event_action_guard
{
typedef TempRow<none,typename EventGuard::Evt,none,typename ActionClass::Action,typename EventGuard::Guard> type;
};
template <class SourceGuard,class ActionClass>
struct fusion_source_action_guard
{
typedef TempRow<typename SourceGuard::Source,none,none,typename ActionClass::Action,typename SourceGuard::Guard> type;
};
template <class SourceClass,class EventClass>
struct fusion_source_event_action_guard
{
typedef TempRow<typename SourceClass::Source,typename EventClass::Evt,
none,typename EventClass::Action,typename EventClass::Guard> type;
};
template <class Left,class Right>
struct fusion_left_right
{
typedef TempRow<typename Right::Source,typename Right::Evt,typename Left::Target
,typename Right::Action,typename Right::Guard> type;
};
struct BuildEventPlusGuard
: proto::when<
proto::subscript<proto::terminal<event_tag>,BuildGuards >,
TempRow<none,proto::_left,none,none,BuildGuards(proto::_right)>()
>
{};
struct BuildSourceState
: proto::or_<
proto::when<
proto::terminal<state_tag>,
proto::_
>,
proto::when<
BuildEntry,
BuildEntry
>
>
{};
struct BuildSourcePlusGuard
: proto::when<
proto::subscript<BuildSourceState,BuildGuards >,
TempRow<BuildSourceState(proto::_left),none,none,none,BuildGuards(proto::_right)>()
>
{};
struct BuildEvent
: proto::or_<
// just event without guard/action
proto::when<
proto::terminal<event_tag>,
TempRow<none,proto::_,none>() >
// event / action
, proto::when<
proto::divides<proto::terminal<event_tag>,BuildActionSequence >,
TempRow<none,proto::_left,none,
BuildActionSequence(proto::_right) >() >
// event [ guard ]
, proto::when<
proto::subscript<proto::terminal<event_tag>,BuildGuards >,
TempRow<none,proto::_left,none,none,BuildGuards(proto::_right)>() >
// event [ guard ] / action
, proto::when<
proto::divides<BuildEventPlusGuard,
BuildActionSequence >,
fusion_event_action_guard<BuildEventPlusGuard(proto::_left),
TempRow<none,none,none,BuildActionSequence(proto::_right)>()
>()
>
>
{};
struct BuildSource
: proto::or_<
// after == if just state without event or guard/action
proto::when<
BuildSourceState,
TempRow<BuildSourceState(proto::_),none,none>() >
// == source / action
, proto::when<
proto::divides<BuildSourceState,BuildActionSequence >,
TempRow<BuildSourceState(proto::_left),none,none,
BuildActionSequence(proto::_right) >() >
// == source [ guard ]
, proto::when<
proto::subscript<BuildSourceState,BuildGuards >,
TempRow<BuildSourceState(proto::_left),none,none,none,BuildGuards(proto::_right)>() >
// == source [ guard ] / action
, proto::when<
proto::divides<BuildSourcePlusGuard,
BuildActionSequence >,
fusion_source_action_guard<BuildSourcePlusGuard(proto::_left),
TempRow<none,none,none,BuildActionSequence(proto::_right)>()
>()
>
>
{};
struct BuildRight
: proto::or_<
proto::when<
proto::plus<BuildSource,BuildEvent >,
fusion_source_event_action_guard<BuildSource(proto::_left),BuildEvent(proto::_right)>()
>,
proto::when<
BuildSource,
BuildSource
>
>
{};
struct BuildRow
: proto::or_<
// grammar 1
proto::when<
proto::equal_to<BuildNextStates,BuildRight >,
convert_to_row<
fusion_left_right<TempRow<none,none,BuildNextStates(proto::_left)>,BuildRight(proto::_right)> >()
>,
// internal events
proto::when<
BuildRight,
convert_to_row<
fusion_left_right<TempRow<none,none,none>,BuildRight(proto::_)> >()
>,
// grammar 2
proto::when<
proto::equal_to<BuildRight,BuildNextStates>,
convert_to_row<
fusion_left_right<TempRow<none,none,BuildNextStates(proto::_right)>,BuildRight(proto::_left)> >()
>
>
{};
// stt grammar
struct BuildStt
: proto::or_<
proto::when<
proto::comma<BuildStt,BuildStt>,
boost::mpl::push_back<BuildStt(proto::_left),BuildRow(proto::_right)>()
>,
proto::when <
BuildRow,
make_vector_one_row<BuildRow(proto::_)>()
>
>
{};
template <class Expr>
typename ::boost::mpl::eval_if<
typename proto::matches<Expr,BuildStt>::type,
boost::result_of<BuildStt(Expr)>,
make_invalid_type>::type
build_stt(Expr const& expr)
{
return typename boost::result_of<BuildStt(Expr)>::type();
}
// internal stt grammar
struct BuildInternalRow
: proto::when<
BuildEvent,
convert_to_internal_row<
fusion_left_right<TempRow<none,none,none>,BuildEvent(proto::_)> >()
>
{};
struct BuildInternalStt
: proto::or_<
proto::when<
proto::comma<BuildInternalStt,BuildInternalStt>,
boost::mpl::push_back<BuildInternalStt(proto::_left),BuildInternalRow(proto::_right)>()
>,
proto::when <
BuildInternalRow,
make_vector_one_row<BuildInternalRow(proto::_)>()
>
>
{};
template <class Expr>
typename ::boost::mpl::eval_if<
typename proto::matches<Expr,BuildInternalStt>::type,
boost::result_of<BuildInternalStt(Expr)>,
make_invalid_type>::type
build_internal_stt(Expr const& expr)
{
return typename boost::result_of<BuildInternalStt(Expr)>::type();
}
}}}}
#endif //BOOST_MSM_FRONT_EUML_STT_GRAMMAR_H