]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright (c) 2001-2011 Hartmut Kaiser |
2 | // | |
3 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
4 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
5 | ||
6 | #if !defined(BOOST_SPIRIT_KARMA_ACTION_MAR_07_2007_0851AM) | |
7 | #define BOOST_SPIRIT_KARMA_ACTION_MAR_07_2007_0851AM | |
8 | ||
9 | #if defined(_MSC_VER) | |
10 | #pragma once | |
11 | #endif | |
12 | ||
13 | #include <boost/spirit/home/karma/detail/attributes.hpp> | |
14 | #include <boost/spirit/home/support/argument.hpp> | |
15 | #include <boost/spirit/home/support/context.hpp> | |
16 | #include <boost/spirit/home/support/unused.hpp> | |
17 | #include <boost/spirit/home/support/info.hpp> | |
18 | #include <boost/spirit/home/support/action_dispatch.hpp> | |
19 | #include <boost/spirit/home/support/has_semantic_action.hpp> | |
20 | #include <boost/spirit/home/support/handles_container.hpp> | |
21 | #include <boost/spirit/home/karma/domain.hpp> | |
22 | #include <boost/spirit/home/karma/meta_compiler.hpp> | |
23 | #include <boost/spirit/home/karma/generator.hpp> | |
24 | ||
25 | #include <boost/mpl/bool.hpp> | |
26 | #include <boost/mpl/if.hpp> | |
27 | #include <boost/type_traits/remove_const.hpp> | |
28 | #include <boost/type_traits/is_same.hpp> | |
29 | ||
30 | namespace boost { namespace spirit { namespace karma | |
31 | { | |
32 | /////////////////////////////////////////////////////////////////////////// | |
33 | BOOST_PP_REPEAT(SPIRIT_ARGUMENTS_LIMIT, SPIRIT_USING_ARGUMENT, _) | |
34 | ||
35 | template <typename Subject, typename Action> | |
36 | struct action : unary_generator<action<Subject, Action> > | |
37 | { | |
38 | typedef Subject subject_type; | |
39 | typedef typename subject_type::properties properties; | |
40 | ||
41 | template <typename Context, typename Iterator> | |
42 | struct attribute | |
43 | : traits::attribute_of<Subject, Context, Iterator> | |
44 | {}; | |
45 | ||
46 | action(Subject const& subject, Action f) | |
47 | : subject(subject), f(f) {} | |
48 | ||
49 | template < | |
50 | typename OutputIterator, typename Context, typename Delimiter | |
51 | , typename Attribute> | |
52 | bool generate(OutputIterator& sink, Context& ctx, Delimiter const& d | |
53 | , Attribute const& attr_) const | |
54 | { | |
55 | typedef typename attribute<Context, unused_type>::type attr_type; | |
56 | typedef traits::make_attribute<attr_type, Attribute> make_attribute; | |
57 | ||
58 | // create a attribute if none is supplied | |
59 | // this creates a _copy_ of the attribute because the semantic | |
60 | // action will likely change parts of this | |
61 | typedef traits::transform_attribute< | |
62 | typename make_attribute::type, attr_type, domain> transform; | |
63 | ||
64 | typename transform::type attr = | |
65 | traits::pre_transform<domain, attr_type>(make_attribute::call(attr_)); | |
66 | ||
67 | // call the function, passing the attribute, the context and a bool | |
68 | // flag that the client can set to false to fail generating. | |
69 | return traits::action_dispatch<Subject>()(f, attr, ctx) && | |
70 | subject.generate(sink, ctx, d, attr); | |
71 | } | |
72 | ||
73 | template <typename Context> | |
74 | info what(Context& context) const | |
75 | { | |
76 | // the action is transparent (does not add any info) | |
77 | return subject.what(context); | |
78 | } | |
79 | ||
80 | subject_type subject; | |
81 | Action f; | |
82 | }; | |
83 | ||
84 | }}} | |
85 | ||
86 | /////////////////////////////////////////////////////////////////////////////// | |
87 | namespace boost { namespace spirit | |
88 | { | |
89 | /////////////////////////////////////////////////////////////////////////// | |
90 | // Karma action meta-compiler | |
91 | template <> | |
92 | struct make_component<karma::domain, tag::action> | |
93 | { | |
94 | template <typename Sig> | |
95 | struct result; | |
96 | ||
97 | template <typename This, typename Elements, typename Modifiers> | |
98 | struct result<This(Elements, Modifiers)> | |
99 | { | |
100 | typedef typename | |
101 | remove_const<typename Elements::car_type>::type | |
102 | subject_type; | |
103 | ||
104 | typedef typename | |
105 | remove_const<typename Elements::cdr_type::car_type>::type | |
106 | action_type; | |
107 | ||
108 | typedef karma::action<subject_type, action_type> type; | |
109 | }; | |
110 | ||
111 | template <typename Elements> | |
112 | typename result<make_component(Elements, unused_type)>::type | |
113 | operator()(Elements const& elements, unused_type) const | |
114 | { | |
115 | typename result<make_component(Elements, unused_type)>::type | |
116 | result(elements.car, elements.cdr.car); | |
117 | return result; | |
118 | } | |
119 | }; | |
120 | }} | |
121 | ||
122 | namespace boost { namespace spirit { namespace traits | |
123 | { | |
124 | /////////////////////////////////////////////////////////////////////////// | |
125 | template <typename Subject, typename Action> | |
126 | struct has_semantic_action<karma::action<Subject, Action> > | |
127 | : mpl::true_ {}; | |
128 | ||
129 | /////////////////////////////////////////////////////////////////////////// | |
130 | template <typename Subject, typename Action, typename Attribute | |
131 | , typename Context, typename Iterator> | |
132 | struct handles_container<karma::action<Subject, Action>, Attribute | |
133 | , Context, Iterator> | |
134 | : unary_handles_container<Subject, Attribute, Context, Iterator> {}; | |
135 | }}} | |
136 | ||
137 | #endif |