1 //  Hannibal: partial C++ grammar to parse C++ type information
2 //  Copyright (c) 2005-2006 Danny Havenith
3 //
4 //  Boost.Wave: A Standard compliant C++ preprocessor
5 //  Copyright (c) 2001-2009 Hartmut Kaiser
6 //
7 //  http://www.boost.org/
8 //
9 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
10 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
11 
12 #if !defined(BOOST_HANNIBAL_TRANSLATION_UNIT_GRAMMAR_H_INCLUDED)
13 #define BOOST_HANNIBAL_TRANSLATION_UNIT_GRAMMAR_H_INCLUDED
14 
15 #include <map>
16 #if defined(HANNIBAL_TRACE_DECLARATIONS)
17 #include <iostream>
18 #endif
19 
20 #include <boost/assert.hpp>
21 #include <boost/spirit/include/classic_core.hpp>
22 #include <boost/spirit/include/classic_confix.hpp>
23 
24 #include <boost/wave/wave_config.hpp>
25 #include <boost/wave/token_ids.hpp>
26 #include <boost/wave/util/pattern_parser.hpp>
27 
28 //
29 // If so required, trace every declaration and member-declaration.
30 // This can be a much faster alternative to BOOST_SPIRIT_DEBUG-type of
31 // debugging.
32 //
33 #ifdef HANNIBAL_TRACE_DECLARATIONS
34 struct trace_actor
35 {
trace_actortrace_actor36     trace_actor(
37         const char rule_type[],
38         std::ostream &strm
39         )
40         : strm_( strm), rule_type_( rule_type)
41     {
42         // nop
43     }
44 
45     template<typename PositionIterator>
operatortrace_actor46     void operator()(PositionIterator begin, PositionIterator end) const
47     {
48         typedef const boost::wave::cpplexer::lex_token<>::position_type
49             position_type;
50         //typedef pos_iterator_type::token_type::position_type position_type;
51 
52         position_type &begin_pos(begin->get_position());
53 
54         strm_ << "Parsed " << rule_type_ << std::endl;
55         strm_ << " from: " << begin_pos.get_file()
56               << "(" << begin_pos.get_line() << ")"
57               << std::endl;
58     };
59 
60 private:
61     std::ostream &strm_;
62     char const* const rule_type_;
63 };
64 
65 #define HANNIBAL_TRACE_ACTION( type) [trace_actor( (type), std::cout)]
66 #else
67 #define HANNIBAL_TRACE_ACTION( type)
68 #endif
69 
70 ///////////////////////////////////////////////////////////////////////////////
71 #define HANNIBAL_TRACE_TRANSLATION_UNIT_GRAMMAR                               \
72     bool(BOOST_SPIRIT_DEBUG_FLAGS_CPP & BOOST_SPIRIT_DEBUG_FLAGS_CPP_EXPR_GRAMMAR) \
73     /**/
74 
75 ///////////////////////////////////////////////////////////////////////////////
76 //  Helper macro to register rules for debugging
77 #if HANNIBAL_DUMP_PARSE_TREE != 0
78 #define HANNIBAL_REGISTER_RULE(r)                                             \
79     BOOST_SPIRIT_DEBUG_NODE(r);                                               \
80     self.declare_rule(r, #r)                                                  \
81     /**/
82 #else
83 #define HANNIBAL_REGISTER_RULE(r)                                             \
84     BOOST_SPIRIT_DEBUG_NODE(r)                                                \
85     /**/
86 #endif
87 
88 ///////////////////////////////////////////////////////////////////////////////
89 struct dump_actor {
90     template<typename ForwardIterator>
operatordump_actor91     void operator()(ForwardIterator begin, ForwardIterator end)
92     {
93         std::cerr << "*** COULD NOT PARSE THE FOLLOWING ***" << std::endl;
94         while (begin != end)
95         {
96             std::cerr << begin->get_value();
97             ++begin;
98         }
99     }
100 } dump_a;
101 
102 ///////////////////////////////////////////////////////////////////////////////
103 struct translation_unit_grammar
104 :   public boost::spirit::classic::grammar<translation_unit_grammar>
105 {
106 #if HANNIBAL_DUMP_PARSE_TREE != 0
107 //
108 // allow an external map with rule-id -> rule-name mappings.
109 // this map is external so it can be altered by the definition constructor,
110 // which receives a const grammar object.
111 //
112 // Please Note: the lifetime of the rule map should at least extend beyond the
113 // call of the definition constructor...
114 //
115     typedef std::map<boost::spirit::classic::parser_id, std::string>
116         rule_map_type;
117 
118     translation_unit_grammar(rule_map_type *rule_map_ptr_ = 0)
rule_map_ptrtranslation_unit_grammar119     :   rule_map_ptr(rule_map_ptr_)
120 #else
121     translation_unit_grammar()
122 #endif
123     {
124         BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(*this,
125             "translation_unit_grammar", HANNIBAL_TRACE_TRANSLATION_UNIT_GRAMMAR);
126     }
127 
128     template <typename ScannerT>
129     struct definition
130     {
131         // declare non-terminals
132         typedef boost::spirit::classic::rule<ScannerT> rule_type;
133 
134         rule_type constant_expression;
135         rule_type logical_or_exp, logical_and_exp;
136         rule_type inclusive_or_exp, exclusive_or_exp, and_exp;
137         rule_type cmp_equality, cmp_relational;
138         rule_type shift_exp;
139         rule_type add_exp, multiply_exp;
140         rule_type unary_exp, primary_exp, constant;
141 
142         boost::spirit::classic::subrule<0> const_exp_subrule;
143         boost::spirit::classic::subrule<1> shift_exp_clos;
144 
145         rule_type simple_type_name, class_keywords;
146         rule_type storage_class_specifier, cv_qualifier, function_specifier;
147         rule_type access_specifier;
148         rule_type extension_type_decorator;
149         rule_type operator_sym;
150         rule_type class_key;
151         rule_type enumerator;
152         rule_type enumerator_list;
153         rule_type enumerator_definition;
154         rule_type member_declarator;
155         rule_type member_declarator_list;
156         rule_type member_declaration;
157         rule_type constant_initializer;
158         rule_type pure_specifier;
159         rule_type namespace_body;
160         rule_type type_id;
161         rule_type unnamed_namespace_definition;
162         rule_type extension_namespace_definition;
163         rule_type original_namespace_definition;
164         rule_type named_namespace_definition;
165         rule_type namespace_definition;
166         rule_type linkage_specification;
167         rule_type explicit_specialization;
168         rule_type using_directive;
169         rule_type using_declaration;
170         rule_type type_parameter;
171         rule_type template_parameter;
172         rule_type template_parameter_list;
173         rule_type template_declaration;
174         rule_type explicit_instantiation;
175         rule_type qualified_namespace_specifier;
176         rule_type namespace_alias_definition;
177         rule_type expression_list;
178         rule_type initializer_list;
179         rule_type initializer_clause;
180         rule_type initializer;
181         rule_type init_declarator;
182         rule_type init_declarator_list;
183         rule_type asm_definition;
184         rule_type simple_declaration;
185         rule_type block_declaration;
186         rule_type declaration;
187         rule_type declaration_seq;
188         rule_type translation_unit;
189 
190         rule_type function_definition, function_definition_helper, declarator;
191         rule_type direct_declarator, parameters_or_array_spec;
192         rule_type abstract_declarator, direct_abstract_declarator;
193         rule_type direct_abstract_declarator_helper;
194         rule_type parameter_declaration_clause, parameter_declaration_list;
195         rule_type parameter_declaration, assignment_expression, decimal_literal;
196         rule_type octal_literal, hexadecimal_literal;
197         rule_type declarator_id, id_expression, qualified_id, unqualified_id;
198         rule_type operator_function_id, conversion_function_id, conversion_type_id;
199         rule_type conversion_declarator, function_body;
200         rule_type compound_statement, ctor_initializer, ptr_operator;
201         rule_type decl_specifier, type_specifier;
202         rule_type type_specifier_seq, cv_qualifier_seq, enum_specifier;
203         rule_type enum_keyword, simple_type_specifier;
204         rule_type class_specifier, member_specification, class_head;
205         rule_type type_name, elaborated_type_specifier, template_argument_list;
206         rule_type template_argument, nested_name_specifier;
207         rule_type class_or_namespace_name, class_name, enum_name, typedef_name;
208         rule_type namespace_name, template_id;
209         rule_type decl_specifier_seq, no_type_decl_specifier;
210         rule_type function_try_block, handler_seq, handler;
211         rule_type exception_specification, template_name;
212         rule_type original_namespace_name, base_specifier;
213         rule_type base_specifier_list, base_clause;
214         rule_type odd_language_extension, mem_initializer_id;
215         rule_type mem_initializer, mem_initializer_list;
216 
217 
218         rule_type ta_expression_operator;
219         rule_type ta_logical_or_expression;
220         rule_type ta_expression;
221         rule_type ta_conditional_expression;
222         rule_type ta_throw_expression;
223         rule_type ta_assignment_expression;
224         rule_type postfix_expression_helper;
225         rule_type simple_postfix_expression;
226         rule_type pseudo_destructor_name;
227         rule_type direct_new_declarator;
228         rule_type new_declarator;
229         rule_type new_initializer;
230         rule_type new_type_id;
231         rule_type new_placement;
232         rule_type delete_expression;
233         rule_type new_expression;
234         rule_type unary_operator;
235         rule_type postfix_expression;
236         rule_type unary_expression;
237         rule_type expression_operator;
238         rule_type cast_expression;
239         rule_type throw_expression;
240         rule_type assignment_operator;
241         rule_type logical_or_expression;
242         rule_type conditional_expression;
243         rule_type boolean_literal;
244         rule_type string_literal;
245         rule_type floating_literal;
246         rule_type character_literal;
247         rule_type integer_literal;
248         rule_type expression;
249         rule_type literal;
250         rule_type primary_expression;
251 
252         //
253         // grammar definition.
254 
definitiontranslation_unit_grammar::definition255         definition(translation_unit_grammar const& self)
256         {
257             using namespace boost::spirit::classic;
258             using namespace boost::wave;
259             using boost::wave::util::pattern_p;
260 
261             //
262             // First, a long list of expression rules.
263             //
264             HANNIBAL_REGISTER_RULE( primary_expression);
265             primary_expression
266                 =   literal
267                 |   ch_p(T_THIS)
268                 |   ch_p(T_COLON_COLON) >> ch_p(T_IDENTIFIER)
269                 |   ch_p(T_COLON_COLON) >> operator_function_id
270                 |   ch_p(T_COLON_COLON) >> qualified_id
271                 |   ch_p(T_LEFTPAREN) >> expression >> ch_p(T_RIGHTPAREN)
272                 |   id_expression
273                 ;
274 
275             HANNIBAL_REGISTER_RULE( literal);
276             literal
277                 =   integer_literal
278                 |   character_literal
279                 |   floating_literal
280                 |   string_literal
281                 |   boolean_literal
282                 ;
283 
284             HANNIBAL_REGISTER_RULE( integer_literal);
285             integer_literal
286                 =   pattern_p( IntegerLiteralTokenType, TokenTypeMask)
287                 ;
288 
289             HANNIBAL_REGISTER_RULE( character_literal);
290             character_literal
291                 =   pattern_p( CharacterLiteralTokenType, TokenTypeMask)
292                 ;
293 
294             HANNIBAL_REGISTER_RULE( floating_literal);
295             floating_literal
296                 =   pattern_p( FloatingLiteralTokenType, TokenTypeMask)
297                 ;
298 
299             HANNIBAL_REGISTER_RULE( string_literal);
300             string_literal
301                 =   pattern_p( StringLiteralTokenType, TokenTypeMask)
302                 ;
303 
304             HANNIBAL_REGISTER_RULE( boolean_literal);
305             boolean_literal
306                 =   pattern_p( BoolLiteralTokenType, TokenTypeMask)
307                 ;
308 
309             //
310             // TODO: separate assignment expression into a grammar of it's own
311             //
312             HANNIBAL_REGISTER_RULE( assignment_expression);
313             assignment_expression
314                 =   conditional_expression
315                 |   logical_or_expression >> assignment_operator >> assignment_expression
316                 |   throw_expression
317                 ;
318 
319             //
320             // Have a separate assignment expression for template arguments.
321             // This is needed, because without it, an expression of the form
322             // template < a, b, c > x;
323             // would not parse, since the 'c > x' part would be taken by the
324             // assignment expression.
325             //
326             // Note that this ta_xxxxx duplication cascades all the way down to
327             // logical_or_expression.
328             // Both the previous example and a declaration of the form
329             // template < a, b, (c > d) > x;
330             // should parse fine now.
331             //
332             //
333             HANNIBAL_REGISTER_RULE( ta_assignment_expression);
334             ta_assignment_expression
335                 =   ta_conditional_expression
336                 |   ta_logical_or_expression >> assignment_operator >> ta_assignment_expression
337                 |   ta_throw_expression
338                 ;
339 
340             HANNIBAL_REGISTER_RULE( throw_expression);
341             throw_expression
342                 =   ch_p(T_THROW) >> !assignment_expression
343                 ;
344 
345             HANNIBAL_REGISTER_RULE( ta_throw_expression);
346             ta_throw_expression
347                 =   ch_p(T_THROW) >> !ta_assignment_expression
348                 ;
349 
350             HANNIBAL_REGISTER_RULE( conditional_expression);
351             conditional_expression
352                 =   logical_or_expression
353                     >> !(
354                                 ch_p(T_QUESTION_MARK)
355                             >>  expression
356                             >>  ch_p(T_COLON)
357                             >>  assignment_expression
358                         )
359                 ;
360 
361             HANNIBAL_REGISTER_RULE( ta_conditional_expression);
362             ta_conditional_expression
363                 =   ta_logical_or_expression
364                     >> !(
365                                 ch_p(T_QUESTION_MARK)
366                             >>  ta_expression
367                             >>  ch_p(T_COLON)
368                             >>  ta_assignment_expression
369                         )
370                 ;
371 
372             HANNIBAL_REGISTER_RULE( expression);
373             expression
374                 =   assignment_expression % ch_p(T_COMMA);
375 
376             HANNIBAL_REGISTER_RULE( ta_expression);
377             ta_expression
378                 =   ta_assignment_expression % ch_p(T_COMMA);
379 
380             HANNIBAL_REGISTER_RULE( assignment_operator);
381             assignment_operator
382                 =   pp(T_ASSIGN)
383                 |   pp(T_ANDASSIGN)
384                 |   pp(T_ORASSIGN)
385                 |   pp(T_XORASSIGN)
386                 |   pp(T_DIVIDEASSIGN)
387                 |   pp(T_MINUSASSIGN)
388                 |   pp(T_PERCENTASSIGN)
389                 |   pp(T_PLUSASSIGN)
390                 |   pp(T_SHIFTLEFTASSIGN)
391                 |   pp(T_SHIFTRIGHTASSIGN)
392                 |   pp(T_STARASSIGN)
393                 ;
394 
395 
396             // we skip quite a few rules here, since we're not interested in operator precedence
397             // just now.
398             HANNIBAL_REGISTER_RULE( logical_or_expression);
399             logical_or_expression
400                 =   cast_expression % expression_operator
401                 ;
402 
403             HANNIBAL_REGISTER_RULE( ta_logical_or_expression);
404             ta_logical_or_expression
405                 =   cast_expression % ta_expression_operator
406                 ;
407 
408             HANNIBAL_REGISTER_RULE( expression_operator );
409             expression_operator
410                 =   ta_expression_operator | pp(T_GREATER)
411                 ;
412 
413             HANNIBAL_REGISTER_RULE( ta_expression_operator );
414             ta_expression_operator
415                 =   pp(T_OROR)
416                 |   pp(T_ANDAND)
417                 |   pp(T_OR)
418                 |   pp(T_XOR)
419                 |   pp(T_AND)
420                 |   pp(T_NOTEQUAL)
421                 |   pp(T_EQUAL)
422                 |   pp(T_GREATEREQUAL)
423                 |   pp(T_LESSEQUAL)
424                 |   pp(T_LESS)
425                 |   pp(T_SHIFTLEFT)
426                 |   pp(T_SHIFTRIGHT)
427                 |   pp(T_PLUS)
428                 |   pp(T_MINUS)
429                 |   pp(T_PERCENT)
430                 |   pp(T_DIVIDE)
431                 |   pp(T_STAR)
432                 |   pp(T_ARROWSTAR)
433                 |   pp(T_DOTSTAR)
434                 ;
435 
436             HANNIBAL_REGISTER_RULE( cast_expression);
437             cast_expression
438                 =   ch_p(T_LEFTPAREN) >> type_id >> ch_p(T_RIGHTPAREN)
439                     >>  cast_expression
440                 |   unary_expression
441                 ;
442 
443             HANNIBAL_REGISTER_RULE( unary_expression);
444             unary_expression
445                 =     postfix_expression
446                 |   ch_p(T_PLUSPLUS) >> cast_expression
447                 |   ch_p(T_MINUSMINUS) >> cast_expression
448                 |   unary_operator >> cast_expression
449                 |   ch_p(T_SIZEOF) >> unary_expression
450                 |   ch_p(T_SIZEOF)
451                     >> ch_p(T_LEFTPAREN) >> type_id >> ch_p(T_RIGHTPAREN)
452                 |   new_expression
453                 |   delete_expression
454                 ;
455 
456             HANNIBAL_REGISTER_RULE( unary_operator);
457             unary_operator
458                 =   ch_p(T_STAR)
459                 |   pp(T_AND)
460                 |   pp(T_PLUS)
461                 |   ch_p(T_MINUS)
462                 |   ch_p(T_NOT)
463                 |   pp(T_COMPL)
464                 ;
465 
466             HANNIBAL_REGISTER_RULE( new_expression);
467             new_expression
468                 =  !ch_p(T_COLON_COLON) >> ch_p(T_NEW) >> !new_placement
469                     >>  (
470                             new_type_id >> !new_initializer
471                         |   ch_p(T_LEFTPAREN) >> type_id >> ch_p(T_RIGHTPAREN) >> !new_initializer
472                         )
473                 ;
474 
475             HANNIBAL_REGISTER_RULE( new_placement);
476             new_placement
477                 =   ch_p(T_LEFTPAREN) >> expression_list >> ch_p(T_RIGHTPAREN)
478                 ;
479 
480             HANNIBAL_REGISTER_RULE( new_type_id);
481             new_type_id
482                 =   type_specifier_seq >> !new_declarator
483                 ;
484 
485             HANNIBAL_REGISTER_RULE( new_declarator);
486             new_declarator
487                 =   ptr_operator >> !new_declarator
488                 |   direct_new_declarator
489                 ;
490 
491             HANNIBAL_REGISTER_RULE( direct_new_declarator);
492             direct_new_declarator
493                 =  *(   pp(T_LEFTBRACKET) >> expression >> pp(T_RIGHTBRACKET) )
494                     >>  pp(T_LEFTBRACKET) >> constant_expression >> pp(T_RIGHTBRACKET)
495                 ;
496 
497             HANNIBAL_REGISTER_RULE( new_initializer);
498             new_initializer
499                 =   ch_p(T_LEFTPAREN) >> !expression_list >> ch_p(T_RIGHTPAREN)
500                 ;
501 
502             HANNIBAL_REGISTER_RULE( delete_expression);
503             delete_expression
504                 =  !ch_p(T_COLON_COLON) >> ch_p(T_DELETE) >> cast_expression
505                 |  !ch_p(T_COLON_COLON) >> ch_p(T_DELETE)
506                     >>  pp(T_LEFTBRACKET) >> pp(T_RIGHTBRACKET)
507                     >>  cast_expression
508                 ;
509 
510             HANNIBAL_REGISTER_RULE( postfix_expression);
511             postfix_expression
512                 =   simple_postfix_expression >> *postfix_expression_helper
513                 ;
514 
515             HANNIBAL_REGISTER_RULE( simple_postfix_expression);
516             simple_postfix_expression
517                 =   primary_expression
518                 |   simple_type_specifier
519                     >>  ch_p(T_LEFTPAREN) >> !expression_list >> ch_p(T_RIGHTPAREN)
520                 |   ch_p(T_DYNAMICCAST)
521                     >>  ch_p(T_LESS) >> type_id >> ch_p(T_GREATER)
522                     >>  ch_p(T_LEFTPAREN) >> expression >> ch_p(T_RIGHTPAREN)
523                 |   ch_p(T_STATICCAST)
524                     >>  ch_p(T_LESS) >> type_id >> ch_p(T_GREATER)
525                     >>  ch_p(T_LEFTPAREN) >> expression >> ch_p(T_RIGHTPAREN)
526                 |   ch_p(T_REINTERPRETCAST)
527                     >>  ch_p(T_LESS) >> type_id >> ch_p(T_GREATER)
528                     >>  ch_p(T_LEFTPAREN) >> expression >> ch_p(T_RIGHTPAREN)
529                 |   ch_p(T_CONSTCAST)
530                     >>  ch_p(T_LESS) >> type_id >> ch_p(T_GREATER)
531                     >>  ch_p(T_LEFTPAREN) >> expression >> ch_p(T_RIGHTPAREN)
532                 |   ch_p(T_TYPEID)
533                     >>  ch_p(T_LEFTPAREN) >> expression >> ch_p(T_RIGHTPAREN)
534                 |   ch_p(T_TYPEID)
535                     >> ch_p(T_LEFTPAREN) >> type_id >> ch_p(T_RIGHTPAREN)
536                 ;
537 
538             HANNIBAL_REGISTER_RULE( postfix_expression_helper );
539             postfix_expression_helper
540                 =   pp(T_LEFTBRACKET) >> expression >> pp(T_RIGHTBRACKET)
541                 |   ch_p(T_LEFTPAREN) >> !expression_list >> ch_p(T_RIGHTPAREN)
542                 |   ch_p(T_DOT) >> !ch_p(T_TEMPLATE) >> !ch_p(T_COLON_COLON) >> id_expression
543                 |   ch_p(T_ARROW) >> !ch_p(T_TEMPLATE) >> !ch_p(T_COLON_COLON) >> id_expression
544                 |   ch_p(T_DOT) >> pseudo_destructor_name
545                 |   ch_p(T_ARROW) >> pseudo_destructor_name
546                 |   ch_p(T_PLUSPLUS)
547                 |   ch_p(T_MINUSMINUS)
548                 ;
549 
550             HANNIBAL_REGISTER_RULE( pseudo_destructor_name);
551             pseudo_destructor_name
552                 =  !ch_p(T_COLON_COLON) >> !nested_name_specifier
553                     >>  (
554                             type_name >> ch_p(T_COLON_COLON) >> ch_p(T_COMPL) >> type_name
555                         |   ch_p(T_COMPL) >> type_name
556                         )
557                 ;
558 
559 
560             HANNIBAL_REGISTER_RULE(constant_expression);
561             constant_expression
562                 =   conditional_expression
563                 ;
564 
565             HANNIBAL_REGISTER_RULE(ctor_initializer);
566             ctor_initializer
567                 =   ch_p(T_COLON) >> mem_initializer_list
568                 ;
569 
570             HANNIBAL_REGISTER_RULE(mem_initializer_list);
571             mem_initializer_list
572                 =   mem_initializer % ch_p(T_COMMA)
573                 ;
574 
575             HANNIBAL_REGISTER_RULE(mem_initializer);
576             mem_initializer
577                 =   mem_initializer_id
578                 >>  comment_nest_p(ch_p(T_LEFTPAREN), ch_p(T_RIGHTPAREN))
579                 // TODO: restore after assignment expression has been implemented
580                 //ch_p(T_LEFTPAREN) >> !expression_list >> ch_p(T_RIGHTPAREN)
581                 ;
582 
583             HANNIBAL_REGISTER_RULE(mem_initializer_id);
584             mem_initializer_id
585                 =  !ch_p(T_COLON_COLON) >> !nested_name_specifier >> class_name
586                 |   ch_p(T_IDENTIFIER)
587                 ;
588 
589             //
590             // the eps_p is added to allow skipping of trailing whitespace
591             // (post-skip)
592             //
593             HANNIBAL_REGISTER_RULE(translation_unit);
594             translation_unit
595                 =  !declaration_seq >> end_p;
596                 ;
597 
598             HANNIBAL_REGISTER_RULE(odd_language_extension);
599             odd_language_extension    // read: microsoft extensions
600                 =   extension_type_decorator
601                 >> !comment_nest_p(ch_p(T_LEFTPAREN), ch_p(T_RIGHTPAREN))
602                 ;
603 
604             HANNIBAL_REGISTER_RULE(declaration_seq);
605             declaration_seq
606                 =  +declaration HANNIBAL_TRACE_ACTION( "declaration")
607                 ;
608 
609             HANNIBAL_REGISTER_RULE(declaration);
610             declaration
611                 =   template_declaration
612                 |   explicit_instantiation
613                 |   explicit_specialization
614                 |   linkage_specification
615                 |   namespace_definition
616                 |   block_declaration
617                 |   function_definition
618                 ;
619 
620             HANNIBAL_REGISTER_RULE(block_declaration);
621             block_declaration
622                 =   simple_declaration
623                 |   asm_definition
624                 |   namespace_alias_definition
625                 |   using_declaration
626                 |   using_directive
627                 ;
628 
629             HANNIBAL_REGISTER_RULE(simple_declaration);
630             simple_declaration
631                 =  !decl_specifier_seq >> !init_declarator_list
632                     >>  ch_p(T_SEMICOLON)
633                 ;
634 
635             HANNIBAL_REGISTER_RULE(asm_definition);
636             asm_definition
637                 =   ch_p(T_ASM)
638                     >>  ch_p(T_LEFTPAREN) >> ch_p(T_STRINGLIT) >> ch_p(T_RIGHTPAREN)
639                     >>  ch_p(T_SEMICOLON)
640                 ;
641 
642             HANNIBAL_REGISTER_RULE(init_declarator_list);
643             init_declarator_list
644                 =   init_declarator % ch_p(T_COMMA)
645                 ;
646 
647             HANNIBAL_REGISTER_RULE(init_declarator);
648             init_declarator
649                 =   declarator >> !initializer
650                 ;
651 
652             HANNIBAL_REGISTER_RULE(initializer);
653             initializer
654                 =   ch_p(T_ASSIGN) >> initializer_clause
655                 |   ch_p(T_LEFTPAREN) >> expression_list >> ch_p(T_RIGHTPAREN)
656                 ;
657 
658             HANNIBAL_REGISTER_RULE(initializer_clause);
659             initializer_clause
660                 =   assignment_expression
661                 |   ch_p(T_LEFTBRACE) >> initializer_list
662                     >> !ch_p(T_COMMA) >> ch_p(T_RIGHTBRACE)
663                 |   ch_p(T_LEFTBRACE) >> ch_p(T_RIGHTBRACE)
664                 ;
665 
666             HANNIBAL_REGISTER_RULE(initializer_list);
667             initializer_list
668                 =   initializer_clause % ch_p(T_COMMA)
669                 ;
670 
671             HANNIBAL_REGISTER_RULE(expression_list);
672             expression_list
673                 =   assignment_expression % ch_p(T_COMMA)
674                 ;
675 
676             HANNIBAL_REGISTER_RULE(namespace_alias_definition);
677             namespace_alias_definition
678                 =   ch_p(T_NAMESPACE) >> ch_p(T_IDENTIFIER) >> ch_p(T_ASSIGN)
679                     >>  qualified_namespace_specifier
680                     >>  ch_p(T_SEMICOLON)
681                 ;
682 
683             HANNIBAL_REGISTER_RULE(qualified_namespace_specifier);
684             qualified_namespace_specifier
685                 =  !ch_p(T_COLON_COLON) >> !nested_name_specifier
686                     >>  namespace_name
687                 ;
688 
689             HANNIBAL_REGISTER_RULE(explicit_instantiation);
690             explicit_instantiation
691                 =   template_declaration
692                 ;
693 
694             HANNIBAL_REGISTER_RULE(template_declaration);
695             template_declaration
696                 =  !ch_p(T_EXPORT) >> ch_p(T_TEMPLATE)
697                     >>  ch_p(T_LESS) >> template_parameter_list >> ch_p(T_GREATER)
698                     >>  declaration
699                 ;
700 
701             HANNIBAL_REGISTER_RULE(template_parameter_list);
702             template_parameter_list
703                 =   template_parameter % ch_p(T_COMMA)
704                 ;
705 
706             HANNIBAL_REGISTER_RULE(template_parameter);
707             template_parameter
708                 =   type_parameter
709                 |   parameter_declaration
710                 ;
711 
712             HANNIBAL_REGISTER_RULE(type_parameter);
713             type_parameter
714                 =   ch_p(T_CLASS) >> !ch_p(T_IDENTIFIER)
715                     >> !(ch_p(T_ASSIGN) >> type_id)
716                 |   ch_p(T_TYPENAME) >> !ch_p(T_IDENTIFIER)
717                     >> !(ch_p(T_ASSIGN) >> type_id)
718                 |   ch_p(T_TEMPLATE)
719                     >>  ch_p(T_LESS) >> template_parameter_list >> ch_p(T_GREATER)
720                     >>  ch_p(T_CLASS) >> !ch_p(T_IDENTIFIER)
721                     >> !(ch_p(T_ASSIGN) >> template_name)
722                 ;
723 
724             HANNIBAL_REGISTER_RULE(template_name);
725             template_name
726                 =   ch_p(T_IDENTIFIER)
727                 ;
728 
729             HANNIBAL_REGISTER_RULE(using_declaration);
730             using_declaration     // optimize?
731                 =   ch_p(T_USING) >> !ch_p(T_TYPENAME) >> !ch_p(T_COLON_COLON)
732                     >>  nested_name_specifier >> unqualified_id
733                     >>  ch_p(T_SEMICOLON)
734                 |   ch_p(T_USING) >> ch_p(T_COLON_COLON) >> unqualified_id
735                     >>  ch_p(T_SEMICOLON)
736                 ;
737 
738             HANNIBAL_REGISTER_RULE(using_directive);
739             using_directive
740                 =   ch_p(T_USING) >> ch_p(T_NAMESPACE) >> !ch_p(T_COLON_COLON)
741                     >> !nested_name_specifier >> namespace_name
742                     >>  ch_p(T_SEMICOLON)
743                 ;
744 
745             HANNIBAL_REGISTER_RULE(explicit_specialization);
746             explicit_specialization
747                 =   ch_p(T_TEMPLATE) >> ch_p(T_LESS) >> ch_p(T_GREATER)
748                     >>  declaration
749                 ;
750 
751             HANNIBAL_REGISTER_RULE(linkage_specification);
752             linkage_specification
753                 =   ch_p(T_EXTERN) >> ch_p(T_STRINGLIT)
754                     >>  (   ch_p(T_LEFTBRACE) >> !declaration_seq >> ch_p(T_RIGHTBRACE)
755                         |   declaration
756                         )
757                 ;
758 
759             HANNIBAL_REGISTER_RULE(namespace_definition);
760             namespace_definition
761                 =   named_namespace_definition
762                 |   unnamed_namespace_definition    // TODO: optimize?
763                 ;
764 
765             HANNIBAL_REGISTER_RULE(named_namespace_definition);
766             named_namespace_definition
767                 =   original_namespace_definition
768            //   |   extension_namespace_definition // optimization: extension namespace is syntactically identical
769                 ;
770 
771             HANNIBAL_REGISTER_RULE(original_namespace_definition);
772             original_namespace_definition
773                 =   ch_p(T_NAMESPACE) >> ch_p(T_IDENTIFIER)
774                     >>  ch_p(T_LEFTBRACE) >> namespace_body >> ch_p(T_RIGHTBRACE)
775                 ;
776 
777             HANNIBAL_REGISTER_RULE(extension_namespace_definition);
778             extension_namespace_definition
779                 =   ch_p(T_NAMESPACE) >> original_namespace_name
780                     >>  ch_p(T_LEFTBRACE) >> namespace_body >> ch_p(T_RIGHTBRACE)
781                 ;
782 
783             HANNIBAL_REGISTER_RULE(original_namespace_name);
784             original_namespace_name
785                 =   ch_p(T_IDENTIFIER)
786                 ;
787 
788             HANNIBAL_REGISTER_RULE(unnamed_namespace_definition);
789             unnamed_namespace_definition
790                 =   ch_p(T_NAMESPACE)
791                     >>  ch_p(T_LEFTBRACE) >> namespace_body >> ch_p(T_RIGHTBRACE)
792                 ;
793 
794             HANNIBAL_REGISTER_RULE(namespace_body);
795             namespace_body
796                 =  !declaration_seq
797                 ;
798 
799             HANNIBAL_REGISTER_RULE(function_definition);
800             function_definition
801                 =   function_definition_helper
802                     >> !ctor_initializer >> !function_body  // removed semicolons
803                 |   decl_specifier_seq >> declarator >> function_try_block
804                 |   declarator >> function_try_block
805                 ;
806 
807             HANNIBAL_REGISTER_RULE(function_definition_helper);
808             function_definition_helper
809                 =   decl_specifier_seq >> declarator
810                 |  +no_type_decl_specifier >> declarator
811                 |   declarator
812                 ;
813 
814             HANNIBAL_REGISTER_RULE(function_try_block);
815             function_try_block
816                 =   ch_p(T_TRY)
817                     >> !ctor_initializer >> function_body >> handler_seq
818                 ;
819 
820             HANNIBAL_REGISTER_RULE(handler_seq);
821             handler_seq
822                 =  +handler
823                 ;
824 
825             HANNIBAL_REGISTER_RULE(handler);
826             handler // TODO
827                 =   ch_p(T_CATCH)
828                     >>  comment_nest_p(ch_p(T_LEFTPAREN), ch_p(T_RIGHTPAREN))
829                     >>  compound_statement
830                 ;
831 
832             HANNIBAL_REGISTER_RULE(declarator);
833             declarator
834                 =  *(   ptr_operator
835                     |   odd_language_extension
836                     )
837                     >> direct_declarator
838                 ;
839 
840             HANNIBAL_REGISTER_RULE(direct_declarator);
841             direct_declarator
842                 =   (   declarator_id
843                     |   ch_p(T_LEFTPAREN) >> declarator >> ch_p(T_RIGHTPAREN)
844                     )
845                     >> *parameters_or_array_spec
846                 ;
847 
848             HANNIBAL_REGISTER_RULE(parameters_or_array_spec);
849             parameters_or_array_spec
850                 =   ch_p(T_LEFTPAREN) >> parameter_declaration_clause >> ch_p(T_RIGHTPAREN)
851                     >> !cv_qualifier_seq >> !exception_specification
852                 |   pp(T_LEFTBRACKET) >> !constant_expression >> pp(T_RIGHTBRACKET)
853                 ;
854 
855             HANNIBAL_REGISTER_RULE(exception_specification);
856             exception_specification     // TODO
857                 =   ch_p(T_THROW)
858                     >>  comment_nest_p(ch_p(T_LEFTPAREN), ch_p(T_RIGHTPAREN))
859                 ;
860 
861             HANNIBAL_REGISTER_RULE(abstract_declarator);
862             abstract_declarator
863                 =  +(   ptr_operator
864                     |   odd_language_extension
865                     )
866                     >> !direct_abstract_declarator
867                 |   direct_abstract_declarator
868                 ;
869 
870             HANNIBAL_REGISTER_RULE(direct_abstract_declarator);
871             direct_abstract_declarator
872                 =   ch_p(T_LEFTPAREN) >> abstract_declarator >> ch_p(T_RIGHTPAREN)
873                     >> *direct_abstract_declarator_helper
874                 ;
875 
876             HANNIBAL_REGISTER_RULE(direct_abstract_declarator_helper);
877             direct_abstract_declarator_helper
878                 =   ch_p(T_LEFTPAREN) >> parameter_declaration_clause >> ch_p(T_RIGHTPAREN)
879                     >> !cv_qualifier_seq >> !exception_specification
880                 |   pp(T_LEFTBRACKET) >> !constant_expression >> pp(T_RIGHTBRACKET)
881                 ;
882 
883             HANNIBAL_REGISTER_RULE(parameter_declaration_clause);
884             parameter_declaration_clause
885                 =   parameter_declaration_list >> ch_p(T_COMMA)
886                     >> ch_p(T_ELLIPSIS)
887                 |  !parameter_declaration_list >> !ch_p(T_ELLIPSIS)
888                 ;
889 
890             HANNIBAL_REGISTER_RULE(parameter_declaration_list);
891             parameter_declaration_list
892                 =   parameter_declaration % ch_p(T_COMMA)
893                 ;
894 
895 
896             HANNIBAL_REGISTER_RULE(parameter_declaration);
897             parameter_declaration
898                 =   decl_specifier_seq
899                     >> !(declarator | abstract_declarator)
900                     >> !(ch_p(T_ASSIGN) >> assignment_expression)
901                 ;
902 
903             HANNIBAL_REGISTER_RULE(declarator_id);
904             declarator_id
905                 =  !ch_p(T_COLON_COLON)
906                     >> (   id_expression
907                         |  !nested_name_specifier >> type_name
908                         )
909                 ;
910 
911             HANNIBAL_REGISTER_RULE(id_expression);
912             id_expression
913                 =   qualified_id
914                 |   unqualified_id
915                 ;
916 
917             HANNIBAL_REGISTER_RULE(qualified_id);
918             qualified_id
919                 =   nested_name_specifier >> !ch_p(T_TEMPLATE) >> unqualified_id
920                 ;
921 
922             HANNIBAL_REGISTER_RULE(unqualified_id);
923             unqualified_id
924                 =   operator_function_id
925                 |   conversion_function_id
926                 |   ch_p(T_COMPL) >> class_name
927                 |   template_id
928                 |   ch_p(T_IDENTIFIER)
929                 ;
930 
931             HANNIBAL_REGISTER_RULE(operator_function_id);
932             operator_function_id
933                 =   ch_p(T_OPERATOR) >> operator_sym // this is called 'operator' in the std grammar
934                 ;
935 
936             HANNIBAL_REGISTER_RULE(operator_sym);
937             operator_sym
938                 =   ch_p(T_DELETE) >> !(pp(T_LEFTBRACKET) >> pp(T_RIGHTBRACKET))
939                 |   ch_p(T_NEW) >> !(pp(T_LEFTBRACKET) >> pp(T_RIGHTBRACKET))
940                 |   pp(T_LEFTBRACKET) >> pp(T_RIGHTBRACKET)
941                 |   ch_p(T_LEFTPAREN) >> ch_p(T_RIGHTPAREN)
942                 |   pattern_p(OperatorTokenType, TokenTypeMask)
943                 ;
944 
945             HANNIBAL_REGISTER_RULE(conversion_function_id);
946             conversion_function_id
947                 =   ch_p(T_OPERATOR) >> conversion_type_id
948                 ;
949 
950             HANNIBAL_REGISTER_RULE( conversion_type_id);
951             conversion_type_id
952                 =   type_specifier_seq >> !conversion_declarator
953                 ;
954 
955             HANNIBAL_REGISTER_RULE(type_id);
956             type_id
957                 =   type_specifier_seq >> !abstract_declarator
958                 ;
959 
960 
961             HANNIBAL_REGISTER_RULE(conversion_declarator);
962             conversion_declarator
963                 = ptr_operator >> !conversion_declarator
964                 ;
965 
966             HANNIBAL_REGISTER_RULE(function_body);
967             function_body
968                 = compound_statement
969                 ;
970 
971             HANNIBAL_REGISTER_RULE(compound_statement);
972             compound_statement
973                 =   comment_nest_p(ch_p(T_LEFTBRACE), ch_p(T_RIGHTBRACE))
974                 ;   // TODO later
975 
976 
977             HANNIBAL_REGISTER_RULE(ptr_operator);
978             ptr_operator
979                 =   ch_p(T_STAR) >> !cv_qualifier_seq
980                 |   ch_p(T_AND)
981                 |  !ch_p(T_COLON_COLON) >> nested_name_specifier
982                     >> ch_p(T_STAR) >> !cv_qualifier_seq
983                 ;
984 
985 
986             HANNIBAL_REGISTER_RULE(decl_specifier);
987             decl_specifier
988                 =   no_type_decl_specifier
989                 |   type_specifier
990                 ;
991 
992             HANNIBAL_REGISTER_RULE(no_type_decl_specifier);
993             no_type_decl_specifier
994                 =   storage_class_specifier
995                 |   function_specifier
996                 |   ch_p(T_FRIEND)
997                 |   ch_p(T_TYPEDEF)
998                 |   cv_qualifier
999                 |   odd_language_extension
1000                 ;
1001 
1002             HANNIBAL_REGISTER_RULE(type_specifier_seq);
1003             type_specifier_seq
1004                 =  +type_specifier
1005                 ;
1006 
1007             HANNIBAL_REGISTER_RULE(type_specifier);
1008             type_specifier
1009                 =   enum_specifier
1010                 |   class_specifier
1011                 |   elaborated_type_specifier
1012                 |   simple_type_specifier
1013                 |   cv_qualifier
1014                 ;
1015 
1016             HANNIBAL_REGISTER_RULE(cv_qualifier_seq);
1017             cv_qualifier_seq
1018                 =   cv_qualifier >> !cv_qualifier_seq
1019                 ;
1020 
1021             HANNIBAL_REGISTER_RULE(cv_qualifier);
1022             cv_qualifier
1023                 =   ch_p(T_CONST)
1024                 |   ch_p(T_VOLATILE)
1025                 ;
1026 
1027             HANNIBAL_REGISTER_RULE(enum_specifier);
1028             enum_specifier
1029                 =   enum_keyword >> !ch_p(T_IDENTIFIER)
1030                     >> ch_p(T_LEFTBRACE) >> !enumerator_list >> ch_p(T_RIGHTBRACE)
1031                 ;
1032 
1033             HANNIBAL_REGISTER_RULE(enum_keyword);
1034             enum_keyword
1035                 =   ch_p(T_ENUM)
1036                 ;
1037 
1038             HANNIBAL_REGISTER_RULE(enumerator_list);
1039             enumerator_list
1040                 =   enumerator_definition % ch_p(T_COMMA)
1041                     >> !ch_p(T_COMMA)
1042                     // TODO find out if this last COMMA_T is an MS-"extension"?
1043                     // it seems not to be in the grammar but MSVC 7.0 accepts it.
1044                 ;
1045 
1046             HANNIBAL_REGISTER_RULE(enumerator_definition);
1047             enumerator_definition
1048                 = enumerator >> !(ch_p(T_ASSIGN) >> constant_expression)
1049                 ;
1050 
1051             HANNIBAL_REGISTER_RULE(enumerator);
1052             enumerator
1053                 =   ch_p(T_IDENTIFIER)
1054                 ;
1055 
1056 
1057             HANNIBAL_REGISTER_RULE(simple_type_specifier);
1058             simple_type_specifier
1059                 =   !ch_p(T_COLON_COLON) >> !nested_name_specifier
1060                     >>  ch_p(T_TEMPLATE) >> template_id
1061                 |   +simple_type_name
1062                 |  !ch_p(T_COLON_COLON) >> !nested_name_specifier >> type_name
1063                 ;
1064 
1065             HANNIBAL_REGISTER_RULE(class_head);
1066             class_head // DH changed the order because otherwise it would always parse the (!IDENTIFIER) part.
1067                 =  !access_specifier >> *odd_language_extension
1068                     >>  class_key >> *odd_language_extension
1069                     >>  (
1070                             !nested_name_specifier >> template_id
1071                         |   nested_name_specifier >> ch_p(T_IDENTIFIER)
1072                         |   !ch_p(T_IDENTIFIER)
1073                         )
1074                     >> !base_clause
1075                 ;
1076 
1077             HANNIBAL_REGISTER_RULE(type_name);
1078             type_name
1079                 =   class_name
1080                 |   enum_name
1081                 |   typedef_name
1082                 ;
1083 
1084             HANNIBAL_REGISTER_RULE(elaborated_type_specifier);
1085             elaborated_type_specifier
1086                 =   class_key >> *odd_language_extension
1087                     >>  !ch_p(T_COLON_COLON)
1088                     >>  !nested_name_specifier
1089                     >>  (
1090                             !ch_p(T_TEMPLATE) >> template_id
1091                         |   ch_p(T_IDENTIFIER)
1092                         )
1093                 |   ch_p(T_ENUM) >> !ch_p(T_COLON_COLON)
1094                     >> !nested_name_specifier
1095                     >>  ch_p(T_IDENTIFIER)
1096                 |   ch_p(T_TYPENAME)
1097                     >> !ch_p(T_COLON_COLON)
1098                     >>  nested_name_specifier
1099                     >>  (
1100                             !ch_p(T_TEMPLATE) >> template_id
1101                         |   ch_p(T_IDENTIFIER)
1102                         )
1103                 ;
1104 
1105             HANNIBAL_REGISTER_RULE(template_argument_list);
1106             template_argument_list
1107                 =   template_argument % ch_p(T_COMMA)
1108                 ;
1109 
1110             HANNIBAL_REGISTER_RULE(template_argument);
1111             template_argument
1112                 =   longest_d
1113                     [
1114                         type_id
1115                     |   ta_assignment_expression
1116                     |   template_name
1117                     ]
1118                 ;
1119 
1120             HANNIBAL_REGISTER_RULE(class_key);
1121             class_key
1122                 =   class_keywords
1123                 ;
1124 
1125             HANNIBAL_REGISTER_RULE(class_keywords);
1126             class_keywords
1127                 =   ch_p(T_CLASS)
1128                 |   ch_p(T_STRUCT)
1129                 |   ch_p(T_UNION)
1130                 ;
1131 
1132             HANNIBAL_REGISTER_RULE(nested_name_specifier);
1133             nested_name_specifier
1134                 =   class_or_namespace_name >> ch_p(T_COLON_COLON)
1135                     >>  ch_p(T_TEMPLATE) >> nested_name_specifier
1136                 |   class_or_namespace_name >> ch_p(T_COLON_COLON)
1137                     >> !nested_name_specifier
1138                 ;
1139 
1140             HANNIBAL_REGISTER_RULE(class_or_namespace_name);
1141             class_or_namespace_name
1142                 =   class_name
1143                 |   namespace_name
1144                 ;
1145 
1146             HANNIBAL_REGISTER_RULE(class_name);
1147             class_name
1148                 =   template_id
1149                 |   ch_p(T_IDENTIFIER)
1150                 ;
1151 
1152             HANNIBAL_REGISTER_RULE(enum_name);
1153             enum_name
1154                 =   ch_p(T_IDENTIFIER)
1155                 ;
1156 
1157             HANNIBAL_REGISTER_RULE(typedef_name);
1158             typedef_name
1159                 =   ch_p(T_IDENTIFIER)
1160                 ;
1161 
1162             HANNIBAL_REGISTER_RULE(namespace_name);
1163             namespace_name    // TODO
1164                 =   ch_p(T_IDENTIFIER)
1165                 ;
1166 
1167             HANNIBAL_REGISTER_RULE(template_id);
1168             template_id
1169                 =   template_name
1170                     >> ch_p(T_LESS) >> template_argument_list >> ch_p(T_GREATER)
1171                 ;
1172 
1173             //
1174             //  This is kind of a HACK. We want to prevent the decl_specifier_seq
1175             //  from eating the whole declaration, including the ch_p(T_IDENTIFIER).
1176             //  Therefore in the sequence, we only allow one 'unknown' word
1177             //  (the type_specifier), the rest of the decl_specifier sequence
1178             //  must consist of known keywords or constructs (the
1179             //  no_type_decl_specifier).
1180             //  This means that a declaration like:
1181             //     MYDLL_EXPORT int f();
1182             //  will not be accepted unless the MYDLL_EXPORT is properly
1183             //  expanded by the preprocessor first.
1184             //
1185             //  This should not cause any problems normally, it just means that
1186             //  this rule is not very robust in the case where not all symbols
1187             //  are known.
1188             //
1189             HANNIBAL_REGISTER_RULE(decl_specifier_seq);
1190             decl_specifier_seq
1191                 =  *no_type_decl_specifier >> type_specifier >> *no_type_decl_specifier
1192                 ;
1193 
1194             //  The following rule is more according to the standard grammar
1195             //  decl_specifier_seq // adapted
1196             //     =   decl_specifier >> decl_specifier_seq
1197             //    |   (decl_specifier - (declarator_id >> parameters_or_array_spec ))
1198             //     ;
1199 
1200             HANNIBAL_REGISTER_RULE( storage_class_specifier);
1201             storage_class_specifier
1202                 =   ch_p(T_AUTO)
1203                 |   ch_p(T_REGISTER)
1204                 |   ch_p(T_STATIC)
1205                 |   ch_p(T_EXTERN)
1206                 |   ch_p(T_MUTABLE)
1207                 ;
1208 
1209             HANNIBAL_REGISTER_RULE( function_specifier);
1210             function_specifier
1211                 =   ch_p(T_INLINE)
1212                 |   ch_p(T_VIRTUAL)
1213                 |   ch_p(T_EXPLICIT)
1214                 ;
1215 
1216             HANNIBAL_REGISTER_RULE(class_specifier);
1217             class_specifier
1218                 =   class_head
1219                     >> ch_p(T_LEFTBRACE) >> !member_specification >> ch_p(T_RIGHTBRACE)
1220                 ;
1221 
1222             HANNIBAL_REGISTER_RULE(member_specification);
1223             member_specification
1224                 =  +(   access_specifier >> ch_p(T_COLON)
1225                     |   member_declaration HANNIBAL_TRACE_ACTION("member declaration")
1226                     )
1227                 ;
1228 
1229       //    member_specification
1230       //     = access_specifier >> COLON_T >> !member_specification
1231       //     | member_declaration >> !member_specification
1232       //     ;
1233 
1234             HANNIBAL_REGISTER_RULE(member_declaration);
1235             member_declaration
1236                 =   using_declaration
1237                 |   template_declaration
1238                 |  !decl_specifier_seq >> !member_declarator_list
1239                     >> ch_p(T_SEMICOLON)
1240                 |   function_definition >>
1241                    !ch_p(T_SEMICOLON)
1242                 |   qualified_id
1243                     >> ch_p(T_SEMICOLON)
1244                 ;
1245 
1246             HANNIBAL_REGISTER_RULE(member_declarator_list);
1247             member_declarator_list
1248                 =   member_declarator % ch_p(T_COMMA)
1249                 ;
1250 
1251             HANNIBAL_REGISTER_RULE(member_declarator);
1252             member_declarator
1253                 =  !ch_p(T_IDENTIFIER) >> ch_p(T_COLON) >> constant_expression
1254                 |   declarator >> !(pure_specifier | constant_initializer)
1255                 ;
1256 
1257             HANNIBAL_REGISTER_RULE(pure_specifier);
1258             pure_specifier
1259                 =   ch_p(T_ASSIGN) >> ch_p(T_INTLIT)
1260                 ;
1261 
1262             HANNIBAL_REGISTER_RULE(constant_initializer);
1263             constant_initializer
1264                 =   ch_p(T_ASSIGN) >> constant_expression
1265                 ;
1266 
1267             HANNIBAL_REGISTER_RULE(access_specifier);
1268             access_specifier
1269                 =   ch_p(T_PUBLIC)
1270                 |   ch_p(T_PROTECTED)
1271                 |   ch_p(T_PRIVATE)
1272                 ;
1273 
1274             HANNIBAL_REGISTER_RULE(base_clause);
1275             base_clause
1276                 =   ch_p(T_COLON) >> base_specifier_list
1277                 ;
1278 
1279             HANNIBAL_REGISTER_RULE(base_specifier_list);
1280             base_specifier_list
1281                 =   base_specifier % ch_p(T_COMMA)
1282                 ;
1283 
1284             HANNIBAL_REGISTER_RULE(base_specifier);
1285             base_specifier
1286                 =   ch_p(T_VIRTUAL) >> !access_specifier >> !ch_p(T_COLON_COLON)
1287                     >> !nested_name_specifier >> class_name
1288                 |   access_specifier >> !ch_p(T_VIRTUAL) >> !ch_p(T_COLON_COLON)
1289                     >> !nested_name_specifier >> class_name
1290                 |  !ch_p(T_COLON_COLON) >> !nested_name_specifier >> class_name
1291                 ;
1292 
1293             HANNIBAL_REGISTER_RULE(extension_type_decorator);
1294             extension_type_decorator
1295                 =   ch_p(T_MSEXT_CDECL)
1296                 |   ch_p(T_MSEXT_DECLSPEC)
1297                 |   ch_p(T_MSEXT_BASED)
1298                 |   ch_p(T_MSEXT_FASTCALL)
1299                 |   ch_p(T_MSEXT_INLINE)
1300                 ;
1301 
1302             HANNIBAL_REGISTER_RULE(simple_type_name);
1303             simple_type_name
1304                 =   ch_p(T_CHAR)
1305                 |   ch_p(T_WCHART)
1306                 |   ch_p(T_BOOL)
1307                 |   ch_p(T_SHORT)
1308                 |   ch_p(T_INT)
1309                 |   ch_p(T_LONG)
1310                 |   ch_p(T_UNSIGNED)
1311                 |   ch_p(T_SIGNED)
1312                 |   ch_p(T_FLOAT)
1313                 |   ch_p(T_DOUBLE)
1314                 |   ch_p(T_VOID)
1315                 |   ch_p(T_MSEXT_INT64)
1316                 |   ch_p(T_MSEXT_INT8)
1317                 |   ch_p(T_MSEXT_INT16)
1318                 |   ch_p(T_MSEXT_INT32)
1319                 ;
1320         }
1321 
starttranslation_unit_grammar::definition1322         rule_type const& start() const { return translation_unit; }
1323 
1324         //  Helper function wrapping pattern_p
1325         static inline boost::wave::util::pattern_and< boost::wave::token_id>
pptranslation_unit_grammar::definition1326         pp (boost::wave::token_id id)
1327         {
1328             using namespace boost::wave;
1329             return util::pattern_p(id, MainTokenMask);
1330         }
1331     };
1332 
1333 #if HANNIBAL_DUMP_PARSE_TREE != 0
1334 private:
1335     template<typename Rule>
declare_ruletranslation_unit_grammar1336     void declare_rule(Rule const& rule, std::string const& rule_name) const
1337     {
1338         if (rule_map_ptr)
1339             (*rule_map_ptr)[rule.id()] = rule_name;
1340     }
1341     rule_map_type *rule_map_ptr;
1342 #endif
1343 };
1344 
1345 #undef HANNIBAL_REGISTER_RULE
1346 #undef HANNIBAL_TRACE_TRANSLATION_UNIT_GRAMMAR
1347 
1348 #endif // BOOST_HANNIBAL_TRANSLATION_UNIT_GRAMMAR_H_INCLUDED
1349