/*=============================================================================
Wave: A Standard compliant C++ preprocessor
Copyright (c) 2001-2004 Hartmut Kaiser
http://spirit.sourceforge.net/
Use, modification and distribution is subject to 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)
See Copyright.txt for full acknowledgements.
=============================================================================*/
#if !defined(CPP_GRAMMAR_HPP_FEAEBC2E_2734_428B_A7CA_85E5A415E23E_INCLUDED)
#define CPP_GRAMMAR_HPP_FEAEBC2E_2734_428B_A7CA_85E5A415E23E_INCLUDED
#include <boost/spirit/core.hpp>
#include <boost/spirit/tree/parse_tree.hpp>
#include <boost/spirit/tree/parse_tree_utils.hpp>
#include <boost/spirit/utility/parsers/confix.hpp>
#include <boost/spirit/utility/parsers/lists.hpp>
#if defined(WAVE_DUMP_PARSE_TREE)
#include <map>
#include <boost/spirit/tree/tree_to_xml.hpp>
#endif // defined(WAVE_DUMP_PARSE_TREE)
#include "wave/token_ids.hpp"
#include "wave/lex_iterator.hpp"
#include "wave/grammars/cpp_grammar_gen.hpp"
#include "wave/util/pattern_parser.hpp"
#include "wave/cpp_exceptions.hpp"
///////////////////////////////////////////////////////////////////////////////
namespace wave {
namespace grammars {
namespace impl {
///////////////////////////////////////////////////////////////////////////////
//
// store_position
//
// The store_position functor extracts the actual file position from the
// supplied token.
//
///////////////////////////////////////////////////////////////////////////////
template <typename PositionT>
struct store_position {
store_position(PositionT &pos_) : pos(pos_) {}
template <typename TokenT>
void operator()(TokenT const &token) const
{
pos = token.get_position();
}
PositionT &pos;
};
///////////////////////////////////////////////////////////////////////////////
//
// store_found_eof
//
// The store_found_eof functor sets a given flag if the T_EOF token was
// found during the parsing process
//
///////////////////////////////////////////////////////////////////////////////
struct store_found_eof {
store_found_eof(bool &found_eof_) : found_eof(found_eof_) {}
template <typename TokenT>
void operator()(TokenT const &token) const
{
found_eof = true;
}
bool &found_eof;
};
///////////////////////////////////////////////////////////////////////////////
//
// store_found_directive
//
// The store_found_directive functor stores the token_id of the recognized
// pp directive
//
///////////////////////////////////////////////////////////////////////////////
struct store_found_directive {
store_found_directive(WAVE_LEXER_NS::token_id &found_directive_)
: found_directive(found_directive_) {}
template <typename TokenT>
void operator()(TokenT const &token) const
{
found_directive = WAVE_LEXER_NS::token_id(token);
}
WAVE_LEXER_NS::token_id &found_directive;
};
///////////////////////////////////////////////////////////////////////////////
//
// flush_underlying_parser
//
// The flush_underlying_parser flushes the underlying
// multi_pass_iterator during the normal parsing process. This is
// used at certain points during the parsing process, when it is
// clear, that no backtracking is needed anymore and the input
// gathered so far may be discarded.
//
///////////////////////////////////////////////////////////////////////////////
struct flush_underlying_parser
: public boost::spirit::parser<flush_underlying_parser>
{
typedef flush_underlying_parser this_t;
template <typename ScannerT>
typename boost::spirit::parser_result<this_t, ScannerT>::type
parse(ScannerT const& scan) const
{
scan.first.clear_queue();
return scan.empty_match();
}
};
flush_underlying_parser const
flush_underlying_parser_p = flush_underlying_parser();
} // anonymous namespace
///////////////////////////////////////////////////////////////////////////////
// define, whether the rule's should generate some debug output
#define TRACE_CPP_GRAMMAR \
bool(BOOST_SPIRIT_DEBUG_FLAGS_CPP & BOOST_SPIRIT_DEBUG_FLAGS_CPP_GRAMMAR) \
/**/
///////////////////////////////////////////////////////////////////////////////
// Encapsulation of the C++ preprocessor grammar.
template <typename PositionT>
struct cpp_grammar :
public boost::spirit::grammar<cpp_grammar<PositionT> >
{
typedef cpp_grammar<PositionT> grammar_t;
typedef impl::store_position<PositionT> store_pos_t;
typedef impl::store_found_eof store_found_eof_t;
typedef impl::store_found_directive store_found_directive_t;
template <typename ScannerT>
struct definition
{
// non-parse_tree generating rule type
typedef typename ScannerT::iteration_policy_t iteration_policy_t;
typedef boost::spirit::match_policy match_policy_t;
typedef typename ScannerT::action_policy_t action_policy_t;
typedef
boost::spirit::scanner_policies<
iteration_policy_t, match_policy_t, action_policy_t>
policies_t;
typedef
boost::spirit::scanner<typename ScannerT::iterator_t, policies_t>
non_tree_scanner_t;
typedef boost::spirit::rule<non_tree_scanner_t> no_tree_rule_t;
// 'normal' (parse_tree generating) rule type
typedef boost::spirit::rule<ScannerT> rule_t;
rule_t pp_statement;
rule_t include_file, system_include_file, macro_include_file;
rule_t plain_define, macro_definition, macro_parameters;
rule_t undefine;
rule_t ppifdef, ppifndef, ppif, ppelse, ppelif, ppendif;
rule_t ppline;
rule_t pperror;
rule_t ppwarning;
rule_t pppragma;
rule_t illformed;
#if defined(WAVE_ENABLE_CPP0X_EXTENSIONS)
rule_t ppregion;
rule_t ppendregion;
rule_t ppimport;
rule_t pp_regionsupport;
#endif // defined(WAVE_ENABLE_CPP0X_EXTENSIONS)
rule_t ppqualifiedname;
rule_t eol_tokens;
no_tree_rule_t ppsp;
definition(cpp_grammar const &self)
{
// import the spirit and cpplexer namespaces here
using namespace boost::spirit;
using namespace WAVE_LEXER_NS;
using namespace wave::util;
// save the rule id's for later use
self.rule_ids.pp_statement_id = pp_statement.id().to_long();
self.rule_ids.include_file_id = include_file.id().to_long();
self.rule_ids.sysinclude_file_id = system_include_file.id().to_long();
self.rule_ids.macroinclude_file_id = macro_include_file.id().to_long();
self.rule_ids.plain_define_id = plain_define.id().to_long();
self.rule_ids.macro_parameters_id = macro_parameters.id().to_long();
self.rule_ids.macro_definition_id = macro_definition.id().to_long();
self.rule_ids.undefine_id = undefine.id().to_long();
self.rule_ids.ifdef_id = ppifdef.id().to_long();
self.rule_ids.ifndef_id = ppifndef.id().to_long();
self.rule_ids.if_id = ppif.id().to_long();
self.rule_ids.elif_id = ppelif.id().to_long();
self.rule_ids.else_id = ppelse.id().to_long();
self.rule_ids.endif_id = ppendif.id().to_long();
self.rule_ids.line_id = ppline.id().to_long();
self.rule_ids.error_id = pperror.id().to_long();
self.rule_ids.warning_id = ppwarning.id().to_long();
self.rule_ids.pragma_id = pppragma.id().to_long();
self.rule_ids.illformed_id = illformed.id().to_long();
self.rule_ids.ppspace_id = ppsp.id().to_long();
#if defined(WAVE_ENABLE_CPP0X_EXTENSIONS)
self.rule_ids.ppregion_id = ppregion.id().to_long();
self.rule_ids.ppendregion_id = ppendregion.id().to_long();
self.rule_ids.pp_regionsupport_id = pp_regionsupport.id().to_long();
self.rule_ids.ppimport_id = ppimport.id().to_long();
#endif // defined(WAVE_ENABLE_CPP0X_EXTENSIONS)
self.rule_ids.ppqualifiedname_id = ppqualifiedname.id().to_long();
#if defined(WAVE_DUMP_PARSE_TREE)
self.map_rule_id_to_name.init_rule_id_to_name_map(self);
#endif // defined(WAVE_DUMP_PARSE_TREE)
// recognizes preprocessor directives only
// C++ standard 16.1: A preprocessing directive consists of a sequence
// of preprocessing tokens. The first token in the sequence is #
// preprocessing token that is either the first character in the source
// file (optionally after white space containing no new-line
// characters) or that follows white space containing at least one
// new-line character. The last token in the sequence is the first
// new-line character that follows the first token in the sequence.
pp_statement
= ( include_file
| system_include_file
| macro_include_file
| plain_define
| undefine
| ppifdef
| ppifndef
| ppif
| ppelse
| ppelif
| ppendif
| ppline
| pperror
| ppwarning
| pppragma
#if defined(WAVE_ENABLE_CPP0X_EXTENSIONS)
| pp_regionsupport
#endif // defined(WAVE_ENABLE_CPP0X_EXTENSIONS)
| illformed
)
>> eol_tokens
#if !defined(BOOST_SPIRIT_DEBUG) || \
(BOOST_SPIRIT_DEBUG_FLAGS_CPP & BOOST_SPIRIT_DEBUG_FLAGS_CPP_GRAMMAR)
>> impl::flush_underlying_parser_p
#endif // !defined(BOOST_SPIRIT_DEBUG ||
// (BOOST_SPIRIT_DEBUG_FLAGS_CPP & BOOST_SPIRIT_DEBUG_FLAGS_CPP_GRAMMAR)
;
#if defined(WAVE_ENABLE_CPP0X_EXTENSIONS)
// the pp_regionsupport is factored out, because else
// VC7.1 complains about an out of heapspace error (non-fixable)
pp_regionsupport
= ppregion
| ppendregion
| ppimport
;
#endif // defined(WAVE_ENABLE_CPP0X_EXTENSIONS)
// #include ...
include_file // include "..."
= ch_p(T_PP_QHEADER)
[ store_found_directive_t(self.found_directive) ]
;
system_include_file // include <...>
= ch_p(T_PP_HHEADER)
[ store_found_directive_t(self.found_directive) ]
;
macro_include_file // include ...anything else...
= no_node_d
[
ch_p(T_PP_INCLUDE)
[ store_found_directive_t(self.found_directive) ]
]
>> *( anychar_p -
(ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
)
;
// #define FOO foo (with optional parameters)
plain_define
= no_node_d
[
ch_p(T_PP_DEFINE)
[ store_found_directive_t(self.found_directive) ]
>> +ppsp
]
>> ( ch_p(T_IDENTIFIER)
| pattern_p(KeywordTokenType, TokenTypeMask)
)
>> !macro_parameters
>> !macro_definition
;
// parameter list
// normal C++ mode
macro_parameters
= confix_p(
no_node_d[ch_p(T_LEFTPAREN) >> *ppsp],
!list_p(
( ch_p(T_IDENTIFIER)
| pattern_p(KeywordTokenType, TokenTypeMask)
#if defined(WAVE_SUPPORT_VARIADICS_PLACEMARKERS)
| ch_p(T_ELLIPSIS)
#endif // defined(WAVE_SUPPORT_VARIADICS_PLACEMARKERS)
),
no_node_d[*ppsp >> ch_p(T_COMMA) >> *ppsp]
),
no_node_d[*ppsp >> ch_p(T_RIGHTPAREN)]
)
;
// macro body (anything left until eol)
macro_definition
= no_node_d[*ppsp]
>> *( anychar_p -
(ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
)
;
// #undef FOO
undefine
= no_node_d
[
ch_p(T_PP_UNDEF)
[ store_found_directive_t(self.found_directive) ]
>> +ppsp
]
>> ( ch_p(T_IDENTIFIER)
| pattern_p(KeywordTokenType, TokenTypeMask)
)
;
// #ifdef et.al.
ppifdef
= no_node_d
[
ch_p(T_PP_IFDEF)
[ store_found_directive_t(self.found_directive) ]
>> +ppsp
]
>> ppqualifiedname
;
ppifndef
= no_node_d
[
ch_p(T_PP_IFNDEF)
[ store_found_directive_t(self.found_directive) ]
>> +ppsp
]
>> ppqualifiedname
;
ppif
= no_node_d
[
ch_p(T_PP_IF)
[ store_found_directive_t(self.found_directive) ]
>> *ppsp
]
>> +( anychar_p -
(ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
)
;
ppelse
= no_node_d
[
ch_p(T_PP_ELSE)
[ store_found_directive_t(self.found_directive) ]
]
;
ppelif
= no_node_d
[
ch_p(T_PP_ELIF)
[ store_found_directive_t(self.found_directive) ]
>> *ppsp
]
>> +( anychar_p -
(ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
)
;
ppendif
= no_node_d
[
ch_p(T_PP_ENDIF)
[ store_found_directive_t(self.found_directive) ]
]
;
// #line ...
ppline
= no_node_d
[
ch_p(T_PP_LINE)
[ store_found_directive_t(self.found_directive) ]
>> *ppsp
]
>> +( anychar_p -
(ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
)
;
// # something else (ill formed preprocessor directive)
illformed // for error reporting
= no_node_d[ch_p(T_POUND) >> *ppsp]
>> ( anychar_p -
(ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
)
>> no_node_d
[
*( anychar_p -
(ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
)
]
;
// #error
pperror
= no_node_d
[
ch_p(T_PP_ERROR)
[ store_found_directive_t(self.found_directive) ]
>> *ppsp
]
>> *( anychar_p -
(ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
)
;
// #warning
ppwarning
= no_node_d
[
ch_p(T_PP_WARNING)
[ store_found_directive_t(self.found_directive) ]
>> *ppsp
]
>> *( anychar_p -
(ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
)
;
// #pragma ...
pppragma
= no_node_d
[
ch_p(T_PP_PRAGMA)
[ store_found_directive_t(self.found_directive) ]
]
>> *( anychar_p -
(ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
)
;
#if defined(WAVE_ENABLE_CPP0X_EXTENSIONS)
// #region [name]
ppregion
= no_node_d
[
ch_p(T_PP_REGION)
[ store_found_directive_t(self.found_directive) ]
]
>> !(
no_node_d[+ppsp]
>> ppqualifiedname
)
;
// #endregion
ppendregion
= no_node_d
[
ch_p(T_PP_ENDREGION)
[ store_found_directive_t(self.found_directive) ]
]
;
// #import name
ppimport
= no_node_d
[
ch_p(T_PP_IMPORT)
[ store_found_directive_t(self.found_directive) ]
>> *ppsp
]
>> list_p(
ppqualifiedname,
no_node_d[*ppsp >> ch_p(T_COMMA) >> *ppsp]
)
;
#endif // defined(WAVE_ENABLE_CPP0X_EXTENSIONS)
#if !defined(WAVE_USE_RE2C_IDL_LEXER)
// possibly qualified name
ppqualifiedname
= ch_p(T_COLON_COLON)
|| (no_node_d[*ppsp]
>> list_p(
( ch_p(T_IDENTIFIER)
| pattern_p(KeywordTokenType, TokenTypeMask)
),
no_node_d[*ppsp]
>> ch_p(T_COLON_COLON)
>> no_node_d[*ppsp]
)
)
;
#else
ppqualifiedname
= no_node_d[*ppsp]
>> ( ch_p(T_IDENTIFIER)
| pattern_p(KeywordTokenType, TokenTypeMask)
)
;
#endif // !defined(WAVE_USE_RE2C_IDL_LEXER)
// auxiliary helper rules
ppsp // valid space in a line with a preprocessor directive
= ch_p(T_SPACE) | ch_p(T_CCOMMENT)
;
// end of line tokens
eol_tokens
= no_node_d
[
*ppsp
>> ( ch_p(T_NEWLINE)
[ store_pos_t(self.pos_of_newline) ]
| ch_p(T_CPPCOMMENT)
[ store_pos_t(self.pos_of_newline) ]
| ch_p(T_EOF)
[ store_pos_t(self.pos_of_newline) ]
[ store_found_eof_t(self.found_eof) ]
)
]
;
BOOST_SPIRIT_DEBUG_TRACE_RULE(pp_statement, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(include_file, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(system_include_file, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(macro_include_file, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(plain_define, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(macro_definition, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(macro_parameters, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(undefine, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(ppifdef, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(ppifndef, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(ppif, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(ppelse, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(ppelif, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(ppendif, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(ppline, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(pperror, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(ppwarning, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(illformed, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(ppsp, TRACE_CPP_GRAMMAR);
#if defined(WAVE_ENABLE_CPP0X_EXTENSIONS)
BOOST_SPIRIT_DEBUG_TRACE_RULE(pp_regionsupport, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(ppregion, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(ppendregion, TRACE_CPP_GRAMMAR);
BOOST_SPIRIT_DEBUG_TRACE_RULE(ppimport, TRACE_CPP_GRAMMAR);
#endif // defined(WAVE_ENABLE_CPP0X_EXTENSIONS)
BOOST_SPIRIT_DEBUG_TRACE_RULE(ppqualifiedname, TRACE_CPP_GRAMMAR);
}
// start rule of this grammar
rule_t const& start() const
{ return pp_statement; }
};
cpp_grammar_rule_ids &rule_ids;
PositionT &pos_of_newline;
bool &found_eof;
WAVE_LEXER_NS::token_id &found_directive;
cpp_grammar(cpp_grammar_rule_ids &rule_ids_, PositionT &pos_of_newline_,
bool &found_eof_, WAVE_LEXER_NS::token_id &found_directive_)
: rule_ids(rule_ids_), pos_of_newline(pos_of_newline_),
found_eof(found_eof_), found_directive(found_directive_)
{
BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(*this, "cpp_grammar",
TRACE_CPP_GRAMMAR);
}
#if defined(WAVE_DUMP_PARSE_TREE)
// helper function and data to get readable names of the rules known to us
struct map_ruleid_to_name :
public std::map<boost::spirit::parser_id, std::string>
{
typedef std::map<boost::spirit::parser_id, std::string> base_t;
void init_rule_id_to_name_map(cpp_grammar const &self)
{
struct {
int parser_id;
char const *rule_name;
}
init_ruleid_name_map[] = {
{ self.rule_ids.pp_statement_id, "pp_statement" },
{ self.rule_ids.include_file_id, "include_file" },
{ self.rule_ids.sysinclude_file_id, "system_include_file" },
{ self.rule_ids.macroinclude_file_id, "macro_include_file" },
{ self.rule_ids.plain_define_id, "plain_define" },
{ self.rule_ids.macro_parameters_id, "macro_parameters" },
{ self.rule_ids.macro_definition_id, "macro_definition" },
{ self.rule_ids.undefine_id, "undefine" },
{ self.rule_ids.ifdef_id, "ppifdef" },
{ self.rule_ids.ifndef_id, "ppifndef" },
{ self.rule_ids.if_id, "ppif" },
{ self.rule_ids.elif_id, "ppelif" },
{ self.rule_ids.else_id, "ppelse" },
{ self.rule_ids.endif_id, "ppendif" },
{ self.rule_ids.line_id, "ppline" },
{ self.rule_ids.error_id, "pperror" },
{ self.rule_ids.warning_id, "ppwarning" },
{ self.rule_ids.pragma_id, "pppragma" },
{ self.rule_ids.illformed_id, "illformed" },
{ self.rule_ids.ppsp_id, "ppsp" },
#if defined(WAVE_ENABLE_CPP0X_EXTENSIONS)
{ self.rule_ids.pp_regionsupport_id, "pp_regionsupport" },
{ self.rule_ids.ppregion_id, "pp" WAVE_PP_REGION },
{ self.rule_ids.ppendregion_id, "pp" WAVE_PP_ENDREGION },
{ self.rule_ids.ppimport_id, "pp" WAVE_PP_IMPORT },
#endif // defined(WAVE_ENABLE_CPP0X_EXTENSIONS)
{ self.rule_ids.ppqualifiedname_id, "ppqualifiedname" },
{ 0 }
};
// initialize parser_id to rule_name map
for (int i = 0; 0 != init_ruleid_name_map[i].parser_id; ++i)
base_t::insert(base_t::value_type(
boost::spirit::parser_id(init_ruleid_name_map[i].parser_id),
std::string(init_ruleid_name_map[i].rule_name))
);
}
};
mutable map_ruleid_to_name map_rule_id_to_name;
#endif // defined(WAVE_DUMP_PARSE_TREE)
};
///////////////////////////////////////////////////////////////////////////////
#undef TRACE_CPP_GRAMMAR
///////////////////////////////////////////////////////////////////////////////
//
// The following parse function is defined here, to allow the separation of
// the compilation of the cpp_grammar from the function using it.
//
///////////////////////////////////////////////////////////////////////////////
#if defined(WAVE_SEPARATE_GRAMMAR_INSTANTIATION)
#define WAVE_GRAMMAR_GEN_INLINE
#else
#define WAVE_GRAMMAR_GEN_INLINE inline
#endif
namespace {
char const *get_directivename(WAVE_LEXER_NS::token_id id)
{
using namespace WAVE_LEXER_NS;
switch (id) {
case T_PP_QHEADER:
case T_PP_HHEADER:
case T_PP_INCLUDE: return "#include";
case T_PP_DEFINE: return "#define";
case T_PP_UNDEF: return "#undef";
case T_PP_IFDEF: return "#ifdef";
case T_PP_IFNDEF: return "#ifndef";
case T_PP_IF: return "#if";
case T_PP_ELSE: return "#else";
case T_PP_ELIF: return "#elif";
case T_PP_ENDIF: return "#endif";
case T_PP_LINE: return "#line";
case T_PP_ERROR: return "#error";
case T_PP_WARNING: return "#warning";
case T_PP_PRAGMA: return "#pragma";
#if defined(WAVE_ENABLE_CPP0X_EXTENSIONS)
case T_PP_REGION: return "#" WAVE_PP_REGION;
case T_PP_ENDREGION: return "#" WAVE_PP_ENDREGION;
case T_PP_IMPORT: return "#" WAVE_PP_IMPORT;
#endif // defined(WAVE_ENABLE_CPP0X_EXTENSIONS)
default:
return "#unknown directive";
}
}
}
template <typename TokenT>
WAVE_GRAMMAR_GEN_INLINE
boost::spirit::tree_parse_info<WAVE_LEXER_NS::lex_iterator<TokenT> >
cpp_grammar_gen<TokenT>::parse_cpp_grammar (
WAVE_LEXER_NS::lex_iterator<TokenT> const &first,
WAVE_LEXER_NS::lex_iterator<TokenT> const &last,
bool &found_eof_, position_t const &act_pos)
{
using namespace boost::spirit;
using namespace WAVE_LEXER_NS;
pos_of_newline = position_t(); // reset position
found_eof = false; // reset flag
found_directive = T_EOF; // reset found directive
static cpp_grammar<typename TokenT::position_t> g(
rule_ids, pos_of_newline, found_eof, found_directive);
tree_parse_info<WAVE_LEXER_NS::lex_iterator<TokenT> > hit =
pt_parse (first, last, g);
#if defined(WAVE_DUMP_PARSE_TREE)
if (hit.match) {
tree_to_xml (WAVE_DUMP_PARSE_TREE_OUT, hit.trees, "",
g.map_rule_id_to_name, &TokenT::get_token_id,
&TokenT::get_token_value);
}
#endif // defined(WAVE_DUMP_PARSE_TREE)
if (!hit.match && found_directive != T_EOF) {
// recognized invalid directive
std::string directive = get_directivename(found_directive);
CPP_THROW(preprocess_exception, ill_formed_directive,
directive, act_pos);
}
found_eof_ = found_eof;
return hit;
}
#undef WAVE_GRAMMAR_GEN_INLINE
///////////////////////////////////////////////////////////////////////////////
} // namespace grammars
} // namespace wave
#endif // !defined(CPP_GRAMMAR_HPP_FEAEBC2E_2734_428B_A7CA_85E5A415E23E_INCLUDED)