]>
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 | ||
20effc67 TL |
11 | #if !defined(BOOST_CPP_GRAMMAR_HPP_FEAEBC2E_2734_428B_A7CA_85E5A415E23E_INCLUDED) |
12 | #define BOOST_CPP_GRAMMAR_HPP_FEAEBC2E_2734_428B_A7CA_85E5A415E23E_INCLUDED | |
7c673cae FG |
13 | |
14 | #include <boost/spirit/include/classic_core.hpp> | |
15 | #include <boost/spirit/include/classic_parse_tree.hpp> | |
16 | #include <boost/spirit/include/classic_parse_tree_utils.hpp> | |
17 | #include <boost/spirit/include/classic_confix.hpp> | |
18 | #include <boost/spirit/include/classic_lists.hpp> | |
19 | ||
20 | #include <boost/wave/wave_config.hpp> | |
21 | #include <boost/pool/pool_alloc.hpp> | |
22 | ||
23 | #if BOOST_WAVE_DUMP_PARSE_TREE != 0 | |
24 | #include <map> | |
25 | #include <boost/spirit/include/classic_tree_to_xml.hpp> | |
26 | #endif | |
27 | ||
28 | #include <boost/wave/token_ids.hpp> | |
29 | #include <boost/wave/grammars/cpp_grammar_gen.hpp> | |
30 | #include <boost/wave/util/pattern_parser.hpp> | |
31 | ||
32 | #include <boost/wave/cpp_exceptions.hpp> | |
33 | ||
34 | // this must occur after all of the includes and before any code appears | |
35 | #ifdef BOOST_HAS_ABI_HEADERS | |
36 | #include BOOST_ABI_PREFIX | |
37 | #endif | |
38 | ||
39 | /////////////////////////////////////////////////////////////////////////////// | |
40 | namespace boost { | |
b32b8144 | 41 | namespace wave { |
7c673cae FG |
42 | namespace grammars { |
43 | ||
44 | namespace impl { | |
45 | ||
46 | /////////////////////////////////////////////////////////////////////////////// | |
47 | // | |
48 | // store_found_eof | |
49 | // | |
b32b8144 | 50 | // The store_found_eof functor sets a given flag if the T_EOF token was |
7c673cae FG |
51 | // found during the parsing process |
52 | // | |
53 | /////////////////////////////////////////////////////////////////////////////// | |
54 | ||
55 | struct store_found_eof { | |
56 | ||
57 | store_found_eof(bool &found_eof_) : found_eof(found_eof_) {} | |
b32b8144 | 58 | |
7c673cae FG |
59 | template <typename TokenT> |
60 | void operator()(TokenT const &/*token*/) const | |
61 | { | |
62 | found_eof = true; | |
63 | } | |
b32b8144 | 64 | |
7c673cae FG |
65 | bool &found_eof; |
66 | }; | |
67 | ||
68 | /////////////////////////////////////////////////////////////////////////////// | |
69 | // | |
70 | // store_found_directive | |
71 | // | |
72 | // The store_found_directive functor stores the token_id of the recognized | |
73 | // pp directive | |
74 | // | |
75 | /////////////////////////////////////////////////////////////////////////////// | |
76 | ||
77 | template <typename TokenT> | |
78 | struct store_found_directive { | |
79 | ||
b32b8144 | 80 | store_found_directive(TokenT &found_directive_) |
7c673cae | 81 | : found_directive(found_directive_) {} |
b32b8144 | 82 | |
7c673cae FG |
83 | void operator()(TokenT const &token) const |
84 | { | |
85 | found_directive = token; | |
86 | } | |
b32b8144 | 87 | |
7c673cae FG |
88 | TokenT &found_directive; |
89 | }; | |
90 | ||
91 | /////////////////////////////////////////////////////////////////////////////// | |
92 | // | |
93 | // store_found_eoltokens | |
94 | // | |
b32b8144 | 95 | // The store_found_eoltokens functor stores the token sequence of the |
7c673cae FG |
96 | // line ending for a particular pp directive |
97 | // | |
98 | /////////////////////////////////////////////////////////////////////////////// | |
99 | ||
100 | template <typename ContainerT> | |
101 | struct store_found_eoltokens { | |
102 | ||
b32b8144 | 103 | store_found_eoltokens(ContainerT &found_eoltokens_) |
7c673cae | 104 | : found_eoltokens(found_eoltokens_) {} |
b32b8144 | 105 | |
7c673cae FG |
106 | template <typename IteratorT> |
107 | void operator()(IteratorT const &first, IteratorT const& last) const | |
108 | { | |
b32b8144 | 109 | std::copy(first, last, |
7c673cae FG |
110 | std::inserter(found_eoltokens, found_eoltokens.end())); |
111 | } | |
b32b8144 | 112 | |
7c673cae FG |
113 | ContainerT &found_eoltokens; |
114 | }; | |
115 | ||
116 | /////////////////////////////////////////////////////////////////////////////// | |
117 | // | |
118 | // flush_underlying_parser | |
119 | // | |
120 | // The flush_underlying_parser flushes the underlying | |
121 | // multi_pass_iterator during the normal parsing process. This is | |
122 | // used at certain points during the parsing process, when it is | |
123 | // clear, that no backtracking is needed anymore and the input | |
124 | // gathered so far may be discarded. | |
125 | // | |
126 | /////////////////////////////////////////////////////////////////////////////// | |
127 | struct flush_underlying_parser | |
128 | : public boost::spirit::classic::parser<flush_underlying_parser> | |
129 | { | |
130 | typedef flush_underlying_parser this_t; | |
131 | ||
132 | template <typename ScannerT> | |
133 | typename boost::spirit::classic::parser_result<this_t, ScannerT>::type | |
134 | parse(ScannerT const& scan) const | |
135 | { | |
136 | scan.first.clear_queue(); | |
b32b8144 | 137 | return scan.empty_match(); |
7c673cae FG |
138 | } |
139 | }; | |
140 | ||
b32b8144 | 141 | flush_underlying_parser const |
7c673cae FG |
142 | flush_underlying_parser_p = flush_underlying_parser(); |
143 | ||
144 | } // anonymous namespace | |
145 | ||
146 | /////////////////////////////////////////////////////////////////////////////// | |
147 | // define, whether the rule's should generate some debug output | |
148 | #define TRACE_CPP_GRAMMAR \ | |
149 | bool(BOOST_SPIRIT_DEBUG_FLAGS_CPP & BOOST_SPIRIT_DEBUG_FLAGS_CPP_GRAMMAR) \ | |
150 | /**/ | |
151 | ||
152 | /////////////////////////////////////////////////////////////////////////////// | |
153 | // Encapsulation of the C++ preprocessor grammar. | |
154 | template <typename TokenT, typename ContainerT> | |
b32b8144 | 155 | struct cpp_grammar : |
7c673cae FG |
156 | public boost::spirit::classic::grammar<cpp_grammar<TokenT, ContainerT> > |
157 | { | |
158 | typedef typename TokenT::position_type position_type; | |
159 | typedef cpp_grammar<TokenT, ContainerT> grammar_type; | |
160 | typedef impl::store_found_eof store_found_eof_type; | |
161 | typedef impl::store_found_directive<TokenT> store_found_directive_type; | |
162 | typedef impl::store_found_eoltokens<ContainerT> store_found_eoltokens_type; | |
b32b8144 | 163 | |
7c673cae FG |
164 | template <typename ScannerT> |
165 | struct definition | |
166 | { | |
20effc67 | 167 | // non-parse_tree generating rule type |
7c673cae FG |
168 | typedef typename ScannerT::iteration_policy_t iteration_policy_t; |
169 | typedef boost::spirit::classic::match_policy match_policy_t; | |
170 | typedef typename ScannerT::action_policy_t action_policy_t; | |
b32b8144 | 171 | typedef |
7c673cae | 172 | boost::spirit::classic::scanner_policies< |
b32b8144 | 173 | iteration_policy_t, match_policy_t, action_policy_t> |
7c673cae | 174 | policies_t; |
b32b8144 FG |
175 | typedef |
176 | boost::spirit::classic::scanner<typename ScannerT::iterator_t, policies_t> | |
7c673cae | 177 | non_tree_scanner_t; |
b32b8144 | 178 | typedef |
7c673cae | 179 | boost::spirit::classic::rule< |
b32b8144 | 180 | non_tree_scanner_t, boost::spirit::classic::dynamic_parser_tag> |
7c673cae FG |
181 | no_tree_rule_type; |
182 | ||
20effc67 | 183 | // 'normal' (parse_tree generating) rule type |
b32b8144 | 184 | typedef |
7c673cae | 185 | boost::spirit::classic::rule< |
b32b8144 | 186 | ScannerT, boost::spirit::classic::dynamic_parser_tag> |
7c673cae FG |
187 | rule_type; |
188 | ||
189 | rule_type pp_statement, macro_include_file; | |
190 | // rule_type include_file, system_include_file; | |
191 | rule_type plain_define, macro_definition, macro_parameters; | |
192 | rule_type undefine; | |
193 | rule_type ppifdef, ppifndef, ppif, ppelif; | |
194 | // rule_type ppelse, ppendif; | |
b32b8144 | 195 | rule_type ppline; |
7c673cae FG |
196 | rule_type pperror; |
197 | rule_type ppwarning; | |
198 | rule_type pppragma; | |
199 | rule_type illformed; | |
200 | rule_type ppqualifiedname; | |
201 | rule_type eol_tokens; | |
202 | no_tree_rule_type ppsp; | |
203 | #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0 | |
204 | rule_type ppregion; | |
205 | rule_type ppendregion; | |
206 | #endif | |
207 | ||
b32b8144 | 208 | definition(cpp_grammar const &self) |
7c673cae | 209 | { |
20effc67 | 210 | // import the spirit and cpplexer namespaces here |
7c673cae FG |
211 | using namespace boost::spirit::classic; |
212 | using namespace boost::wave; | |
213 | using namespace boost::wave::util; | |
214 | ||
20effc67 | 215 | // set the rule id's for later use |
7c673cae FG |
216 | pp_statement.set_id(BOOST_WAVE_PP_STATEMENT_ID); |
217 | // include_file.set_id(BOOST_WAVE_INCLUDE_FILE_ID); | |
218 | // system_include_file.set_id(BOOST_WAVE_SYSINCLUDE_FILE_ID); | |
219 | macro_include_file.set_id(BOOST_WAVE_MACROINCLUDE_FILE_ID); | |
220 | plain_define.set_id(BOOST_WAVE_PLAIN_DEFINE_ID); | |
221 | macro_parameters.set_id(BOOST_WAVE_MACRO_PARAMETERS_ID); | |
222 | macro_definition.set_id(BOOST_WAVE_MACRO_DEFINITION_ID); | |
223 | undefine.set_id(BOOST_WAVE_UNDEFINE_ID); | |
224 | ppifdef.set_id(BOOST_WAVE_IFDEF_ID); | |
225 | ppifndef.set_id(BOOST_WAVE_IFNDEF_ID); | |
226 | ppif.set_id(BOOST_WAVE_IF_ID); | |
227 | ppelif.set_id(BOOST_WAVE_ELIF_ID); | |
228 | // ppelse.set_id(BOOST_WAVE_ELSE_ID); | |
229 | // ppendif.set_id(BOOST_WAVE_ENDIF_ID); | |
230 | ppline.set_id(BOOST_WAVE_LINE_ID); | |
231 | pperror.set_id(BOOST_WAVE_ERROR_ID); | |
232 | ppwarning.set_id(BOOST_WAVE_WARNING_ID); | |
233 | pppragma.set_id(BOOST_WAVE_PRAGMA_ID); | |
234 | illformed.set_id(BOOST_WAVE_ILLFORMED_ID); | |
235 | ppsp.set_id(BOOST_WAVE_PPSPACE_ID); | |
236 | ppqualifiedname.set_id(BOOST_WAVE_PPQUALIFIEDNAME_ID); | |
237 | #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0 | |
238 | ppregion.set_id(BOOST_WAVE_REGION_ID); | |
239 | ppendregion.set_id(BOOST_WAVE_ENDREGION_ID); | |
240 | #endif | |
241 | ||
242 | #if BOOST_WAVE_DUMP_PARSE_TREE != 0 | |
243 | self.map_rule_id_to_name.init_rule_id_to_name_map(self); | |
b32b8144 | 244 | #endif |
7c673cae FG |
245 | |
246 | // recognizes preprocessor directives only | |
247 | ||
b32b8144 FG |
248 | // C++ standard 16.1: A preprocessing directive consists of a sequence |
249 | // of preprocessing tokens. The first token in the sequence is # | |
250 | // preprocessing token that is either the first character in the source | |
251 | // file (optionally after white space containing no new-line | |
252 | // characters) or that follows white space containing at least one | |
253 | // new-line character. The last token in the sequence is the first | |
7c673cae FG |
254 | // new-line character that follows the first token in the sequence. |
255 | ||
256 | pp_statement | |
257 | = ( plain_define | |
258 | // | include_file | |
259 | // | system_include_file | |
260 | | ppif | |
261 | | ppelif | |
262 | | ppifndef | |
263 | | ppifdef | |
264 | | undefine | |
265 | // | ppelse | |
266 | | macro_include_file | |
267 | | ppline | |
268 | | pppragma | |
269 | | pperror | |
270 | | ppwarning | |
271 | // | ppendif | |
272 | #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0 | |
273 | | ppregion | |
274 | | ppendregion | |
275 | #endif | |
276 | | illformed | |
277 | ) | |
278 | >> eol_tokens | |
279 | [ store_found_eoltokens_type(self.found_eoltokens) ] | |
280 | // In parser debug mode it is useful not to flush the underlying stream | |
281 | // to allow its investigation in the debugger and to see the correct | |
282 | // output in the printed debug log.. | |
283 | // Note: this may break the parser, though. | |
284 | #if !(defined(BOOST_SPIRIT_DEBUG) && \ | |
285 | (BOOST_SPIRIT_DEBUG_FLAGS_CPP & BOOST_SPIRIT_DEBUG_FLAGS_CPP_GRAMMAR) \ | |
286 | ) | |
287 | >> impl::flush_underlying_parser_p | |
288 | #endif // !(defined(BOOST_SPIRIT_DEBUG) && | |
289 | ; | |
290 | ||
291 | // // #include ... | |
292 | // include_file // include "..." | |
b32b8144 | 293 | // = ch_p(T_PP_QHEADER) |
7c673cae FG |
294 | // [ store_found_directive_type(self.found_directive) ] |
295 | // #if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0 | |
296 | // | ch_p(T_PP_QHEADER_NEXT) | |
297 | // [ store_found_directive_type(self.found_directive) ] | |
b32b8144 | 298 | // #endif |
7c673cae FG |
299 | // ; |
300 | ||
301 | // system_include_file // include <...> | |
b32b8144 | 302 | // = ch_p(T_PP_HHEADER) |
7c673cae FG |
303 | // [ store_found_directive_type(self.found_directive) ] |
304 | // #if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0 | |
305 | // | ch_p(T_PP_HHEADER_NEXT) | |
306 | // [ store_found_directive_type(self.found_directive) ] | |
b32b8144 | 307 | // #endif |
7c673cae FG |
308 | // ; |
309 | ||
310 | macro_include_file // include ...anything else... | |
311 | = no_node_d | |
312 | [ | |
313 | ch_p(T_PP_INCLUDE) | |
314 | [ store_found_directive_type(self.found_directive) ] | |
315 | #if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0 | |
316 | | ch_p(T_PP_INCLUDE_NEXT) | |
317 | [ store_found_directive_type(self.found_directive) ] | |
318 | #endif | |
319 | ] | |
320 | >> *( anychar_p - | |
b32b8144 | 321 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) |
7c673cae FG |
322 | ) |
323 | ; | |
324 | ||
325 | // #define FOO foo (with optional parameters) | |
326 | plain_define | |
327 | = no_node_d | |
328 | [ | |
b32b8144 | 329 | ch_p(T_PP_DEFINE) |
7c673cae FG |
330 | [ store_found_directive_type(self.found_directive) ] |
331 | >> +ppsp | |
332 | ] | |
b32b8144 FG |
333 | >> ( ch_p(T_IDENTIFIER) |
334 | | pattern_p(KeywordTokenType, | |
7c673cae | 335 | TokenTypeMask|PPTokenFlag) |
b32b8144 | 336 | | pattern_p(OperatorTokenType|AltExtTokenType, |
7c673cae | 337 | ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc. |
b32b8144 | 338 | | pattern_p(BoolLiteralTokenType, |
7c673cae FG |
339 | TokenTypeMask|PPTokenFlag) // true/false |
340 | ) | |
341 | >> ( ( no_node_d[eps_p(ch_p(T_LEFTPAREN))] | |
342 | >> macro_parameters | |
343 | >> !macro_definition | |
344 | ) | |
b32b8144 | 345 | | !( no_node_d[+ppsp] |
7c673cae FG |
346 | >> macro_definition |
347 | ) | |
348 | ) | |
349 | ; | |
350 | ||
351 | // parameter list | |
352 | // normal C++ mode | |
353 | macro_parameters | |
354 | = confix_p( | |
355 | no_node_d[ch_p(T_LEFTPAREN) >> *ppsp], | |
356 | !list_p( | |
b32b8144 FG |
357 | ( ch_p(T_IDENTIFIER) |
358 | | pattern_p(KeywordTokenType, | |
7c673cae | 359 | TokenTypeMask|PPTokenFlag) |
b32b8144 | 360 | | pattern_p(OperatorTokenType|AltExtTokenType, |
7c673cae | 361 | ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc. |
b32b8144 | 362 | | pattern_p(BoolLiteralTokenType, |
7c673cae FG |
363 | TokenTypeMask|PPTokenFlag) // true/false |
364 | #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 | |
365 | | ch_p(T_ELLIPSIS) | |
366 | #endif | |
b32b8144 | 367 | ), |
7c673cae FG |
368 | no_node_d[*ppsp >> ch_p(T_COMMA) >> *ppsp] |
369 | ), | |
370 | no_node_d[*ppsp >> ch_p(T_RIGHTPAREN)] | |
371 | ) | |
372 | ; | |
b32b8144 | 373 | |
7c673cae FG |
374 | // macro body (anything left until eol) |
375 | macro_definition | |
376 | = no_node_d[*ppsp] | |
377 | >> *( anychar_p - | |
b32b8144 | 378 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) |
7c673cae FG |
379 | ) |
380 | ; | |
381 | ||
b32b8144 | 382 | // #undef FOO |
7c673cae FG |
383 | undefine |
384 | = no_node_d | |
385 | [ | |
b32b8144 | 386 | ch_p(T_PP_UNDEF) |
7c673cae FG |
387 | [ store_found_directive_type(self.found_directive) ] |
388 | >> +ppsp | |
389 | ] | |
b32b8144 FG |
390 | >> ( ch_p(T_IDENTIFIER) |
391 | | pattern_p(KeywordTokenType, | |
7c673cae | 392 | TokenTypeMask|PPTokenFlag) |
b32b8144 | 393 | | pattern_p(OperatorTokenType|AltExtTokenType, |
7c673cae | 394 | ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc. |
b32b8144 | 395 | | pattern_p(BoolLiteralTokenType, |
7c673cae FG |
396 | TokenTypeMask|PPTokenFlag) // true/false |
397 | ) | |
398 | ; | |
399 | ||
400 | // #ifdef et.al. | |
401 | ppifdef | |
402 | = no_node_d | |
403 | [ | |
b32b8144 | 404 | ch_p(T_PP_IFDEF) |
7c673cae FG |
405 | [ store_found_directive_type(self.found_directive) ] |
406 | >> +ppsp | |
407 | ] | |
408 | >> ppqualifiedname | |
409 | ; | |
410 | ||
411 | ppifndef | |
412 | = no_node_d | |
413 | [ | |
b32b8144 | 414 | ch_p(T_PP_IFNDEF) |
7c673cae FG |
415 | [ store_found_directive_type(self.found_directive) ] |
416 | >> +ppsp | |
417 | ] | |
418 | >> ppqualifiedname | |
419 | ; | |
420 | ||
421 | ppif | |
422 | = no_node_d | |
423 | [ | |
b32b8144 | 424 | ch_p(T_PP_IF) |
7c673cae FG |
425 | [ store_found_directive_type(self.found_directive) ] |
426 | // >> *ppsp | |
427 | ] | |
428 | >> +( anychar_p - | |
b32b8144 | 429 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) |
7c673cae FG |
430 | ) |
431 | ; | |
432 | ||
433 | // ppelse | |
434 | // = no_node_d | |
435 | // [ | |
436 | // ch_p(T_PP_ELSE) | |
437 | // [ store_found_directive_type(self.found_directive) ] | |
438 | // ] | |
439 | // ; | |
440 | ||
441 | ppelif | |
442 | = no_node_d | |
443 | [ | |
b32b8144 | 444 | ch_p(T_PP_ELIF) |
7c673cae FG |
445 | [ store_found_directive_type(self.found_directive) ] |
446 | // >> *ppsp | |
447 | ] | |
448 | >> +( anychar_p - | |
b32b8144 | 449 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) |
7c673cae FG |
450 | ) |
451 | ; | |
452 | ||
453 | // ppendif | |
454 | // = no_node_d | |
455 | // [ | |
456 | // ch_p(T_PP_ENDIF) | |
457 | // [ store_found_directive_type(self.found_directive) ] | |
458 | // ] | |
459 | // ; | |
460 | ||
461 | // #line ... | |
b32b8144 | 462 | ppline |
7c673cae FG |
463 | = no_node_d |
464 | [ | |
b32b8144 | 465 | ch_p(T_PP_LINE) |
7c673cae FG |
466 | [ store_found_directive_type(self.found_directive) ] |
467 | >> *ppsp | |
468 | ] | |
469 | >> +( anychar_p - | |
b32b8144 | 470 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) |
7c673cae FG |
471 | ) |
472 | ; | |
b32b8144 | 473 | |
7c673cae FG |
474 | #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0 |
475 | // #region ... | |
476 | ppregion | |
477 | = no_node_d | |
478 | [ | |
b32b8144 | 479 | ch_p(T_MSEXT_PP_REGION) |
7c673cae FG |
480 | [ store_found_directive_type(self.found_directive) ] |
481 | >> +ppsp | |
482 | ] | |
483 | >> ppqualifiedname | |
484 | ; | |
485 | ||
486 | // #endregion | |
487 | ppendregion | |
488 | = no_node_d | |
489 | [ | |
b32b8144 | 490 | ch_p(T_MSEXT_PP_ENDREGION) |
7c673cae FG |
491 | [ store_found_directive_type(self.found_directive) ] |
492 | ] | |
493 | ; | |
494 | #endif | |
495 | ||
496 | // # something else (ill formed preprocessor directive) | |
497 | illformed // for error reporting | |
498 | = no_node_d | |
499 | [ | |
b32b8144 | 500 | pattern_p(T_POUND, MainTokenMask) |
7c673cae FG |
501 | >> *ppsp |
502 | ] | |
503 | >> ( anychar_p - | |
b32b8144 | 504 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) |
7c673cae FG |
505 | ) |
506 | >> no_node_d | |
507 | [ | |
508 | *( anychar_p - | |
b32b8144 | 509 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) |
7c673cae FG |
510 | ) |
511 | ] | |
512 | ; | |
513 | ||
514 | // #error | |
515 | pperror | |
516 | = no_node_d | |
517 | [ | |
b32b8144 | 518 | ch_p(T_PP_ERROR) |
7c673cae FG |
519 | [ store_found_directive_type(self.found_directive) ] |
520 | >> *ppsp | |
521 | ] | |
522 | >> *( anychar_p - | |
b32b8144 | 523 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) |
7c673cae FG |
524 | ) |
525 | ; | |
526 | ||
527 | // #warning | |
528 | ppwarning | |
529 | = no_node_d | |
530 | [ | |
b32b8144 | 531 | ch_p(T_PP_WARNING) |
7c673cae FG |
532 | [ store_found_directive_type(self.found_directive) ] |
533 | >> *ppsp | |
534 | ] | |
535 | >> *( anychar_p - | |
b32b8144 | 536 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) |
7c673cae FG |
537 | ) |
538 | ; | |
539 | ||
540 | // #pragma ... | |
541 | pppragma | |
542 | = no_node_d | |
543 | [ | |
544 | ch_p(T_PP_PRAGMA) | |
545 | [ store_found_directive_type(self.found_directive) ] | |
b32b8144 | 546 | ] |
7c673cae | 547 | >> *( anychar_p - |
b32b8144 | 548 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) |
7c673cae FG |
549 | ) |
550 | ; | |
551 | ||
552 | ppqualifiedname | |
553 | = no_node_d[*ppsp] | |
b32b8144 FG |
554 | >> ( ch_p(T_IDENTIFIER) |
555 | | pattern_p(KeywordTokenType, | |
7c673cae | 556 | TokenTypeMask|PPTokenFlag) |
b32b8144 | 557 | | pattern_p(OperatorTokenType|AltExtTokenType, |
7c673cae | 558 | ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc. |
b32b8144 | 559 | | pattern_p(BoolLiteralTokenType, |
7c673cae | 560 | TokenTypeMask|PPTokenFlag) // true/false |
b32b8144 | 561 | ) |
7c673cae FG |
562 | ; |
563 | ||
564 | // auxiliary helper rules | |
565 | ppsp // valid space in a line with a preprocessor directive | |
566 | = ch_p(T_SPACE) | ch_p(T_CCOMMENT) | |
567 | ; | |
568 | ||
569 | // end of line tokens | |
b32b8144 | 570 | eol_tokens |
7c673cae FG |
571 | = no_node_d |
572 | [ | |
b32b8144 | 573 | *( ch_p(T_SPACE) |
7c673cae FG |
574 | | ch_p(T_CCOMMENT) |
575 | ) | |
576 | >> ( ch_p(T_NEWLINE) | |
577 | | ch_p(T_CPPCOMMENT) | |
578 | | ch_p(T_EOF) | |
579 | [ store_found_eof_type(self.found_eof) ] | |
580 | ) | |
581 | ] | |
582 | ; | |
583 | ||
584 | BOOST_SPIRIT_DEBUG_TRACE_RULE(pp_statement, TRACE_CPP_GRAMMAR); | |
585 | // BOOST_SPIRIT_DEBUG_TRACE_RULE(include_file, TRACE_CPP_GRAMMAR); | |
586 | // BOOST_SPIRIT_DEBUG_TRACE_RULE(system_include_file, TRACE_CPP_GRAMMAR); | |
587 | BOOST_SPIRIT_DEBUG_TRACE_RULE(macro_include_file, TRACE_CPP_GRAMMAR); | |
588 | BOOST_SPIRIT_DEBUG_TRACE_RULE(plain_define, TRACE_CPP_GRAMMAR); | |
589 | BOOST_SPIRIT_DEBUG_TRACE_RULE(macro_definition, TRACE_CPP_GRAMMAR); | |
590 | BOOST_SPIRIT_DEBUG_TRACE_RULE(macro_parameters, TRACE_CPP_GRAMMAR); | |
591 | BOOST_SPIRIT_DEBUG_TRACE_RULE(undefine, TRACE_CPP_GRAMMAR); | |
592 | BOOST_SPIRIT_DEBUG_TRACE_RULE(ppifdef, TRACE_CPP_GRAMMAR); | |
593 | BOOST_SPIRIT_DEBUG_TRACE_RULE(ppifndef, TRACE_CPP_GRAMMAR); | |
594 | BOOST_SPIRIT_DEBUG_TRACE_RULE(ppif, TRACE_CPP_GRAMMAR); | |
595 | // BOOST_SPIRIT_DEBUG_TRACE_RULE(ppelse, TRACE_CPP_GRAMMAR); | |
596 | // BOOST_SPIRIT_DEBUG_TRACE_RULE(ppelif, TRACE_CPP_GRAMMAR); | |
597 | BOOST_SPIRIT_DEBUG_TRACE_RULE(ppendif, TRACE_CPP_GRAMMAR); | |
598 | BOOST_SPIRIT_DEBUG_TRACE_RULE(ppline, TRACE_CPP_GRAMMAR); | |
599 | BOOST_SPIRIT_DEBUG_TRACE_RULE(pperror, TRACE_CPP_GRAMMAR); | |
600 | BOOST_SPIRIT_DEBUG_TRACE_RULE(ppwarning, TRACE_CPP_GRAMMAR); | |
601 | BOOST_SPIRIT_DEBUG_TRACE_RULE(illformed, TRACE_CPP_GRAMMAR); | |
602 | BOOST_SPIRIT_DEBUG_TRACE_RULE(ppsp, TRACE_CPP_GRAMMAR); | |
603 | BOOST_SPIRIT_DEBUG_TRACE_RULE(ppqualifiedname, TRACE_CPP_GRAMMAR); | |
604 | #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0 | |
605 | BOOST_SPIRIT_DEBUG_TRACE_RULE(ppregion, TRACE_CPP_GRAMMAR); | |
606 | BOOST_SPIRIT_DEBUG_TRACE_RULE(ppendregion, TRACE_CPP_GRAMMAR); | |
607 | #endif | |
608 | } | |
609 | ||
20effc67 | 610 | // start rule of this grammar |
7c673cae FG |
611 | rule_type const& start() const |
612 | { return pp_statement; } | |
613 | }; | |
614 | ||
615 | bool &found_eof; | |
616 | TokenT &found_directive; | |
617 | ContainerT &found_eoltokens; | |
b32b8144 FG |
618 | |
619 | cpp_grammar(bool &found_eof_, TokenT &found_directive_, | |
7c673cae | 620 | ContainerT &found_eoltokens_) |
b32b8144 | 621 | : found_eof(found_eof_), |
7c673cae FG |
622 | found_directive(found_directive_), |
623 | found_eoltokens(found_eoltokens_) | |
b32b8144 FG |
624 | { |
625 | BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(*this, "cpp_grammar", | |
626 | TRACE_CPP_GRAMMAR); | |
7c673cae FG |
627 | } |
628 | ||
629 | #if BOOST_WAVE_DUMP_PARSE_TREE != 0 | |
20effc67 | 630 | // helper function and data to get readable names of the rules known to us |
7c673cae | 631 | struct map_ruleid_to_name : |
b32b8144 | 632 | public std::map<boost::spirit::classic::parser_id, std::string> |
7c673cae FG |
633 | { |
634 | typedef std::map<boost::spirit::classic::parser_id, std::string> base_type; | |
635 | ||
636 | void init_rule_id_to_name_map(cpp_grammar const &self) | |
637 | { | |
638 | struct { | |
639 | int parser_id; | |
640 | char const *rule_name; | |
b32b8144 | 641 | } |
7c673cae FG |
642 | init_ruleid_name_map[] = { |
643 | { BOOST_WAVE_PP_STATEMENT_ID, "pp_statement" }, | |
644 | // { BOOST_WAVE_INCLUDE_FILE_ID, "include_file" }, | |
645 | // { BOOST_WAVE_SYSINCLUDE_FILE_ID, "system_include_file" }, | |
646 | { BOOST_WAVE_MACROINCLUDE_FILE_ID, "macro_include_file" }, | |
647 | { BOOST_WAVE_PLAIN_DEFINE_ID, "plain_define" }, | |
648 | { BOOST_WAVE_MACRO_PARAMETERS_ID, "macro_parameters" }, | |
649 | { BOOST_WAVE_MACRO_DEFINITION_ID, "macro_definition" }, | |
650 | { BOOST_WAVE_UNDEFINE_ID, "undefine" }, | |
651 | { BOOST_WAVE_IFDEF_ID, "ppifdef" }, | |
652 | { BOOST_WAVE_IFNDEF_ID, "ppifndef" }, | |
653 | { BOOST_WAVE_IF_ID, "ppif" }, | |
654 | { BOOST_WAVE_ELIF_ID, "ppelif" }, | |
655 | // { BOOST_WAVE_ELSE_ID, "ppelse" }, | |
656 | // { BOOST_WAVE_ENDIF_ID, "ppendif" }, | |
657 | { BOOST_WAVE_LINE_ID, "ppline" }, | |
658 | { BOOST_WAVE_ERROR_ID, "pperror" }, | |
659 | { BOOST_WAVE_WARNING_ID, "ppwarning" }, | |
660 | { BOOST_WAVE_PRAGMA_ID, "pppragma" }, | |
661 | { BOOST_WAVE_ILLFORMED_ID, "illformed" }, | |
662 | { BOOST_WAVE_PPSPACE_ID, "ppspace" }, | |
663 | { BOOST_WAVE_PPQUALIFIEDNAME_ID, "ppqualifiedname" }, | |
664 | #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0 | |
665 | { BOOST_WAVE_REGION_ID, "ppregion" }, | |
666 | { BOOST_WAVE_ENDREGION_ID, "ppendregion" }, | |
667 | #endif | |
668 | { 0 } | |
669 | }; | |
670 | ||
20effc67 | 671 | // initialize parser_id to rule_name map |
7c673cae FG |
672 | for (int i = 0; 0 != init_ruleid_name_map[i].parser_id; ++i) |
673 | base_type::insert(base_type::value_type( | |
b32b8144 | 674 | boost::spirit::classic::parser_id(init_ruleid_name_map[i].parser_id), |
7c673cae FG |
675 | std::string(init_ruleid_name_map[i].rule_name)) |
676 | ); | |
677 | } | |
678 | }; | |
679 | mutable map_ruleid_to_name map_rule_id_to_name; | |
680 | #endif // WAVE_DUMP_PARSE_TREE != 0 | |
681 | }; | |
682 | ||
683 | /////////////////////////////////////////////////////////////////////////////// | |
684 | #undef TRACE_CPP_GRAMMAR | |
685 | ||
686 | /////////////////////////////////////////////////////////////////////////////// | |
687 | // | |
688 | // Special parse function generating a parse tree using a given node_factory. | |
689 | // | |
690 | /////////////////////////////////////////////////////////////////////////////// | |
691 | template <typename NodeFactoryT, typename IteratorT, typename ParserT> | |
692 | inline boost::spirit::classic::tree_parse_info<IteratorT, NodeFactoryT> | |
693 | parsetree_parse(IteratorT const& first_, IteratorT const& last, | |
694 | boost::spirit::classic::parser<ParserT> const& p) | |
695 | { | |
696 | using namespace boost::spirit::classic; | |
b32b8144 | 697 | |
7c673cae FG |
698 | typedef pt_match_policy<IteratorT, NodeFactoryT> pt_match_policy_type; |
699 | typedef scanner_policies<iteration_policy, pt_match_policy_type> | |
700 | scanner_policies_type; | |
701 | typedef scanner<IteratorT, scanner_policies_type> scanner_type; | |
702 | ||
703 | scanner_policies_type policies; | |
704 | IteratorT first = first_; | |
705 | scanner_type scan(first, last, policies); | |
706 | tree_match<IteratorT, NodeFactoryT> hit = p.derived().parse(scan); | |
707 | return tree_parse_info<IteratorT, NodeFactoryT>( | |
708 | first, hit, hit && (first == last), hit.length(), hit.trees); | |
709 | } | |
710 | ||
711 | /////////////////////////////////////////////////////////////////////////////// | |
b32b8144 FG |
712 | // |
713 | // The following parse function is defined here, to allow the separation of | |
7c673cae | 714 | // the compilation of the cpp_grammar from the function using it. |
b32b8144 | 715 | // |
7c673cae FG |
716 | /////////////////////////////////////////////////////////////////////////////// |
717 | ||
718 | #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0 | |
719 | #define BOOST_WAVE_GRAMMAR_GEN_INLINE | |
720 | #else | |
721 | #define BOOST_WAVE_GRAMMAR_GEN_INLINE inline | |
b32b8144 | 722 | #endif |
7c673cae FG |
723 | |
724 | template <typename LexIteratorT, typename TokenContainerT> | |
b32b8144 | 725 | BOOST_WAVE_GRAMMAR_GEN_INLINE |
7c673cae | 726 | boost::spirit::classic::tree_parse_info< |
b32b8144 | 727 | LexIteratorT, |
7c673cae FG |
728 | typename cpp_grammar_gen<LexIteratorT, TokenContainerT>::node_factory_type |
729 | > | |
730 | cpp_grammar_gen<LexIteratorT, TokenContainerT>::parse_cpp_grammar ( | |
731 | LexIteratorT const &first, LexIteratorT const &last, | |
732 | position_type const &act_pos, bool &found_eof, | |
733 | token_type &found_directive, token_container_type &found_eoltokens) | |
734 | { | |
735 | using namespace boost::spirit::classic; | |
736 | using namespace boost::wave; | |
b32b8144 | 737 | |
7c673cae | 738 | cpp_grammar<token_type, TokenContainerT> g(found_eof, found_directive, found_eoltokens); |
b32b8144 | 739 | tree_parse_info<LexIteratorT, node_factory_type> hit = |
7c673cae | 740 | parsetree_parse<node_factory_type>(first, last, g); |
b32b8144 | 741 | |
7c673cae FG |
742 | #if BOOST_WAVE_DUMP_PARSE_TREE != 0 |
743 | if (hit.match) { | |
b32b8144 FG |
744 | tree_to_xml (BOOST_WAVE_DUMP_PARSE_TREE_OUT, hit.trees, "", |
745 | g.map_rule_id_to_name, &token_type::get_token_id, | |
7c673cae FG |
746 | &token_type::get_token_value); |
747 | } | |
748 | #endif | |
749 | ||
750 | return hit; | |
751 | } | |
752 | ||
753 | #undef BOOST_WAVE_GRAMMAR_GEN_INLINE | |
754 | ||
755 | /////////////////////////////////////////////////////////////////////////////// | |
756 | } // namespace grammars | |
757 | } // namespace wave | |
b32b8144 | 758 | } // namespace boost |
7c673cae FG |
759 | |
760 | // the suffix header occurs after all of the code | |
761 | #ifdef BOOST_HAS_ABI_HEADERS | |
762 | #include BOOST_ABI_SUFFIX | |
763 | #endif | |
764 | ||
20effc67 | 765 | #endif // !defined(BOOST_CPP_GRAMMAR_HPP_FEAEBC2E_2734_428B_A7CA_85E5A415E23E_INCLUDED) |