]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 2001-2011 Joel de Guzman | |
3 | ||
4 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
5 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | =============================================================================*/ | |
7 | #if !defined(SPIRIT_SEQUENTIAL_OR_MARCH_12_2007_1130PM) | |
8 | #define SPIRIT_SEQUENTIAL_OR_MARCH_12_2007_1130PM | |
9 | ||
10 | #if defined(_MSC_VER) | |
11 | #pragma once | |
12 | #endif | |
13 | ||
14 | #include <boost/spirit/home/qi/meta_compiler.hpp> | |
15 | #include <boost/spirit/home/qi/detail/pass_function.hpp> | |
16 | #include <boost/spirit/home/qi/detail/attributes.hpp> | |
17 | #include <boost/spirit/home/support/detail/what_function.hpp> | |
18 | #include <boost/spirit/home/support/algorithm/any_if_ns.hpp> | |
19 | #include <boost/spirit/home/support/handles_container.hpp> | |
20 | #include <boost/fusion/include/as_vector.hpp> | |
21 | #include <boost/fusion/include/for_each.hpp> | |
22 | ||
23 | namespace boost { namespace spirit | |
24 | { | |
25 | /////////////////////////////////////////////////////////////////////////// | |
26 | // Enablers | |
27 | /////////////////////////////////////////////////////////////////////////// | |
28 | template <> | |
29 | struct use_operator<qi::domain, proto::tag::logical_or> // enables || | |
30 | : mpl::true_ {}; | |
31 | ||
32 | template <> | |
33 | struct flatten_tree<qi::domain, proto::tag::logical_or> // flattens || | |
34 | : mpl::true_ {}; | |
35 | }} | |
36 | ||
37 | namespace boost { namespace spirit { namespace qi | |
38 | { | |
39 | template <typename Elements> | |
40 | struct sequential_or : nary_parser<sequential_or<Elements> > | |
41 | { | |
42 | template <typename Context, typename Iterator> | |
43 | struct attribute | |
44 | { | |
45 | // Put all the element attributes in a tuple, | |
46 | // wrapping each element in a boost::optional | |
47 | typedef typename traits::build_attribute_sequence< | |
48 | Elements, Context, traits::sequential_or_attribute_transform | |
49 | , Iterator, qi::domain | |
50 | >::type all_attributes; | |
51 | ||
52 | // Now, build a fusion vector over the attributes. Note | |
53 | // that build_fusion_vector 1) removes all unused attributes | |
54 | // and 2) may return unused_type if all elements have | |
55 | // unused_type(s). | |
56 | typedef typename | |
57 | traits::build_fusion_vector<all_attributes>::type | |
58 | type; | |
59 | }; | |
60 | ||
61 | sequential_or(Elements const& elements_) | |
62 | : elements(elements_) {} | |
63 | ||
64 | template <typename Iterator, typename Context | |
65 | , typename Skipper, typename Attribute> | |
66 | bool parse(Iterator& first, Iterator const& last | |
67 | , Context& context, Skipper const& skipper | |
68 | , Attribute& attr_) const | |
69 | { | |
70 | typedef traits::attribute_not_unused<Context, Iterator> predicate; | |
71 | detail::pass_function<Iterator, Context, Skipper> | |
72 | f(first, last, context, skipper); | |
73 | ||
74 | // wrap the attribute in a tuple if it is not a tuple | |
75 | typename traits::wrap_if_not_tuple<Attribute>::type attr_local(attr_); | |
76 | ||
77 | // return true if *any* of the parsers succeed | |
78 | // (we use the non-short-circuiting version: any_if_ns | |
79 | // to force all elements to be tested) | |
80 | return spirit::any_if_ns(elements, attr_local, f, predicate()); | |
81 | } | |
82 | ||
83 | template <typename Context> | |
84 | info what(Context& context) const | |
85 | { | |
86 | info result("sequential-or"); | |
87 | fusion::for_each(elements, | |
88 | spirit::detail::what_function<Context>(result, context)); | |
89 | return result; | |
90 | } | |
91 | ||
92 | Elements elements; | |
93 | }; | |
94 | ||
95 | /////////////////////////////////////////////////////////////////////////// | |
96 | // Parser generators: make_xxx function (objects) | |
97 | /////////////////////////////////////////////////////////////////////////// | |
98 | template <typename Elements, typename Modifiers> | |
99 | struct make_composite<proto::tag::logical_or, Elements, Modifiers> | |
100 | : make_nary_composite<Elements, sequential_or> | |
101 | {}; | |
102 | }}} | |
103 | ||
104 | namespace boost { namespace spirit { namespace traits | |
105 | { | |
106 | /////////////////////////////////////////////////////////////////////////// | |
107 | // We specialize this for sequential_or (see support/attributes.hpp). | |
108 | // For sequential_or, we only wrap the attribute in a tuple IFF | |
109 | // it is not already a fusion tuple. | |
110 | template <typename Elements, typename Attribute> | |
111 | struct pass_attribute<qi::sequential_or<Elements>, Attribute> | |
112 | : wrap_if_not_tuple<Attribute> {}; | |
113 | ||
114 | /////////////////////////////////////////////////////////////////////////// | |
115 | template <typename Elements> | |
116 | struct has_semantic_action<qi::sequential_or<Elements> > | |
117 | : nary_has_semantic_action<Elements> {}; | |
118 | ||
119 | /////////////////////////////////////////////////////////////////////////// | |
120 | template <typename Elements, typename Attribute, typename Context | |
121 | , typename Iterator> | |
122 | struct handles_container<qi::sequential_or<Elements>, Attribute, Context | |
123 | , Iterator> | |
124 | : nary_handles_container<Elements, Attribute, Context, Iterator> {}; | |
125 | }}} | |
126 | ||
127 | #endif |