2671c143ad
[SVN r50637]
1346 lines
49 KiB
C++
1346 lines
49 KiB
C++
// Hannibal: partial C++ grammar to parse C++ type information
|
|
// Copyright (c) 2005-2006 Danny Havenith
|
|
//
|
|
// Boost.Wave: A Standard compliant C++ preprocessor
|
|
// Copyright (c) 2001-2009 Hartmut Kaiser
|
|
//
|
|
// http://www.boost.org/
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
#if !defined(HANNIBAL_TRANSLATION_UNIT_GRAMMAR_H_INCLUDED)
|
|
#define HANNIBAL_TRANSLATION_UNIT_GRAMMAR_H_INCLUDED
|
|
|
|
#include <map>
|
|
|
|
#include <boost/assert.hpp>
|
|
#include <boost/spirit/include/classic_core.hpp>
|
|
#include <boost/spirit/include/classic_confix.hpp>
|
|
|
|
#include <boost/wave/wave_config.hpp>
|
|
#include <boost/wave/token_ids.hpp>
|
|
#include <boost/wave/util/pattern_parser.hpp>
|
|
|
|
//
|
|
// If so required, trace every declaration and member-declaration.
|
|
// This can be a much faster alternative to BOOST_SPIRIT_DEBUG-type of
|
|
// debugging.
|
|
//
|
|
#ifdef HANNIBAL_TRACE_DECLARATIONS
|
|
struct trace_actor
|
|
{
|
|
trace_actor(
|
|
const char rule_type[],
|
|
std::ostream &strm
|
|
)
|
|
: strm_( strm), rule_type_( rule_type)
|
|
{
|
|
// nop
|
|
}
|
|
|
|
template<typename PositionIterator>
|
|
void operator()(PositionIterator begin, PositionIterator end) const
|
|
{
|
|
typedef const boost::wave::cpplexer::lex_token<>::position_type
|
|
position_type;
|
|
//typedef pos_iterator_type::token_type::position_type position_type;
|
|
|
|
position_type &begin_pos(begin->get_position());
|
|
|
|
strm_ << "Parsed " << rule_type_ << std::endl;
|
|
strm_ << " from: " << begin_pos.get_file()
|
|
<< "(" << begin_pos.get_line() << ")"
|
|
<< std::endl;
|
|
};
|
|
|
|
private:
|
|
std::ostream &strm_;
|
|
char const* const rule_type_;
|
|
};
|
|
|
|
#define HANNIBAL_TRACE_ACTION( type) [trace_actor( (type), std::cout)]
|
|
#else
|
|
#define HANNIBAL_TRACE_ACTION( type)
|
|
#endif
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#define HANNIBAL_TRACE_TRANSLATION_UNIT_GRAMMAR \
|
|
bool(BOOST_SPIRIT_DEBUG_FLAGS_CPP & BOOST_SPIRIT_DEBUG_FLAGS_CPP_EXPR_GRAMMAR) \
|
|
/**/
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Helper macro to register rules for debugging
|
|
#if HANNIBAL_DUMP_PARSE_TREE != 0
|
|
#define HANNIBAL_REGISTER_RULE(r) \
|
|
BOOST_SPIRIT_DEBUG_NODE(r); \
|
|
self.declare_rule(r, #r) \
|
|
/**/
|
|
#else
|
|
#define HANNIBAL_REGISTER_RULE(r) \
|
|
BOOST_SPIRIT_DEBUG_NODE(r) \
|
|
/**/
|
|
#endif
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
struct dump_actor {
|
|
template<typename ForwardIterator>
|
|
void operator()(ForwardIterator begin, ForwardIterator end)
|
|
{
|
|
std::cerr << "*** COULD NOT PARSE THE FOLLOWING ***" << std::endl;
|
|
while (begin != end)
|
|
{
|
|
std::cerr << begin->get_value();
|
|
++begin;
|
|
}
|
|
}
|
|
} dump_a;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
struct translation_unit_grammar
|
|
: public boost::spirit::classic::grammar<translation_unit_grammar>
|
|
{
|
|
#if HANNIBAL_DUMP_PARSE_TREE != 0
|
|
//
|
|
// allow an external map with rule-id -> rule-name mappings.
|
|
// this map is external so it can be altered by the definition constructor,
|
|
// which receives a const grammar object.
|
|
//
|
|
// Please Note: the lifetime of the rule map should at least extend beyond the
|
|
// call of the definition constructor...
|
|
//
|
|
typedef std::map<boost::spirit::classic::parser_id, std::string>
|
|
rule_map_type;
|
|
|
|
translation_unit_grammar(rule_map_type *rule_map_ptr_ = 0)
|
|
: rule_map_ptr(rule_map_ptr_)
|
|
#else
|
|
translation_unit_grammar()
|
|
#endif
|
|
{
|
|
BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(*this,
|
|
"translation_unit_grammar", HANNIBAL_TRACE_TRANSLATION_UNIT_GRAMMAR);
|
|
}
|
|
|
|
template <typename ScannerT>
|
|
struct definition
|
|
{
|
|
// declare non-terminals
|
|
typedef boost::spirit::classic::rule<ScannerT> rule_type;
|
|
|
|
rule_type constant_expression;
|
|
rule_type logical_or_exp, logical_and_exp;
|
|
rule_type inclusive_or_exp, exclusive_or_exp, and_exp;
|
|
rule_type cmp_equality, cmp_relational;
|
|
rule_type shift_exp;
|
|
rule_type add_exp, multiply_exp;
|
|
rule_type unary_exp, primary_exp, constant;
|
|
|
|
boost::spirit::classic::subrule<0> const_exp_subrule;
|
|
boost::spirit::classic::subrule<1> shift_exp_clos;
|
|
|
|
rule_type simple_type_name, class_keywords;
|
|
rule_type storage_class_specifier, cv_qualifier, function_specifier;
|
|
rule_type access_specifier;
|
|
rule_type extension_type_decorator;
|
|
rule_type operator_sym;
|
|
rule_type class_key;
|
|
rule_type enumerator;
|
|
rule_type enumerator_list;
|
|
rule_type enumerator_definition;
|
|
rule_type member_declarator;
|
|
rule_type member_declarator_list;
|
|
rule_type member_declaration;
|
|
rule_type constant_initializer;
|
|
rule_type pure_specifier;
|
|
rule_type namespace_body;
|
|
rule_type type_id;
|
|
rule_type unnamed_namespace_definition;
|
|
rule_type extension_namespace_definition;
|
|
rule_type original_namespace_definition;
|
|
rule_type named_namespace_definition;
|
|
rule_type namespace_definition;
|
|
rule_type linkage_specification;
|
|
rule_type explicit_specialization;
|
|
rule_type using_directive;
|
|
rule_type using_declaration;
|
|
rule_type type_parameter;
|
|
rule_type template_parameter;
|
|
rule_type template_parameter_list;
|
|
rule_type template_declaration;
|
|
rule_type explicit_instantiation;
|
|
rule_type qualified_namespace_specifier;
|
|
rule_type namespace_alias_definition;
|
|
rule_type expression_list;
|
|
rule_type initializer_list;
|
|
rule_type initializer_clause;
|
|
rule_type initializer;
|
|
rule_type init_declarator;
|
|
rule_type init_declarator_list;
|
|
rule_type asm_definition;
|
|
rule_type simple_declaration;
|
|
rule_type block_declaration;
|
|
rule_type declaration;
|
|
rule_type declaration_seq;
|
|
rule_type translation_unit;
|
|
|
|
rule_type function_definition, function_definition_helper, declarator;
|
|
rule_type direct_declarator, parameters_or_array_spec;
|
|
rule_type abstract_declarator, direct_abstract_declarator;
|
|
rule_type direct_abstract_declarator_helper;
|
|
rule_type parameter_declaration_clause, parameter_declaration_list;
|
|
rule_type parameter_declaration, assignment_expression, decimal_literal;
|
|
rule_type octal_literal, hexadecimal_literal;
|
|
rule_type declarator_id, id_expression, qualified_id, unqualified_id;
|
|
rule_type operator_function_id, conversion_function_id, conversion_type_id;
|
|
rule_type conversion_declarator, function_body;
|
|
rule_type compound_statement, ctor_initializer, ptr_operator;
|
|
rule_type decl_specifier, type_specifier;
|
|
rule_type type_specifier_seq, cv_qualifier_seq, enum_specifier;
|
|
rule_type enum_keyword, simple_type_specifier;
|
|
rule_type class_specifier, member_specification, class_head;
|
|
rule_type type_name, elaborated_type_specifier, template_argument_list;
|
|
rule_type template_argument, nested_name_specifier;
|
|
rule_type class_or_namespace_name, class_name, enum_name, typedef_name;
|
|
rule_type namespace_name, template_id;
|
|
rule_type decl_specifier_seq, no_type_decl_specifier;
|
|
rule_type function_try_block, handler_seq, handler;
|
|
rule_type exception_specification, template_name;
|
|
rule_type original_namespace_name, base_specifier;
|
|
rule_type base_specifier_list, base_clause;
|
|
rule_type odd_language_extension, mem_initializer_id;
|
|
rule_type mem_initializer, mem_initializer_list;
|
|
|
|
|
|
rule_type ta_expression_operator;
|
|
rule_type ta_logical_or_expression;
|
|
rule_type ta_expression;
|
|
rule_type ta_conditional_expression;
|
|
rule_type ta_throw_expression;
|
|
rule_type ta_assignment_expression;
|
|
rule_type postfix_expression_helper;
|
|
rule_type simple_postfix_expression;
|
|
rule_type pseudo_destructor_name;
|
|
rule_type direct_new_declarator;
|
|
rule_type new_declarator;
|
|
rule_type new_initializer;
|
|
rule_type new_type_id;
|
|
rule_type new_placement;
|
|
rule_type delete_expression;
|
|
rule_type new_expression;
|
|
rule_type unary_operator;
|
|
rule_type postfix_expression;
|
|
rule_type unary_expression;
|
|
rule_type expression_operator;
|
|
rule_type cast_expression;
|
|
rule_type throw_expression;
|
|
rule_type assignment_operator;
|
|
rule_type logical_or_expression;
|
|
rule_type conditional_expression;
|
|
rule_type boolean_literal;
|
|
rule_type string_literal;
|
|
rule_type floating_literal;
|
|
rule_type character_literal;
|
|
rule_type integer_literal;
|
|
rule_type expression;
|
|
rule_type literal;
|
|
rule_type primary_expression;
|
|
|
|
//
|
|
// grammar definition.
|
|
|
|
definition(translation_unit_grammar const& self)
|
|
{
|
|
using namespace boost::spirit::classic;
|
|
using namespace boost::wave;
|
|
using boost::wave::util::pattern_p;
|
|
|
|
//
|
|
// First, a long list of expression rules.
|
|
//
|
|
HANNIBAL_REGISTER_RULE( primary_expression);
|
|
primary_expression
|
|
= literal
|
|
| ch_p(T_THIS)
|
|
| ch_p(T_COLON_COLON) >> ch_p(T_IDENTIFIER)
|
|
| ch_p(T_COLON_COLON) >> operator_function_id
|
|
| ch_p(T_COLON_COLON) >> qualified_id
|
|
| ch_p(T_LEFTPAREN) >> expression >> ch_p(T_RIGHTPAREN)
|
|
| id_expression
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( literal);
|
|
literal
|
|
= integer_literal
|
|
| character_literal
|
|
| floating_literal
|
|
| string_literal
|
|
| boolean_literal
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( integer_literal);
|
|
integer_literal
|
|
= pattern_p( IntegerLiteralTokenType, TokenTypeMask)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( character_literal);
|
|
character_literal
|
|
= pattern_p( CharacterLiteralTokenType, TokenTypeMask)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( floating_literal);
|
|
floating_literal
|
|
= pattern_p( FloatingLiteralTokenType, TokenTypeMask)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( string_literal);
|
|
string_literal
|
|
= pattern_p( StringLiteralTokenType, TokenTypeMask)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( boolean_literal);
|
|
boolean_literal
|
|
= pattern_p( BoolLiteralTokenType, TokenTypeMask)
|
|
;
|
|
|
|
//
|
|
// TODO: separate assignment expression into a grammar of it's own
|
|
//
|
|
HANNIBAL_REGISTER_RULE( assignment_expression);
|
|
assignment_expression
|
|
= conditional_expression
|
|
| logical_or_expression >> assignment_operator >> assignment_expression
|
|
| throw_expression
|
|
;
|
|
|
|
//
|
|
// Have a separate assignment expression for template arguments.
|
|
// This is needed, because without it, an expression of the form
|
|
// template < a, b, c > x;
|
|
// would not parse, since the 'c > x' part would be taken by the
|
|
// assignment expression.
|
|
//
|
|
// Note that this ta_xxxxx duplication cascades all the way down to
|
|
// logical_or_expression.
|
|
// Both the previous example and a declaration of the form
|
|
// template < a, b, (c > d) > x;
|
|
// should parse fine now.
|
|
//
|
|
//
|
|
HANNIBAL_REGISTER_RULE( ta_assignment_expression);
|
|
ta_assignment_expression
|
|
= ta_conditional_expression
|
|
| ta_logical_or_expression >> assignment_operator >> ta_assignment_expression
|
|
| ta_throw_expression
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( throw_expression);
|
|
throw_expression
|
|
= ch_p(T_THROW) >> !assignment_expression
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( ta_throw_expression);
|
|
ta_throw_expression
|
|
= ch_p(T_THROW) >> !ta_assignment_expression
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( conditional_expression);
|
|
conditional_expression
|
|
= logical_or_expression
|
|
>> !(
|
|
ch_p(T_QUESTION_MARK)
|
|
>> expression
|
|
>> ch_p(T_COLON)
|
|
>> assignment_expression
|
|
)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( ta_conditional_expression);
|
|
ta_conditional_expression
|
|
= ta_logical_or_expression
|
|
>> !(
|
|
ch_p(T_QUESTION_MARK)
|
|
>> ta_expression
|
|
>> ch_p(T_COLON)
|
|
>> ta_assignment_expression
|
|
)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( expression);
|
|
expression
|
|
= assignment_expression % ch_p(T_COMMA);
|
|
|
|
HANNIBAL_REGISTER_RULE( ta_expression);
|
|
ta_expression
|
|
= ta_assignment_expression % ch_p(T_COMMA);
|
|
|
|
HANNIBAL_REGISTER_RULE( assignment_operator);
|
|
assignment_operator
|
|
= pp(T_ASSIGN)
|
|
| pp(T_ANDASSIGN)
|
|
| pp(T_ORASSIGN)
|
|
| pp(T_XORASSIGN)
|
|
| pp(T_DIVIDEASSIGN)
|
|
| pp(T_MINUSASSIGN)
|
|
| pp(T_PERCENTASSIGN)
|
|
| pp(T_PLUSASSIGN)
|
|
| pp(T_SHIFTLEFTASSIGN)
|
|
| pp(T_SHIFTRIGHTASSIGN)
|
|
| pp(T_STARASSIGN)
|
|
;
|
|
|
|
|
|
// we skip quite a few rules here, since we're not interested in operator precedence
|
|
// just now.
|
|
HANNIBAL_REGISTER_RULE( logical_or_expression);
|
|
logical_or_expression
|
|
= cast_expression % expression_operator
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( ta_logical_or_expression);
|
|
ta_logical_or_expression
|
|
= cast_expression % ta_expression_operator
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( expression_operator );
|
|
expression_operator
|
|
= ta_expression_operator | pp(T_GREATER)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( ta_expression_operator );
|
|
ta_expression_operator
|
|
= pp(T_OROR)
|
|
| pp(T_ANDAND)
|
|
| pp(T_OR)
|
|
| pp(T_XOR)
|
|
| pp(T_AND)
|
|
| pp(T_NOTEQUAL)
|
|
| pp(T_EQUAL)
|
|
| pp(T_GREATEREQUAL)
|
|
| pp(T_LESSEQUAL)
|
|
| pp(T_LESS)
|
|
| pp(T_SHIFTLEFT)
|
|
| pp(T_SHIFTRIGHT)
|
|
| pp(T_PLUS)
|
|
| pp(T_MINUS)
|
|
| pp(T_PERCENT)
|
|
| pp(T_DIVIDE)
|
|
| pp(T_STAR)
|
|
| pp(T_ARROWSTAR)
|
|
| pp(T_DOTSTAR)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( cast_expression);
|
|
cast_expression
|
|
= ch_p(T_LEFTPAREN) >> type_id >> ch_p(T_RIGHTPAREN)
|
|
>> cast_expression
|
|
| unary_expression
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( unary_expression);
|
|
unary_expression
|
|
= postfix_expression
|
|
| ch_p(T_PLUSPLUS) >> cast_expression
|
|
| ch_p(T_MINUSMINUS) >> cast_expression
|
|
| unary_operator >> cast_expression
|
|
| ch_p(T_SIZEOF) >> unary_expression
|
|
| ch_p(T_SIZEOF)
|
|
>> ch_p(T_LEFTPAREN) >> type_id >> ch_p(T_RIGHTPAREN)
|
|
| new_expression
|
|
| delete_expression
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( unary_operator);
|
|
unary_operator
|
|
= ch_p(T_STAR)
|
|
| pp(T_AND)
|
|
| pp(T_PLUS)
|
|
| ch_p(T_MINUS)
|
|
| ch_p(T_NOT)
|
|
| pp(T_COMPL)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( new_expression);
|
|
new_expression
|
|
= !ch_p(T_COLON_COLON) >> ch_p(T_NEW) >> !new_placement
|
|
>> (
|
|
new_type_id >> !new_initializer
|
|
| ch_p(T_LEFTPAREN) >> type_id >> ch_p(T_RIGHTPAREN) >> !new_initializer
|
|
)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( new_placement);
|
|
new_placement
|
|
= ch_p(T_LEFTPAREN) >> expression_list >> ch_p(T_RIGHTPAREN)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( new_type_id);
|
|
new_type_id
|
|
= type_specifier_seq >> !new_declarator
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( new_declarator);
|
|
new_declarator
|
|
= ptr_operator >> !new_declarator
|
|
| direct_new_declarator
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( direct_new_declarator);
|
|
direct_new_declarator
|
|
= *( pp(T_LEFTBRACKET) >> expression >> pp(T_RIGHTBRACKET) )
|
|
>> pp(T_LEFTBRACKET) >> constant_expression >> pp(T_RIGHTBRACKET)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( new_initializer);
|
|
new_initializer
|
|
= ch_p(T_LEFTPAREN) >> !expression_list >> ch_p(T_RIGHTPAREN)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( delete_expression);
|
|
delete_expression
|
|
= !ch_p(T_COLON_COLON) >> ch_p(T_DELETE) >> cast_expression
|
|
| !ch_p(T_COLON_COLON) >> ch_p(T_DELETE)
|
|
>> pp(T_LEFTBRACKET) >> pp(T_RIGHTBRACKET)
|
|
>> cast_expression
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( postfix_expression);
|
|
postfix_expression
|
|
= simple_postfix_expression >> *postfix_expression_helper
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( simple_postfix_expression);
|
|
simple_postfix_expression
|
|
= primary_expression
|
|
| simple_type_specifier
|
|
>> ch_p(T_LEFTPAREN) >> !expression_list >> ch_p(T_RIGHTPAREN)
|
|
| ch_p(T_DYNAMICCAST)
|
|
>> ch_p(T_LESS) >> type_id >> ch_p(T_GREATER)
|
|
>> ch_p(T_LEFTPAREN) >> expression >> ch_p(T_RIGHTPAREN)
|
|
| ch_p(T_STATICCAST)
|
|
>> ch_p(T_LESS) >> type_id >> ch_p(T_GREATER)
|
|
>> ch_p(T_LEFTPAREN) >> expression >> ch_p(T_RIGHTPAREN)
|
|
| ch_p(T_REINTERPRETCAST)
|
|
>> ch_p(T_LESS) >> type_id >> ch_p(T_GREATER)
|
|
>> ch_p(T_LEFTPAREN) >> expression >> ch_p(T_RIGHTPAREN)
|
|
| ch_p(T_CONSTCAST)
|
|
>> ch_p(T_LESS) >> type_id >> ch_p(T_GREATER)
|
|
>> ch_p(T_LEFTPAREN) >> expression >> ch_p(T_RIGHTPAREN)
|
|
| ch_p(T_TYPEID)
|
|
>> ch_p(T_LEFTPAREN) >> expression >> ch_p(T_RIGHTPAREN)
|
|
| ch_p(T_TYPEID)
|
|
>> ch_p(T_LEFTPAREN) >> type_id >> ch_p(T_RIGHTPAREN)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( postfix_expression_helper );
|
|
postfix_expression_helper
|
|
= pp(T_LEFTBRACKET) >> expression >> pp(T_RIGHTBRACKET)
|
|
| ch_p(T_LEFTPAREN) >> !expression_list >> ch_p(T_RIGHTPAREN)
|
|
| ch_p(T_DOT) >> !ch_p(T_TEMPLATE) >> !ch_p(T_COLON_COLON) >> id_expression
|
|
| ch_p(T_ARROW) >> !ch_p(T_TEMPLATE) >> !ch_p(T_COLON_COLON) >> id_expression
|
|
| ch_p(T_DOT) >> pseudo_destructor_name
|
|
| ch_p(T_ARROW) >> pseudo_destructor_name
|
|
| ch_p(T_PLUSPLUS)
|
|
| ch_p(T_MINUSMINUS)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( pseudo_destructor_name);
|
|
pseudo_destructor_name
|
|
= !ch_p(T_COLON_COLON) >> !nested_name_specifier
|
|
>> (
|
|
type_name >> ch_p(T_COLON_COLON) >> ch_p(T_COMPL) >> type_name
|
|
| ch_p(T_COMPL) >> type_name
|
|
)
|
|
;
|
|
|
|
|
|
HANNIBAL_REGISTER_RULE(constant_expression);
|
|
constant_expression
|
|
= conditional_expression
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(ctor_initializer);
|
|
ctor_initializer
|
|
= ch_p(T_COLON) >> mem_initializer_list
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(mem_initializer_list);
|
|
mem_initializer_list
|
|
= mem_initializer % ch_p(T_COMMA)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(mem_initializer);
|
|
mem_initializer
|
|
= mem_initializer_id
|
|
>> comment_nest_p(ch_p(T_LEFTPAREN), ch_p(T_RIGHTPAREN))
|
|
// TODO: restore after assignment expression has been implemented
|
|
//ch_p(T_LEFTPAREN) >> !expression_list >> ch_p(T_RIGHTPAREN)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(mem_initializer_id);
|
|
mem_initializer_id
|
|
= !ch_p(T_COLON_COLON) >> !nested_name_specifier >> class_name
|
|
| ch_p(T_IDENTIFIER)
|
|
;
|
|
|
|
//
|
|
// the eps_p is added to allow skipping of trailing whitespace
|
|
// (post-skip)
|
|
//
|
|
HANNIBAL_REGISTER_RULE(translation_unit);
|
|
translation_unit
|
|
= !declaration_seq >> end_p;
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(odd_language_extension);
|
|
odd_language_extension // read: microsoft extensions
|
|
= extension_type_decorator
|
|
>> !comment_nest_p(ch_p(T_LEFTPAREN), ch_p(T_RIGHTPAREN))
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(declaration_seq);
|
|
declaration_seq
|
|
= +declaration HANNIBAL_TRACE_ACTION( "declaration")
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(declaration);
|
|
declaration
|
|
= template_declaration
|
|
| explicit_instantiation
|
|
| explicit_specialization
|
|
| linkage_specification
|
|
| namespace_definition
|
|
| block_declaration
|
|
| function_definition
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(block_declaration);
|
|
block_declaration
|
|
= simple_declaration
|
|
| asm_definition
|
|
| namespace_alias_definition
|
|
| using_declaration
|
|
| using_directive
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(simple_declaration);
|
|
simple_declaration
|
|
= !decl_specifier_seq >> !init_declarator_list
|
|
>> ch_p(T_SEMICOLON)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(asm_definition);
|
|
asm_definition
|
|
= ch_p(T_ASM)
|
|
>> ch_p(T_LEFTPAREN) >> ch_p(T_STRINGLIT) >> ch_p(T_RIGHTPAREN)
|
|
>> ch_p(T_SEMICOLON)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(init_declarator_list);
|
|
init_declarator_list
|
|
= init_declarator % ch_p(T_COMMA)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(init_declarator);
|
|
init_declarator
|
|
= declarator >> !initializer
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(initializer);
|
|
initializer
|
|
= ch_p(T_ASSIGN) >> initializer_clause
|
|
| ch_p(T_LEFTPAREN) >> expression_list >> ch_p(T_RIGHTPAREN)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(initializer_clause);
|
|
initializer_clause
|
|
= assignment_expression
|
|
| ch_p(T_LEFTBRACE) >> initializer_list
|
|
>> !ch_p(T_COMMA) >> ch_p(T_RIGHTBRACE)
|
|
| ch_p(T_LEFTBRACE) >> ch_p(T_RIGHTBRACE)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(initializer_list);
|
|
initializer_list
|
|
= initializer_clause % ch_p(T_COMMA)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(expression_list);
|
|
expression_list
|
|
= assignment_expression % ch_p(T_COMMA)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(namespace_alias_definition);
|
|
namespace_alias_definition
|
|
= ch_p(T_NAMESPACE) >> ch_p(T_IDENTIFIER) >> ch_p(T_ASSIGN)
|
|
>> qualified_namespace_specifier
|
|
>> ch_p(T_SEMICOLON)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(qualified_namespace_specifier);
|
|
qualified_namespace_specifier
|
|
= !ch_p(T_COLON_COLON) >> !nested_name_specifier
|
|
>> namespace_name
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(explicit_instantiation);
|
|
explicit_instantiation
|
|
= template_declaration
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(template_declaration);
|
|
template_declaration
|
|
= !ch_p(T_EXPORT) >> ch_p(T_TEMPLATE)
|
|
>> ch_p(T_LESS) >> template_parameter_list >> ch_p(T_GREATER)
|
|
>> declaration
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(template_parameter_list);
|
|
template_parameter_list
|
|
= template_parameter % ch_p(T_COMMA)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(template_parameter);
|
|
template_parameter
|
|
= type_parameter
|
|
| parameter_declaration
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(type_parameter);
|
|
type_parameter
|
|
= ch_p(T_CLASS) >> !ch_p(T_IDENTIFIER)
|
|
>> !(ch_p(T_ASSIGN) >> type_id)
|
|
| ch_p(T_TYPENAME) >> !ch_p(T_IDENTIFIER)
|
|
>> !(ch_p(T_ASSIGN) >> type_id)
|
|
| ch_p(T_TEMPLATE)
|
|
>> ch_p(T_LESS) >> template_parameter_list >> ch_p(T_GREATER)
|
|
>> ch_p(T_CLASS) >> !ch_p(T_IDENTIFIER)
|
|
>> !(ch_p(T_ASSIGN) >> template_name)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(template_name);
|
|
template_name
|
|
= ch_p(T_IDENTIFIER)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(using_declaration);
|
|
using_declaration // optimize?
|
|
= ch_p(T_USING) >> !ch_p(T_TYPENAME) >> !ch_p(T_COLON_COLON)
|
|
>> nested_name_specifier >> unqualified_id
|
|
>> ch_p(T_SEMICOLON)
|
|
| ch_p(T_USING) >> ch_p(T_COLON_COLON) >> unqualified_id
|
|
>> ch_p(T_SEMICOLON)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(using_directive);
|
|
using_directive
|
|
= ch_p(T_USING) >> ch_p(T_NAMESPACE) >> !ch_p(T_COLON_COLON)
|
|
>> !nested_name_specifier >> namespace_name
|
|
>> ch_p(T_SEMICOLON)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(explicit_specialization);
|
|
explicit_specialization
|
|
= ch_p(T_TEMPLATE) >> ch_p(T_LESS) >> ch_p(T_GREATER)
|
|
>> declaration
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(linkage_specification);
|
|
linkage_specification
|
|
= ch_p(T_EXTERN) >> ch_p(T_STRINGLIT)
|
|
>> ( ch_p(T_LEFTBRACE) >> !declaration_seq >> ch_p(T_RIGHTBRACE)
|
|
| declaration
|
|
)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(namespace_definition);
|
|
namespace_definition
|
|
= named_namespace_definition
|
|
| unnamed_namespace_definition // TODO: optimize?
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(named_namespace_definition);
|
|
named_namespace_definition
|
|
= original_namespace_definition
|
|
// | extension_namespace_definition // optimization: extension namespace is syntactically identical
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(original_namespace_definition);
|
|
original_namespace_definition
|
|
= ch_p(T_NAMESPACE) >> ch_p(T_IDENTIFIER)
|
|
>> ch_p(T_LEFTBRACE) >> namespace_body >> ch_p(T_RIGHTBRACE)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(extension_namespace_definition);
|
|
extension_namespace_definition
|
|
= ch_p(T_NAMESPACE) >> original_namespace_name
|
|
>> ch_p(T_LEFTBRACE) >> namespace_body >> ch_p(T_RIGHTBRACE)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(original_namespace_name);
|
|
original_namespace_name
|
|
= ch_p(T_IDENTIFIER)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(unnamed_namespace_definition);
|
|
unnamed_namespace_definition
|
|
= ch_p(T_NAMESPACE)
|
|
>> ch_p(T_LEFTBRACE) >> namespace_body >> ch_p(T_RIGHTBRACE)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(namespace_body);
|
|
namespace_body
|
|
= !declaration_seq
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(function_definition);
|
|
function_definition
|
|
= function_definition_helper
|
|
>> !ctor_initializer >> !function_body // removed semicolons
|
|
| decl_specifier_seq >> declarator >> function_try_block
|
|
| declarator >> function_try_block
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(function_definition_helper);
|
|
function_definition_helper
|
|
= decl_specifier_seq >> declarator
|
|
| +no_type_decl_specifier >> declarator
|
|
| declarator
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(function_try_block);
|
|
function_try_block
|
|
= ch_p(T_TRY)
|
|
>> !ctor_initializer >> function_body >> handler_seq
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(handler_seq);
|
|
handler_seq
|
|
= +handler
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(handler);
|
|
handler // TODO
|
|
= ch_p(T_CATCH)
|
|
>> comment_nest_p(ch_p(T_LEFTPAREN), ch_p(T_RIGHTPAREN))
|
|
>> compound_statement
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(declarator);
|
|
declarator
|
|
= *( ptr_operator
|
|
| odd_language_extension
|
|
)
|
|
>> direct_declarator
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(direct_declarator);
|
|
direct_declarator
|
|
= ( declarator_id
|
|
| ch_p(T_LEFTPAREN) >> declarator >> ch_p(T_RIGHTPAREN)
|
|
)
|
|
>> *parameters_or_array_spec
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(parameters_or_array_spec);
|
|
parameters_or_array_spec
|
|
= ch_p(T_LEFTPAREN) >> parameter_declaration_clause >> ch_p(T_RIGHTPAREN)
|
|
>> !cv_qualifier_seq >> !exception_specification
|
|
| pp(T_LEFTBRACKET) >> !constant_expression >> pp(T_RIGHTBRACKET)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(exception_specification);
|
|
exception_specification // TODO
|
|
= ch_p(T_THROW)
|
|
>> comment_nest_p(ch_p(T_LEFTPAREN), ch_p(T_RIGHTPAREN))
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(abstract_declarator);
|
|
abstract_declarator
|
|
= +( ptr_operator
|
|
| odd_language_extension
|
|
)
|
|
>> !direct_abstract_declarator
|
|
| direct_abstract_declarator
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(direct_abstract_declarator);
|
|
direct_abstract_declarator
|
|
= ch_p(T_LEFTPAREN) >> abstract_declarator >> ch_p(T_RIGHTPAREN)
|
|
>> *direct_abstract_declarator_helper
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(direct_abstract_declarator_helper);
|
|
direct_abstract_declarator_helper
|
|
= ch_p(T_LEFTPAREN) >> parameter_declaration_clause >> ch_p(T_RIGHTPAREN)
|
|
>> !cv_qualifier_seq >> !exception_specification
|
|
| pp(T_LEFTBRACKET) >> !constant_expression >> pp(T_RIGHTBRACKET)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(parameter_declaration_clause);
|
|
parameter_declaration_clause
|
|
= parameter_declaration_list >> ch_p(T_COMMA)
|
|
>> ch_p(T_ELLIPSIS)
|
|
| !parameter_declaration_list >> !ch_p(T_ELLIPSIS)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(parameter_declaration_list);
|
|
parameter_declaration_list
|
|
= parameter_declaration % ch_p(T_COMMA)
|
|
;
|
|
|
|
|
|
HANNIBAL_REGISTER_RULE(parameter_declaration);
|
|
parameter_declaration
|
|
= decl_specifier_seq
|
|
>> !(declarator | abstract_declarator)
|
|
>> !(ch_p(T_ASSIGN) >> assignment_expression)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(declarator_id);
|
|
declarator_id
|
|
= !ch_p(T_COLON_COLON)
|
|
>> ( id_expression
|
|
| !nested_name_specifier >> type_name
|
|
)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(id_expression);
|
|
id_expression
|
|
= qualified_id
|
|
| unqualified_id
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(qualified_id);
|
|
qualified_id
|
|
= nested_name_specifier >> !ch_p(T_TEMPLATE) >> unqualified_id
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(unqualified_id);
|
|
unqualified_id
|
|
= operator_function_id
|
|
| conversion_function_id
|
|
| ch_p(T_COMPL) >> class_name
|
|
| template_id
|
|
| ch_p(T_IDENTIFIER)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(operator_function_id);
|
|
operator_function_id
|
|
= ch_p(T_OPERATOR) >> operator_sym // this is called 'operator' in the std grammar
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(operator_sym);
|
|
operator_sym
|
|
= ch_p(T_DELETE) >> !(pp(T_LEFTBRACKET) >> pp(T_RIGHTBRACKET))
|
|
| ch_p(T_NEW) >> !(pp(T_LEFTBRACKET) >> pp(T_RIGHTBRACKET))
|
|
| pp(T_LEFTBRACKET) >> pp(T_RIGHTBRACKET)
|
|
| ch_p(T_LEFTPAREN) >> ch_p(T_RIGHTPAREN)
|
|
| pattern_p(OperatorTokenType, TokenTypeMask)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(conversion_function_id);
|
|
conversion_function_id
|
|
= ch_p(T_OPERATOR) >> conversion_type_id
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( conversion_type_id);
|
|
conversion_type_id
|
|
= type_specifier_seq >> !conversion_declarator
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(type_id);
|
|
type_id
|
|
= type_specifier_seq >> !abstract_declarator
|
|
;
|
|
|
|
|
|
HANNIBAL_REGISTER_RULE(conversion_declarator);
|
|
conversion_declarator
|
|
= ptr_operator >> !conversion_declarator
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(function_body);
|
|
function_body
|
|
= compound_statement
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(compound_statement);
|
|
compound_statement
|
|
= comment_nest_p(ch_p(T_LEFTBRACE), ch_p(T_RIGHTBRACE))
|
|
; // TODO later
|
|
|
|
|
|
HANNIBAL_REGISTER_RULE(ptr_operator);
|
|
ptr_operator
|
|
= ch_p(T_STAR) >> !cv_qualifier_seq
|
|
| ch_p(T_AND)
|
|
| !ch_p(T_COLON_COLON) >> nested_name_specifier
|
|
>> ch_p(T_STAR) >> !cv_qualifier_seq
|
|
;
|
|
|
|
|
|
HANNIBAL_REGISTER_RULE(decl_specifier);
|
|
decl_specifier
|
|
= no_type_decl_specifier
|
|
| type_specifier
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(no_type_decl_specifier);
|
|
no_type_decl_specifier
|
|
= storage_class_specifier
|
|
| function_specifier
|
|
| ch_p(T_FRIEND)
|
|
| ch_p(T_TYPEDEF)
|
|
| cv_qualifier
|
|
| odd_language_extension
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(type_specifier_seq);
|
|
type_specifier_seq
|
|
= +type_specifier
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(type_specifier);
|
|
type_specifier
|
|
= enum_specifier
|
|
| class_specifier
|
|
| elaborated_type_specifier
|
|
| simple_type_specifier
|
|
| cv_qualifier
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(cv_qualifier_seq);
|
|
cv_qualifier_seq
|
|
= cv_qualifier >> !cv_qualifier_seq
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(cv_qualifier);
|
|
cv_qualifier
|
|
= ch_p(T_CONST)
|
|
| ch_p(T_VOLATILE)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(enum_specifier);
|
|
enum_specifier
|
|
= enum_keyword >> !ch_p(T_IDENTIFIER)
|
|
>> ch_p(T_LEFTBRACE) >> !enumerator_list >> ch_p(T_RIGHTBRACE)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(enum_keyword);
|
|
enum_keyword
|
|
= ch_p(T_ENUM)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(enumerator_list);
|
|
enumerator_list
|
|
= enumerator_definition % ch_p(T_COMMA)
|
|
>> !ch_p(T_COMMA)
|
|
// TODO find out if this last COMMA_T is an MS-"extension"?
|
|
// it seems not to be in the grammar but MSVC 7.0 accepts it.
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(enumerator_definition);
|
|
enumerator_definition
|
|
= enumerator >> !(ch_p(T_ASSIGN) >> constant_expression)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(enumerator);
|
|
enumerator
|
|
= ch_p(T_IDENTIFIER)
|
|
;
|
|
|
|
|
|
HANNIBAL_REGISTER_RULE(simple_type_specifier);
|
|
simple_type_specifier
|
|
= !ch_p(T_COLON_COLON) >> !nested_name_specifier
|
|
>> ch_p(T_TEMPLATE) >> template_id
|
|
| +simple_type_name
|
|
| !ch_p(T_COLON_COLON) >> !nested_name_specifier >> type_name
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(class_head);
|
|
class_head // DH changed the order because otherwise it would always parse the (!IDENTIFIER) part.
|
|
= !access_specifier >> *odd_language_extension
|
|
>> class_key >> *odd_language_extension
|
|
>> (
|
|
!nested_name_specifier >> template_id
|
|
| nested_name_specifier >> ch_p(T_IDENTIFIER)
|
|
| !ch_p(T_IDENTIFIER)
|
|
)
|
|
>> !base_clause
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(type_name);
|
|
type_name
|
|
= class_name
|
|
| enum_name
|
|
| typedef_name
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(elaborated_type_specifier);
|
|
elaborated_type_specifier
|
|
= class_key >> *odd_language_extension
|
|
>> !ch_p(T_COLON_COLON)
|
|
>> !nested_name_specifier
|
|
>> (
|
|
!ch_p(T_TEMPLATE) >> template_id
|
|
| ch_p(T_IDENTIFIER)
|
|
)
|
|
| ch_p(T_ENUM) >> !ch_p(T_COLON_COLON)
|
|
>> !nested_name_specifier
|
|
>> ch_p(T_IDENTIFIER)
|
|
| ch_p(T_TYPENAME)
|
|
>> !ch_p(T_COLON_COLON)
|
|
>> nested_name_specifier
|
|
>> (
|
|
!ch_p(T_TEMPLATE) >> template_id
|
|
| ch_p(T_IDENTIFIER)
|
|
)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(template_argument_list);
|
|
template_argument_list
|
|
= template_argument % ch_p(T_COMMA)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(template_argument);
|
|
template_argument
|
|
= longest_d
|
|
[
|
|
type_id
|
|
| ta_assignment_expression
|
|
| template_name
|
|
]
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(class_key);
|
|
class_key
|
|
= class_keywords
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(class_keywords);
|
|
class_keywords
|
|
= ch_p(T_CLASS)
|
|
| ch_p(T_STRUCT)
|
|
| ch_p(T_UNION)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(nested_name_specifier);
|
|
nested_name_specifier
|
|
= class_or_namespace_name >> ch_p(T_COLON_COLON)
|
|
>> ch_p(T_TEMPLATE) >> nested_name_specifier
|
|
| class_or_namespace_name >> ch_p(T_COLON_COLON)
|
|
>> !nested_name_specifier
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(class_or_namespace_name);
|
|
class_or_namespace_name
|
|
= class_name
|
|
| namespace_name
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(class_name);
|
|
class_name
|
|
= template_id
|
|
| ch_p(T_IDENTIFIER)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(enum_name);
|
|
enum_name
|
|
= ch_p(T_IDENTIFIER)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(typedef_name);
|
|
typedef_name
|
|
= ch_p(T_IDENTIFIER)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(namespace_name);
|
|
namespace_name // TODO
|
|
= ch_p(T_IDENTIFIER)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(template_id);
|
|
template_id
|
|
= template_name
|
|
>> ch_p(T_LESS) >> template_argument_list >> ch_p(T_GREATER)
|
|
;
|
|
|
|
//
|
|
// This is kind of a HACK. We want to prevent the decl_specifier_seq
|
|
// from eating the whole declaration, including the ch_p(T_IDENTIFIER).
|
|
// Therefore in the sequence, we only allow one 'unknown' word
|
|
// (the type_specifier), the rest of the decl_specifier sequence
|
|
// must consist of known keywords or constructs (the
|
|
// no_type_decl_specifier).
|
|
// This means that a declaration like:
|
|
// MYDLL_EXPORT int f();
|
|
// will not be accepted unless the MYDLL_EXPORT is properly
|
|
// expanded by the preprocessor first.
|
|
//
|
|
// This should not cause any problems normally, it just means that
|
|
// this rule is not very robust in the case where not all symbols
|
|
// are known.
|
|
//
|
|
HANNIBAL_REGISTER_RULE(decl_specifier_seq);
|
|
decl_specifier_seq
|
|
= *no_type_decl_specifier >> type_specifier >> *no_type_decl_specifier
|
|
;
|
|
|
|
// The following rule is more according to the standard grammar
|
|
// decl_specifier_seq // adapted
|
|
// = decl_specifier >> decl_specifier_seq
|
|
// | (decl_specifier - (declarator_id >> parameters_or_array_spec ))
|
|
// ;
|
|
|
|
HANNIBAL_REGISTER_RULE( storage_class_specifier);
|
|
storage_class_specifier
|
|
= ch_p(T_AUTO)
|
|
| ch_p(T_REGISTER)
|
|
| ch_p(T_STATIC)
|
|
| ch_p(T_EXTERN)
|
|
| ch_p(T_MUTABLE)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE( function_specifier);
|
|
function_specifier
|
|
= ch_p(T_INLINE)
|
|
| ch_p(T_VIRTUAL)
|
|
| ch_p(T_EXPLICIT)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(class_specifier);
|
|
class_specifier
|
|
= class_head
|
|
>> ch_p(T_LEFTBRACE) >> !member_specification >> ch_p(T_RIGHTBRACE)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(member_specification);
|
|
member_specification
|
|
= +( access_specifier >> ch_p(T_COLON)
|
|
| member_declaration HANNIBAL_TRACE_ACTION("member declaration")
|
|
)
|
|
;
|
|
|
|
// member_specification
|
|
// = access_specifier >> COLON_T >> !member_specification
|
|
// | member_declaration >> !member_specification
|
|
// ;
|
|
|
|
HANNIBAL_REGISTER_RULE(member_declaration);
|
|
member_declaration
|
|
= using_declaration
|
|
| template_declaration
|
|
| !decl_specifier_seq >> !member_declarator_list
|
|
>> ch_p(T_SEMICOLON)
|
|
| function_definition >>
|
|
!ch_p(T_SEMICOLON)
|
|
| qualified_id
|
|
>> ch_p(T_SEMICOLON)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(member_declarator_list);
|
|
member_declarator_list
|
|
= member_declarator % ch_p(T_COMMA)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(member_declarator);
|
|
member_declarator
|
|
= !ch_p(T_IDENTIFIER) >> ch_p(T_COLON) >> constant_expression
|
|
| declarator >> !(pure_specifier | constant_initializer)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(pure_specifier);
|
|
pure_specifier
|
|
= ch_p(T_ASSIGN) >> ch_p(T_INTLIT)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(constant_initializer);
|
|
constant_initializer
|
|
= ch_p(T_ASSIGN) >> constant_expression
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(access_specifier);
|
|
access_specifier
|
|
= ch_p(T_PUBLIC)
|
|
| ch_p(T_PROTECTED)
|
|
| ch_p(T_PRIVATE)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(base_clause);
|
|
base_clause
|
|
= ch_p(T_COLON) >> base_specifier_list
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(base_specifier_list);
|
|
base_specifier_list
|
|
= base_specifier % ch_p(T_COMMA)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(base_specifier);
|
|
base_specifier
|
|
= ch_p(T_VIRTUAL) >> !access_specifier >> !ch_p(T_COLON_COLON)
|
|
>> !nested_name_specifier >> class_name
|
|
| access_specifier >> !ch_p(T_VIRTUAL) >> !ch_p(T_COLON_COLON)
|
|
>> !nested_name_specifier >> class_name
|
|
| !ch_p(T_COLON_COLON) >> !nested_name_specifier >> class_name
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(extension_type_decorator);
|
|
extension_type_decorator
|
|
= ch_p(T_MSEXT_CDECL)
|
|
| ch_p(T_MSEXT_DECLSPEC)
|
|
| ch_p(T_MSEXT_BASED)
|
|
| ch_p(T_MSEXT_FASTCALL)
|
|
| ch_p(T_MSEXT_INLINE)
|
|
;
|
|
|
|
HANNIBAL_REGISTER_RULE(simple_type_name);
|
|
simple_type_name
|
|
= ch_p(T_CHAR)
|
|
| ch_p(T_WCHART)
|
|
| ch_p(T_BOOL)
|
|
| ch_p(T_SHORT)
|
|
| ch_p(T_INT)
|
|
| ch_p(T_LONG)
|
|
| ch_p(T_UNSIGNED)
|
|
| ch_p(T_SIGNED)
|
|
| ch_p(T_FLOAT)
|
|
| ch_p(T_DOUBLE)
|
|
| ch_p(T_VOID)
|
|
| ch_p(T_MSEXT_INT64)
|
|
| ch_p(T_MSEXT_INT8)
|
|
| ch_p(T_MSEXT_INT16)
|
|
| ch_p(T_MSEXT_INT32)
|
|
;
|
|
}
|
|
|
|
rule_type const& start() const { return translation_unit; }
|
|
|
|
// Helper function wrapping pattern_p
|
|
static inline boost::wave::util::pattern_and< boost::wave::token_id>
|
|
pp (boost::wave::token_id id)
|
|
{
|
|
using namespace boost::wave;
|
|
return util::pattern_p(id, MainTokenMask);
|
|
}
|
|
};
|
|
|
|
#if HANNIBAL_DUMP_PARSE_TREE != 0
|
|
private:
|
|
template<typename Rule>
|
|
void declare_rule(Rule const& rule, std::string const& rule_name) const
|
|
{
|
|
if (rule_map_ptr)
|
|
(*rule_map_ptr)[rule.id()] = rule_name;
|
|
}
|
|
rule_map_type *rule_map_ptr;
|
|
#endif
|
|
};
|
|
|
|
#undef HANNIBAL_REGISTER_RULE
|
|
#undef HANNIBAL_TRACE_TRANSLATION_UNIT_GRAMMAR
|
|
|
|
#endif // HANNIBAL_TRANSLATION_UNIT_GRAMMAR_H_INCLUDED
|