]>
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_GRAMMAR_HPP_FEAEBC2E_2734_428B_A7CA_85E5A415E23E_INCLUDED) | |
12 | #define CPP_GRAMMAR_HPP_FEAEBC2E_2734_428B_A7CA_85E5A415E23E_INCLUDED | |
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 { | |
41 | namespace wave { | |
42 | namespace grammars { | |
43 | ||
44 | namespace impl { | |
45 | ||
46 | /////////////////////////////////////////////////////////////////////////////// | |
47 | // | |
48 | // store_found_eof | |
49 | // | |
50 | // The store_found_eof functor sets a given flag if the T_EOF token was | |
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_) {} | |
58 | ||
59 | template <typename TokenT> | |
60 | void operator()(TokenT const &/*token*/) const | |
61 | { | |
62 | found_eof = true; | |
63 | } | |
64 | ||
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 | ||
80 | store_found_directive(TokenT &found_directive_) | |
81 | : found_directive(found_directive_) {} | |
82 | ||
83 | void operator()(TokenT const &token) const | |
84 | { | |
85 | found_directive = token; | |
86 | } | |
87 | ||
88 | TokenT &found_directive; | |
89 | }; | |
90 | ||
91 | /////////////////////////////////////////////////////////////////////////////// | |
92 | // | |
93 | // store_found_eoltokens | |
94 | // | |
95 | // The store_found_eoltokens functor stores the token sequence of the | |
96 | // line ending for a particular pp directive | |
97 | // | |
98 | /////////////////////////////////////////////////////////////////////////////// | |
99 | ||
100 | template <typename ContainerT> | |
101 | struct store_found_eoltokens { | |
102 | ||
103 | store_found_eoltokens(ContainerT &found_eoltokens_) | |
104 | : found_eoltokens(found_eoltokens_) {} | |
105 | ||
106 | template <typename IteratorT> | |
107 | void operator()(IteratorT const &first, IteratorT const& last) const | |
108 | { | |
109 | std::copy(first, last, | |
110 | std::inserter(found_eoltokens, found_eoltokens.end())); | |
111 | } | |
112 | ||
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(); | |
137 | return scan.empty_match(); | |
138 | } | |
139 | }; | |
140 | ||
141 | flush_underlying_parser const | |
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> | |
155 | struct cpp_grammar : | |
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; | |
163 | ||
164 | template <typename ScannerT> | |
165 | struct definition | |
166 | { | |
167 | // non-parse_tree generating rule type | |
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; | |
171 | typedef | |
172 | boost::spirit::classic::scanner_policies< | |
173 | iteration_policy_t, match_policy_t, action_policy_t> | |
174 | policies_t; | |
175 | typedef | |
176 | boost::spirit::classic::scanner<typename ScannerT::iterator_t, policies_t> | |
177 | non_tree_scanner_t; | |
178 | typedef | |
179 | boost::spirit::classic::rule< | |
180 | non_tree_scanner_t, boost::spirit::classic::dynamic_parser_tag> | |
181 | no_tree_rule_type; | |
182 | ||
183 | // 'normal' (parse_tree generating) rule type | |
184 | typedef | |
185 | boost::spirit::classic::rule< | |
186 | ScannerT, boost::spirit::classic::dynamic_parser_tag> | |
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; | |
195 | rule_type ppline; | |
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 | ||
208 | definition(cpp_grammar const &self) | |
209 | { | |
210 | // import the spirit and cpplexer namespaces here | |
211 | using namespace boost::spirit::classic; | |
212 | using namespace boost::wave; | |
213 | using namespace boost::wave::util; | |
214 | ||
215 | // set the rule id's for later use | |
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); | |
244 | #endif | |
245 | ||
246 | // recognizes preprocessor directives only | |
247 | ||
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 | |
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 "..." | |
293 | // = ch_p(T_PP_QHEADER) | |
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) ] | |
298 | // #endif | |
299 | // ; | |
300 | ||
301 | // system_include_file // include <...> | |
302 | // = ch_p(T_PP_HHEADER) | |
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) ] | |
307 | // #endif | |
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 - | |
321 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) | |
322 | ) | |
323 | ; | |
324 | ||
325 | // #define FOO foo (with optional parameters) | |
326 | plain_define | |
327 | = no_node_d | |
328 | [ | |
329 | ch_p(T_PP_DEFINE) | |
330 | [ store_found_directive_type(self.found_directive) ] | |
331 | >> +ppsp | |
332 | ] | |
333 | >> ( ch_p(T_IDENTIFIER) | |
334 | | pattern_p(KeywordTokenType, | |
335 | TokenTypeMask|PPTokenFlag) | |
336 | | pattern_p(OperatorTokenType|AltExtTokenType, | |
337 | ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc. | |
338 | | pattern_p(BoolLiteralTokenType, | |
339 | TokenTypeMask|PPTokenFlag) // true/false | |
340 | ) | |
341 | >> ( ( no_node_d[eps_p(ch_p(T_LEFTPAREN))] | |
342 | >> macro_parameters | |
343 | >> !macro_definition | |
344 | ) | |
345 | | !( no_node_d[+ppsp] | |
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( | |
357 | ( ch_p(T_IDENTIFIER) | |
358 | | pattern_p(KeywordTokenType, | |
359 | TokenTypeMask|PPTokenFlag) | |
360 | | pattern_p(OperatorTokenType|AltExtTokenType, | |
361 | ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc. | |
362 | | pattern_p(BoolLiteralTokenType, | |
363 | TokenTypeMask|PPTokenFlag) // true/false | |
364 | #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 | |
365 | | ch_p(T_ELLIPSIS) | |
366 | #endif | |
367 | ), | |
368 | no_node_d[*ppsp >> ch_p(T_COMMA) >> *ppsp] | |
369 | ), | |
370 | no_node_d[*ppsp >> ch_p(T_RIGHTPAREN)] | |
371 | ) | |
372 | ; | |
373 | ||
374 | // macro body (anything left until eol) | |
375 | macro_definition | |
376 | = no_node_d[*ppsp] | |
377 | >> *( anychar_p - | |
378 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) | |
379 | ) | |
380 | ; | |
381 | ||
382 | // #undef FOO | |
383 | undefine | |
384 | = no_node_d | |
385 | [ | |
386 | ch_p(T_PP_UNDEF) | |
387 | [ store_found_directive_type(self.found_directive) ] | |
388 | >> +ppsp | |
389 | ] | |
390 | >> ( ch_p(T_IDENTIFIER) | |
391 | | pattern_p(KeywordTokenType, | |
392 | TokenTypeMask|PPTokenFlag) | |
393 | | pattern_p(OperatorTokenType|AltExtTokenType, | |
394 | ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc. | |
395 | | pattern_p(BoolLiteralTokenType, | |
396 | TokenTypeMask|PPTokenFlag) // true/false | |
397 | ) | |
398 | ; | |
399 | ||
400 | // #ifdef et.al. | |
401 | ppifdef | |
402 | = no_node_d | |
403 | [ | |
404 | ch_p(T_PP_IFDEF) | |
405 | [ store_found_directive_type(self.found_directive) ] | |
406 | >> +ppsp | |
407 | ] | |
408 | >> ppqualifiedname | |
409 | ; | |
410 | ||
411 | ppifndef | |
412 | = no_node_d | |
413 | [ | |
414 | ch_p(T_PP_IFNDEF) | |
415 | [ store_found_directive_type(self.found_directive) ] | |
416 | >> +ppsp | |
417 | ] | |
418 | >> ppqualifiedname | |
419 | ; | |
420 | ||
421 | ppif | |
422 | = no_node_d | |
423 | [ | |
424 | ch_p(T_PP_IF) | |
425 | [ store_found_directive_type(self.found_directive) ] | |
426 | // >> *ppsp | |
427 | ] | |
428 | >> +( anychar_p - | |
429 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) | |
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 | [ | |
444 | ch_p(T_PP_ELIF) | |
445 | [ store_found_directive_type(self.found_directive) ] | |
446 | // >> *ppsp | |
447 | ] | |
448 | >> +( anychar_p - | |
449 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) | |
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 ... | |
462 | ppline | |
463 | = no_node_d | |
464 | [ | |
465 | ch_p(T_PP_LINE) | |
466 | [ store_found_directive_type(self.found_directive) ] | |
467 | >> *ppsp | |
468 | ] | |
469 | >> +( anychar_p - | |
470 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) | |
471 | ) | |
472 | ; | |
473 | ||
474 | #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0 | |
475 | // #region ... | |
476 | ppregion | |
477 | = no_node_d | |
478 | [ | |
479 | ch_p(T_MSEXT_PP_REGION) | |
480 | [ store_found_directive_type(self.found_directive) ] | |
481 | >> +ppsp | |
482 | ] | |
483 | >> ppqualifiedname | |
484 | ; | |
485 | ||
486 | // #endregion | |
487 | ppendregion | |
488 | = no_node_d | |
489 | [ | |
490 | ch_p(T_MSEXT_PP_ENDREGION) | |
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 | [ | |
500 | pattern_p(T_POUND, MainTokenMask) | |
501 | >> *ppsp | |
502 | ] | |
503 | >> ( anychar_p - | |
504 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) | |
505 | ) | |
506 | >> no_node_d | |
507 | [ | |
508 | *( anychar_p - | |
509 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) | |
510 | ) | |
511 | ] | |
512 | ; | |
513 | ||
514 | // #error | |
515 | pperror | |
516 | = no_node_d | |
517 | [ | |
518 | ch_p(T_PP_ERROR) | |
519 | [ store_found_directive_type(self.found_directive) ] | |
520 | >> *ppsp | |
521 | ] | |
522 | >> *( anychar_p - | |
523 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) | |
524 | ) | |
525 | ; | |
526 | ||
527 | // #warning | |
528 | ppwarning | |
529 | = no_node_d | |
530 | [ | |
531 | ch_p(T_PP_WARNING) | |
532 | [ store_found_directive_type(self.found_directive) ] | |
533 | >> *ppsp | |
534 | ] | |
535 | >> *( anychar_p - | |
536 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) | |
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) ] | |
546 | ] | |
547 | >> *( anychar_p - | |
548 | (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) | |
549 | ) | |
550 | ; | |
551 | ||
552 | ppqualifiedname | |
553 | = no_node_d[*ppsp] | |
554 | >> ( ch_p(T_IDENTIFIER) | |
555 | | pattern_p(KeywordTokenType, | |
556 | TokenTypeMask|PPTokenFlag) | |
557 | | pattern_p(OperatorTokenType|AltExtTokenType, | |
558 | ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc. | |
559 | | pattern_p(BoolLiteralTokenType, | |
560 | TokenTypeMask|PPTokenFlag) // true/false | |
561 | ) | |
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 | |
570 | eol_tokens | |
571 | = no_node_d | |
572 | [ | |
573 | *( ch_p(T_SPACE) | |
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 | ||
610 | // start rule of this grammar | |
611 | rule_type const& start() const | |
612 | { return pp_statement; } | |
613 | }; | |
614 | ||
615 | bool &found_eof; | |
616 | TokenT &found_directive; | |
617 | ContainerT &found_eoltokens; | |
618 | ||
619 | cpp_grammar(bool &found_eof_, TokenT &found_directive_, | |
620 | ContainerT &found_eoltokens_) | |
621 | : found_eof(found_eof_), | |
622 | found_directive(found_directive_), | |
623 | found_eoltokens(found_eoltokens_) | |
624 | { | |
625 | BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(*this, "cpp_grammar", | |
626 | TRACE_CPP_GRAMMAR); | |
627 | } | |
628 | ||
629 | #if BOOST_WAVE_DUMP_PARSE_TREE != 0 | |
630 | // helper function and data to get readable names of the rules known to us | |
631 | struct map_ruleid_to_name : | |
632 | public std::map<boost::spirit::classic::parser_id, std::string> | |
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; | |
641 | } | |
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 | ||
671 | // initialize parser_id to rule_name map | |
672 | for (int i = 0; 0 != init_ruleid_name_map[i].parser_id; ++i) | |
673 | base_type::insert(base_type::value_type( | |
674 | boost::spirit::classic::parser_id(init_ruleid_name_map[i].parser_id), | |
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; | |
697 | ||
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 | /////////////////////////////////////////////////////////////////////////////// | |
712 | // | |
713 | // The following parse function is defined here, to allow the separation of | |
714 | // the compilation of the cpp_grammar from the function using it. | |
715 | // | |
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 | |
722 | #endif | |
723 | ||
724 | template <typename LexIteratorT, typename TokenContainerT> | |
725 | BOOST_WAVE_GRAMMAR_GEN_INLINE | |
726 | boost::spirit::classic::tree_parse_info< | |
727 | LexIteratorT, | |
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; | |
737 | ||
738 | cpp_grammar<token_type, TokenContainerT> g(found_eof, found_directive, found_eoltokens); | |
739 | tree_parse_info<LexIteratorT, node_factory_type> hit = | |
740 | parsetree_parse<node_factory_type>(first, last, g); | |
741 | ||
742 | #if BOOST_WAVE_DUMP_PARSE_TREE != 0 | |
743 | if (hit.match) { | |
744 | tree_to_xml (BOOST_WAVE_DUMP_PARSE_TREE_OUT, hit.trees, "", | |
745 | g.map_rule_id_to_name, &token_type::get_token_id, | |
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 | |
758 | } // namespace boost | |
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 | ||
765 | #endif // !defined(CPP_GRAMMAR_HPP_FEAEBC2E_2734_428B_A7CA_85E5A415E23E_INCLUDED) |