| /*============================================================================= |
| Copyright (c) 2001-2007 Joel de Guzman |
| |
| 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) |
| ==============================================================================*/ |
| #if !defined(BOOST_SPIRIT_COMPONENT_JAN_14_2007_1102AM) |
| #define BOOST_SPIRIT_COMPONENT_JAN_14_2007_1102AM |
| |
| #include <boost/spirit/home/support/unused.hpp> |
| #include <boost/spirit/home/support/meta_grammar/grammar.hpp> |
| #include <boost/proto/core.hpp> |
| #include <boost/fusion/include/at.hpp> |
| #include <boost/fusion/include/value_at.hpp> |
| #include <boost/mpl/void.hpp> |
| #include <boost/mpl/identity.hpp> |
| #include <boost/mpl/apply.hpp> |
| |
| namespace boost { namespace spirit |
| { |
| /////////////////////////////////////////////////////////////////////////// |
| // component generalizes a spirit component. A component can be a parser, |
| // a primitive-parser, a composite-parser, a generator, etc. |
| // A component has: |
| // |
| // 1) Domain: The world it operates on (purely a type e.g. qi::domain). |
| // 2) Director: Its Director (purely a type e.g. qi::sequence) |
| // 3) Elements: For composites, a tuple of components |
| // For primitives, a tuple of arbitrary information |
| // |
| /////////////////////////////////////////////////////////////////////////// |
| template <typename Domain, typename Director, typename Elements> |
| struct component |
| { |
| typedef Domain domain; |
| typedef Director director; |
| typedef Elements elements_type; |
| |
| component() |
| { |
| } |
| |
| component(Elements const& elements) |
| : elements(elements) |
| { |
| } |
| |
| template <typename Elements2> |
| component(component<Domain, Director, Elements2> const& other) |
| : elements(other.elements) |
| { |
| // allow copy from components with compatible elements |
| } |
| |
| elements_type elements; |
| }; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // Utils for extracting child components |
| /////////////////////////////////////////////////////////////////////////// |
| namespace result_of |
| { |
| template <typename Component> |
| struct subject |
| { |
| typedef typename |
| fusion::result_of::value_at_c< |
| typename Component::elements_type, 0>::type |
| type; |
| }; |
| |
| template <typename Component> |
| struct left |
| { |
| typedef typename |
| fusion::result_of::value_at_c< |
| typename Component::elements_type, 0>::type |
| type; |
| }; |
| |
| template <typename Component> |
| struct right |
| { |
| typedef typename |
| fusion::result_of::value_at_c< |
| typename Component::elements_type, 1>::type |
| type; |
| }; |
| |
| template <typename Component> |
| struct argument1 |
| { |
| typedef typename |
| fusion::result_of::value_at_c< |
| typename Component::elements_type, 1>::type |
| type; |
| }; |
| |
| template <typename Component> |
| struct argument2 |
| { |
| typedef typename |
| fusion::result_of::value_at_c< |
| typename Component::elements_type, 2>::type |
| type; |
| }; |
| |
| template<typename Component, int N> |
| struct arg_c |
| : fusion::result_of::value_at_c< |
| typename Component::elements_type, N> |
| {}; |
| |
| } |
| |
| template <typename Component> |
| typename fusion::result_of::at_c< |
| typename Component::elements_type const, 0>::type |
| inline subject(Component const& c) |
| { |
| return fusion::at_c<0>(c.elements); |
| } |
| |
| template <typename Component> |
| typename fusion::result_of::at_c< |
| typename Component::elements_type const, 0>::type |
| inline left(Component const& c) |
| { |
| return fusion::at_c<0>(c.elements); |
| } |
| |
| template <typename Component> |
| typename fusion::result_of::at_c< |
| typename Component::elements_type const, 1>::type |
| inline right(Component const& c) |
| { |
| return fusion::at_c<1>(c.elements); |
| } |
| |
| template <typename Component> |
| typename fusion::result_of::at_c< |
| typename Component::elements_type const, 1>::type |
| inline argument1(Component const& c) |
| { |
| return fusion::at_c<1>(c.elements); |
| } |
| |
| template <typename Component> |
| typename fusion::result_of::at_c< |
| typename Component::elements_type const, 2>::type |
| inline argument2(Component const& c) |
| { |
| return fusion::at_c<2>(c.elements); |
| } |
| |
| template <int N, typename Component> |
| typename fusion::result_of::at_c< |
| typename Component::elements_type const, N>::type |
| inline arg_c(Component const& c) |
| { |
| return fusion::at_c<N>(c.elements); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // Test if Expr conforms to the grammar of Domain. If Expr is already |
| // a component, return mpl::true_. |
| /////////////////////////////////////////////////////////////////////////// |
| namespace traits |
| { |
| template <typename Domain, typename Expr> |
| struct is_component |
| : proto::matches< |
| typename proto::result_of::as_expr<Expr>::type |
| , typename meta_grammar::grammar<Domain>::type |
| > |
| { |
| }; |
| |
| template <typename Domain, typename Director, typename Elements> |
| struct is_component<Domain, component<Domain, Director, Elements> > : |
| mpl::true_ |
| { |
| }; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // Convert an arbitrary expression to a spirit component. There's |
| // a metafunction in namespace result_of and a function in main |
| // spirit namespace. If Expr is already a component, return it as-is. |
| /////////////////////////////////////////////////////////////////////////// |
| namespace result_of |
| { |
| template < |
| typename Domain, typename Expr, typename State = unused_type, |
| typename Visitor = unused_type |
| > |
| struct as_component |
| { |
| typedef typename meta_grammar::grammar<Domain>::type grammar; |
| typedef typename proto::result_of::as_expr<Expr>::type proto_xpr; |
| typedef typename grammar::template impl<proto_xpr, State, Visitor> callable; |
| typedef typename callable::result_type type; |
| }; |
| |
| // special case for arrays |
| template < |
| typename Domain, typename T, int N, |
| typename State, typename Visitor> |
| struct as_component<Domain, T[N], State, Visitor> |
| { |
| typedef typename meta_grammar::grammar<Domain>::type grammar; |
| typedef typename proto::result_of::as_expr<T const*>::type proto_xpr; |
| typedef typename grammar::template impl<proto_xpr, State, Visitor> callable; |
| typedef typename callable::result_type type; |
| }; |
| |
| // special case for components |
| template <typename Domain, typename Director, typename Elements> |
| struct as_component<Domain, component<Domain, Director, Elements> > : |
| mpl::identity<component<Domain, Director, Elements> > |
| { |
| }; |
| } |
| |
| namespace detail |
| { |
| template<typename T> |
| T &decay(T &t) |
| { |
| return t; |
| } |
| |
| template<typename T, int N> |
| T *decay(T (&t)[N]) |
| { |
| return t; |
| } |
| } |
| |
| template <typename Domain, typename Expr> |
| inline typename result_of::as_component<Domain, Expr>::type |
| as_component(Domain, Expr const& xpr) |
| { |
| typedef typename result_of::as_component<Domain, Expr>::callable callable; |
| return callable()(proto::as_expr(detail::decay(xpr)), unused_type(), unused_type()); |
| } |
| |
| template <typename Domain, typename Expr, typename State, typename Visitor> |
| inline typename result_of::as_component<Domain, Expr>::type |
| as_component(Domain, Expr const& xpr, State const& state, Visitor& visitor) |
| { |
| typedef typename result_of::as_component<Domain, Expr, State, Visitor>::callable callable; |
| return callable()(proto::as_expr(detail::decay(xpr)), state, visitor); |
| } |
| |
| template <typename Domain, typename Director, typename Elements> |
| inline component<Domain, Director, Elements> const& |
| as_component(Domain, component<Domain, Director, Elements> const& component) |
| { |
| return component; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // Create a component. This is a customization point. Components are |
| // not created directly; they are created through make_component. |
| // Clients may customize this to direct the creation of a component. |
| // |
| // The extra Modifier template parameter may be used to direct the |
| // creation of the component. This is the Visitor parameter in Proto |
| // transforms. |
| // |
| // (see also: modifier.hpp) |
| /////////////////////////////////////////////////////////////////////////// |
| namespace traits |
| { |
| template < |
| typename Domain, typename Director |
| , typename Elements, typename Modifier, typename Enable = void> |
| struct make_component |
| : mpl::identity<component<Domain, Director, Elements> > |
| { |
| static component<Domain, Director, Elements> |
| call(Elements const& elements) |
| { |
| return component<Domain, Director, Elements>(elements); |
| } |
| }; |
| } |
| }} |
| |
| #endif |