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 
store_found_eofboost::wave::grammars::impl::store_found_eof57         store_found_eof(bool &found_eof_) : found_eof(found_eof_) {}
58 
59         template <typename TokenT>
operator ()boost::wave::grammars::impl::store_found_eof60         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 
store_found_directiveboost::wave::grammars::impl::store_found_directive80         store_found_directive(TokenT &found_directive_)
81         :   found_directive(found_directive_) {}
82 
operator ()boost::wave::grammars::impl::store_found_directive83         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 
store_found_eoltokensboost::wave::grammars::impl::store_found_eoltokens103         store_found_eoltokens(ContainerT &found_eoltokens_)
104         :   found_eoltokens(found_eoltokens_) {}
105 
106         template <typename IteratorT>
operator ()boost::wave::grammars::impl::store_found_eoltokens107         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
parseboost::wave::grammars::impl::flush_underlying_parser134         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 
definitionboost::wave::grammars::cpp_grammar::definition208         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
startboost::wave::grammars::cpp_grammar::definition611         rule_type const& start() const
612         { return pp_statement; }
613     };
614 
615     bool &found_eof;
616     TokenT &found_directive;
617     ContainerT &found_eoltokens;
618 
cpp_grammarboost::wave::grammars::cpp_grammar619     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 
init_rule_id_to_name_mapboost::wave::grammars::cpp_grammar::map_ruleid_to_name636         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>
parsetree_parse(IteratorT const & first_,IteratorT const & last,boost::spirit::classic::parser<ParserT> const & p)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 >
parse_cpp_grammar(LexIteratorT const & first,LexIteratorT const & last,position_type const & act_pos,bool & found_eof,token_type & found_directive,token_container_type & found_eoltokens)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)
766