/*============================================================================= 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 #include #include #include #include #include #include #include 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 struct component { typedef Domain domain; typedef Director director; typedef Elements elements_type; component() { } component(Elements const& elements) : elements(elements) { } template component(component const& other) : elements(other.elements) { // allow copy from components with compatible elements } elements_type elements; }; /////////////////////////////////////////////////////////////////////////// // Utils for extracting child components /////////////////////////////////////////////////////////////////////////// namespace result_of { template struct subject { typedef typename fusion::result_of::value_at_c< typename Component::elements_type, 0>::type type; }; template struct left { typedef typename fusion::result_of::value_at_c< typename Component::elements_type, 0>::type type; }; template struct right { typedef typename fusion::result_of::value_at_c< typename Component::elements_type, 1>::type type; }; template struct argument1 { typedef typename fusion::result_of::value_at_c< typename Component::elements_type, 1>::type type; }; template struct argument2 { typedef typename fusion::result_of::value_at_c< typename Component::elements_type, 2>::type type; }; template struct arg_c : fusion::result_of::value_at_c< typename Component::elements_type, N> {}; } template 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 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 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 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 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 typename fusion::result_of::at_c< typename Component::elements_type const, N>::type inline arg_c(Component const& c) { return fusion::at_c(c.elements); } /////////////////////////////////////////////////////////////////////////// // Test if Expr conforms to the grammar of Domain. If Expr is already // a component, return mpl::true_. /////////////////////////////////////////////////////////////////////////// namespace traits { template struct is_component : proto::matches< typename proto::result_of::as_expr::type , typename meta_grammar::grammar::type > { }; template struct is_component > : 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::type grammar; typedef typename proto::result_of::as_expr::type proto_xpr; typedef typename grammar::template result< void(proto_xpr, State, Visitor) >::type type; }; // special case for arrays template < typename Domain, typename T, int N, typename State, typename Visitor> struct as_component { typedef typename meta_grammar::grammar::type grammar; typedef typename proto::result_of::as_expr::type proto_xpr; typedef typename grammar::template result< void(proto_xpr, State, Visitor) >::type type; }; // special case for components template struct as_component > : mpl::identity > { }; } template inline typename result_of::as_component::type as_component(Domain, Expr const& xpr) { unused_type unused; typedef typename result_of::as_component::grammar grammar; return grammar()(proto::as_expr(xpr), unused, unused); } template inline typename result_of::as_component::type as_component(Domain, Expr const& xpr, State const& state, Visitor& visitor) { typedef typename result_of::as_component::grammar grammar; return grammar()(proto::as_expr(xpr), state, visitor); } template inline component const& as_component(Domain, component 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 > { static component call(Elements const& elements) { return component(elements); } }; } }} #endif