]>
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; | |
7c673cae FG |
56 | |
57 | // create a attribute if none is supplied | |
58 | // this creates a _copy_ of the attribute because the semantic | |
59 | // action will likely change parts of this | |
60 | typedef traits::transform_attribute< | |
92f5a8d4 | 61 | Attribute const, attr_type, domain> transform; |
7c673cae | 62 | |
92f5a8d4 | 63 | attr_type attr = transform::pre(attr_); |
7c673cae FG |
64 | |
65 | // call the function, passing the attribute, the context and a bool | |
66 | // flag that the client can set to false to fail generating. | |
67 | return traits::action_dispatch<Subject>()(f, attr, ctx) && | |
68 | subject.generate(sink, ctx, d, attr); | |
69 | } | |
70 | ||
71 | template <typename Context> | |
72 | info what(Context& context) const | |
73 | { | |
74 | // the action is transparent (does not add any info) | |
75 | return subject.what(context); | |
76 | } | |
77 | ||
78 | subject_type subject; | |
79 | Action f; | |
80 | }; | |
81 | ||
82 | }}} | |
83 | ||
84 | /////////////////////////////////////////////////////////////////////////////// | |
85 | namespace boost { namespace spirit | |
86 | { | |
87 | /////////////////////////////////////////////////////////////////////////// | |
88 | // Karma action meta-compiler | |
89 | template <> | |
90 | struct make_component<karma::domain, tag::action> | |
91 | { | |
92 | template <typename Sig> | |
93 | struct result; | |
94 | ||
95 | template <typename This, typename Elements, typename Modifiers> | |
96 | struct result<This(Elements, Modifiers)> | |
97 | { | |
98 | typedef typename | |
99 | remove_const<typename Elements::car_type>::type | |
100 | subject_type; | |
101 | ||
102 | typedef typename | |
103 | remove_const<typename Elements::cdr_type::car_type>::type | |
104 | action_type; | |
105 | ||
106 | typedef karma::action<subject_type, action_type> type; | |
107 | }; | |
108 | ||
109 | template <typename Elements> | |
110 | typename result<make_component(Elements, unused_type)>::type | |
111 | operator()(Elements const& elements, unused_type) const | |
112 | { | |
113 | typename result<make_component(Elements, unused_type)>::type | |
114 | result(elements.car, elements.cdr.car); | |
115 | return result; | |
116 | } | |
117 | }; | |
118 | }} | |
119 | ||
120 | namespace boost { namespace spirit { namespace traits | |
121 | { | |
122 | /////////////////////////////////////////////////////////////////////////// | |
123 | template <typename Subject, typename Action> | |
124 | struct has_semantic_action<karma::action<Subject, Action> > | |
125 | : mpl::true_ {}; | |
126 | ||
127 | /////////////////////////////////////////////////////////////////////////// | |
128 | template <typename Subject, typename Action, typename Attribute | |
129 | , typename Context, typename Iterator> | |
130 | struct handles_container<karma::action<Subject, Action>, Attribute | |
131 | , Context, Iterator> | |
132 | : unary_handles_container<Subject, Attribute, Context, Iterator> {}; | |
133 | }}} | |
134 | ||
135 | #endif |