]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Boost.Wave: A Standard compliant C++ preprocessor library | |
3 | ||
4 | http://www.boost.org/ | |
5 | ||
6 | Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost | |
7 | Software License, Version 1.0. (See accompanying file | |
8 | LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 | =============================================================================*/ | |
10 | ||
11 | #if !defined(CPP_INTLIT_GRAMMAR_HPP_2E1E70B1_F15C_4132_8554_10A231B0D91C_INCLUDED) | |
12 | #define CPP_INTLIT_GRAMMAR_HPP_2E1E70B1_F15C_4132_8554_10A231B0D91C_INCLUDED | |
13 | ||
14 | #include <boost/wave/wave_config.hpp> | |
15 | ||
16 | #include <boost/spirit/include/classic_core.hpp> | |
17 | #include <boost/spirit/include/classic_closure.hpp> | |
18 | #include <boost/spirit/include/classic_assign_actor.hpp> | |
19 | #include <boost/spirit/include/classic_push_back_actor.hpp> | |
20 | ||
21 | #include <boost/spirit/include/phoenix1_operators.hpp> | |
22 | #include <boost/spirit/include/phoenix1_primitives.hpp> | |
23 | #include <boost/spirit/include/phoenix1_statements.hpp> | |
24 | ||
25 | #include <boost/wave/cpp_exceptions.hpp> | |
26 | #include <boost/wave/grammars/cpp_literal_grammar_gen.hpp> | |
27 | ||
28 | #if !defined(spirit_append_actor) | |
29 | #define spirit_append_actor(actor) boost::spirit::classic::push_back_a(actor) | |
30 | #define spirit_assign_actor(actor) boost::spirit::classic::assign_a(actor) | |
31 | #endif // !defined(spirit_append_actor) | |
32 | ||
33 | // this must occur after all of the includes and before any code appears | |
34 | #ifdef BOOST_HAS_ABI_HEADERS | |
35 | #include BOOST_ABI_PREFIX | |
36 | #endif | |
37 | ||
38 | /////////////////////////////////////////////////////////////////////////////// | |
39 | // | |
40 | // Reusable grammar for parsing of C++ style integer literals | |
41 | // | |
42 | /////////////////////////////////////////////////////////////////////////////// | |
43 | namespace boost { | |
44 | namespace wave { | |
45 | namespace grammars { | |
46 | ||
47 | /////////////////////////////////////////////////////////////////////////////// | |
48 | namespace closures { | |
49 | ||
50 | struct intlit_closure | |
51 | : boost::spirit::classic::closure<intlit_closure, uint_literal_type> | |
52 | { | |
53 | member1 val; | |
54 | }; | |
55 | } | |
56 | ||
57 | /////////////////////////////////////////////////////////////////////////////// | |
58 | // define, whether the rule's should generate some debug output | |
59 | #define TRACE_INTLIT_GRAMMAR \ | |
60 | bool(BOOST_SPIRIT_DEBUG_FLAGS_CPP & BOOST_SPIRIT_DEBUG_FLAGS_INTLIT_GRAMMAR) \ | |
61 | /**/ | |
62 | ||
63 | struct intlit_grammar : | |
64 | boost::spirit::classic::grammar<intlit_grammar, closures::intlit_closure::context_t> | |
65 | { | |
66 | intlit_grammar(bool &is_unsigned_) : is_unsigned(is_unsigned_) | |
67 | { | |
68 | BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(*this, "intlit_grammar", | |
69 | TRACE_INTLIT_GRAMMAR); | |
70 | } | |
71 | ||
72 | template <typename ScannerT> | |
73 | struct definition | |
74 | { | |
75 | typedef boost::spirit::classic::rule<ScannerT> rule_t; | |
76 | ||
77 | rule_t int_lit; | |
78 | boost::spirit::classic::subrule<0> sub_int_lit; | |
79 | boost::spirit::classic::subrule<1> oct_lit; | |
80 | boost::spirit::classic::subrule<2> hex_lit; | |
81 | boost::spirit::classic::subrule<3> dec_lit; | |
82 | ||
83 | definition(intlit_grammar const &self) | |
84 | { | |
85 | using namespace boost::spirit::classic; | |
86 | namespace phx = phoenix; | |
87 | ||
88 | ||
89 | int_lit = ( | |
90 | sub_int_lit = | |
91 | ( ch_p('0')[self.val = 0] >> (hex_lit | oct_lit) | |
92 | | dec_lit | |
93 | ) | |
94 | >> !as_lower_d[ | |
95 | (ch_p('u')[phx::var(self.is_unsigned) = true] || ch_p('l')) | |
96 | | (ch_p('l') || ch_p('u')[phx::var(self.is_unsigned) = true]) | |
97 | ] | |
98 | , | |
99 | ||
100 | hex_lit = | |
101 | (ch_p('X') | ch_p('x')) | |
102 | >> uint_parser<uint_literal_type, 16>() | |
103 | [ | |
104 | self.val = phx::arg1, | |
105 | phx::var(self.is_unsigned) = true | |
106 | ] | |
107 | , | |
108 | ||
109 | oct_lit = | |
110 | !uint_parser<uint_literal_type, 8>() | |
111 | [ | |
112 | self.val = phx::arg1, | |
113 | phx::var(self.is_unsigned) = true | |
114 | ] | |
115 | , | |
116 | ||
117 | dec_lit = | |
118 | uint_parser<uint_literal_type, 10>() | |
119 | [ | |
120 | self.val = phx::arg1 | |
121 | ] | |
122 | ) | |
123 | ; | |
124 | ||
125 | BOOST_SPIRIT_DEBUG_TRACE_RULE(int_lit, TRACE_INTLIT_GRAMMAR); | |
126 | BOOST_SPIRIT_DEBUG_TRACE_RULE(sub_int_lit, TRACE_INTLIT_GRAMMAR); | |
127 | BOOST_SPIRIT_DEBUG_TRACE_RULE(hex_lit, TRACE_INTLIT_GRAMMAR); | |
128 | BOOST_SPIRIT_DEBUG_TRACE_RULE(oct_lit, TRACE_INTLIT_GRAMMAR); | |
129 | BOOST_SPIRIT_DEBUG_TRACE_RULE(dec_lit, TRACE_INTLIT_GRAMMAR); | |
130 | } | |
131 | ||
132 | // start rule of this grammar | |
133 | rule_t const& start() const | |
134 | { return int_lit; } | |
135 | }; | |
136 | ||
137 | bool &is_unsigned; | |
138 | }; | |
139 | ||
140 | #undef TRACE_INTLIT_GRAMMAR | |
141 | ||
142 | /////////////////////////////////////////////////////////////////////////////// | |
143 | // | |
144 | // The following function is defined here, to allow the separation of | |
145 | // the compilation of the intlit_grammar from the function using it. | |
146 | // | |
147 | /////////////////////////////////////////////////////////////////////////////// | |
148 | ||
149 | #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0 | |
150 | #define BOOST_WAVE_INTLITGRAMMAR_GEN_INLINE | |
151 | #else | |
152 | #define BOOST_WAVE_INTLITGRAMMAR_GEN_INLINE inline | |
153 | #endif | |
154 | ||
155 | template <typename TokenT> | |
156 | BOOST_WAVE_INTLITGRAMMAR_GEN_INLINE | |
157 | uint_literal_type | |
158 | intlit_grammar_gen<TokenT>::evaluate(TokenT const &token, | |
159 | bool &is_unsigned) | |
160 | { | |
161 | using namespace boost::spirit::classic; | |
162 | ||
163 | intlit_grammar g(is_unsigned); | |
164 | uint_literal_type result = 0; | |
165 | typename TokenT::string_type const &token_val = token.get_value(); | |
166 | parse_info<typename TokenT::string_type::const_iterator> hit = | |
167 | parse(token_val.begin(), token_val.end(), g[spirit_assign_actor(result)]); | |
168 | ||
169 | if (!hit.hit) { | |
170 | BOOST_WAVE_THROW(preprocess_exception, ill_formed_integer_literal, | |
171 | token_val.c_str(), token.get_position()); | |
172 | } | |
173 | return result; | |
174 | } | |
175 | ||
176 | #undef BOOST_WAVE_INTLITGRAMMAR_GEN_INLINE | |
177 | ||
178 | /////////////////////////////////////////////////////////////////////////////// | |
179 | } // namespace grammars | |
180 | } // namespace wave | |
181 | } // namespace boost | |
182 | ||
183 | // the suffix header occurs after all of the code | |
184 | #ifdef BOOST_HAS_ABI_HEADERS | |
185 | #include BOOST_ABI_SUFFIX | |
186 | #endif | |
187 | ||
188 | #endif // !defined(CPP_INTLIT_GRAMMAR_HPP_2E1E70B1_F15C_4132_8554_10A231B0D91C_INCLUDED) |