source: NonGTP/Boost/boost/wave/grammars/cpp_grammar.hpp @ 857

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