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