You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
765 lines
29 KiB
765 lines
29 KiB
/*============================================================================= |
|
Boost.Wave: A Standard compliant C++ preprocessor library |
|
|
|
http://www.boost.org/ |
|
|
|
Copyright (c) 2001-2011 Hartmut Kaiser. 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(CPP_GRAMMAR_HPP_FEAEBC2E_2734_428B_A7CA_85E5A415E23E_INCLUDED) |
|
#define CPP_GRAMMAR_HPP_FEAEBC2E_2734_428B_A7CA_85E5A415E23E_INCLUDED |
|
|
|
#include <boost/spirit/include/classic_core.hpp> |
|
#include <boost/spirit/include/classic_parse_tree.hpp> |
|
#include <boost/spirit/include/classic_parse_tree_utils.hpp> |
|
#include <boost/spirit/include/classic_confix.hpp> |
|
#include <boost/spirit/include/classic_lists.hpp> |
|
|
|
#include <boost/wave/wave_config.hpp> |
|
#include <boost/pool/pool_alloc.hpp> |
|
|
|
#if BOOST_WAVE_DUMP_PARSE_TREE != 0 |
|
#include <map> |
|
#include <boost/spirit/include/classic_tree_to_xml.hpp> |
|
#endif |
|
|
|
#include <boost/wave/token_ids.hpp> |
|
#include <boost/wave/grammars/cpp_grammar_gen.hpp> |
|
#include <boost/wave/util/pattern_parser.hpp> |
|
|
|
#include <boost/wave/cpp_exceptions.hpp> |
|
|
|
// this must occur after all of the includes and before any code appears |
|
#ifdef BOOST_HAS_ABI_HEADERS |
|
#include BOOST_ABI_PREFIX |
|
#endif |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
namespace boost { |
|
namespace wave { |
|
namespace grammars { |
|
|
|
namespace impl { |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// 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 |
|
// |
|
/////////////////////////////////////////////////////////////////////////////// |
|
|
|
template <typename TokenT> |
|
struct store_found_directive { |
|
|
|
store_found_directive(TokenT &found_directive_) |
|
: found_directive(found_directive_) {} |
|
|
|
void operator()(TokenT const &token) const |
|
{ |
|
found_directive = token; |
|
} |
|
|
|
TokenT &found_directive; |
|
}; |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// store_found_eoltokens |
|
// |
|
// The store_found_eoltokens functor stores the token sequence of the |
|
// line ending for a particular pp directive |
|
// |
|
/////////////////////////////////////////////////////////////////////////////// |
|
|
|
template <typename ContainerT> |
|
struct store_found_eoltokens { |
|
|
|
store_found_eoltokens(ContainerT &found_eoltokens_) |
|
: found_eoltokens(found_eoltokens_) {} |
|
|
|
template <typename IteratorT> |
|
void operator()(IteratorT const &first, IteratorT const& last) const |
|
{ |
|
std::copy(first, last, |
|
std::inserter(found_eoltokens, found_eoltokens.end())); |
|
} |
|
|
|
ContainerT &found_eoltokens; |
|
}; |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// 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::classic::parser<flush_underlying_parser> |
|
{ |
|
typedef flush_underlying_parser this_t; |
|
|
|
template <typename ScannerT> |
|
typename boost::spirit::classic::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 TokenT, typename ContainerT> |
|
struct cpp_grammar : |
|
public boost::spirit::classic::grammar<cpp_grammar<TokenT, ContainerT> > |
|
{ |
|
typedef typename TokenT::position_type position_type; |
|
typedef cpp_grammar<TokenT, ContainerT> grammar_type; |
|
typedef impl::store_found_eof store_found_eof_type; |
|
typedef impl::store_found_directive<TokenT> store_found_directive_type; |
|
typedef impl::store_found_eoltokens<ContainerT> store_found_eoltokens_type; |
|
|
|
template <typename ScannerT> |
|
struct definition |
|
{ |
|
// non-parse_tree generating rule type |
|
typedef typename ScannerT::iteration_policy_t iteration_policy_t; |
|
typedef boost::spirit::classic::match_policy match_policy_t; |
|
typedef typename ScannerT::action_policy_t action_policy_t; |
|
typedef |
|
boost::spirit::classic::scanner_policies< |
|
iteration_policy_t, match_policy_t, action_policy_t> |
|
policies_t; |
|
typedef |
|
boost::spirit::classic::scanner<typename ScannerT::iterator_t, policies_t> |
|
non_tree_scanner_t; |
|
typedef |
|
boost::spirit::classic::rule< |
|
non_tree_scanner_t, boost::spirit::classic::dynamic_parser_tag> |
|
no_tree_rule_type; |
|
|
|
// 'normal' (parse_tree generating) rule type |
|
typedef |
|
boost::spirit::classic::rule< |
|
ScannerT, boost::spirit::classic::dynamic_parser_tag> |
|
rule_type; |
|
|
|
rule_type pp_statement, macro_include_file; |
|
// rule_type include_file, system_include_file; |
|
rule_type plain_define, macro_definition, macro_parameters; |
|
rule_type undefine; |
|
rule_type ppifdef, ppifndef, ppif, ppelif; |
|
// rule_type ppelse, ppendif; |
|
rule_type ppline; |
|
rule_type pperror; |
|
rule_type ppwarning; |
|
rule_type pppragma; |
|
rule_type illformed; |
|
rule_type ppqualifiedname; |
|
rule_type eol_tokens; |
|
no_tree_rule_type ppsp; |
|
#if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0 |
|
rule_type ppregion; |
|
rule_type ppendregion; |
|
#endif |
|
|
|
definition(cpp_grammar const &self) |
|
{ |
|
// import the spirit and cpplexer namespaces here |
|
using namespace boost::spirit::classic; |
|
using namespace boost::wave; |
|
using namespace boost::wave::util; |
|
|
|
// set the rule id's for later use |
|
pp_statement.set_id(BOOST_WAVE_PP_STATEMENT_ID); |
|
// include_file.set_id(BOOST_WAVE_INCLUDE_FILE_ID); |
|
// system_include_file.set_id(BOOST_WAVE_SYSINCLUDE_FILE_ID); |
|
macro_include_file.set_id(BOOST_WAVE_MACROINCLUDE_FILE_ID); |
|
plain_define.set_id(BOOST_WAVE_PLAIN_DEFINE_ID); |
|
macro_parameters.set_id(BOOST_WAVE_MACRO_PARAMETERS_ID); |
|
macro_definition.set_id(BOOST_WAVE_MACRO_DEFINITION_ID); |
|
undefine.set_id(BOOST_WAVE_UNDEFINE_ID); |
|
ppifdef.set_id(BOOST_WAVE_IFDEF_ID); |
|
ppifndef.set_id(BOOST_WAVE_IFNDEF_ID); |
|
ppif.set_id(BOOST_WAVE_IF_ID); |
|
ppelif.set_id(BOOST_WAVE_ELIF_ID); |
|
// ppelse.set_id(BOOST_WAVE_ELSE_ID); |
|
// ppendif.set_id(BOOST_WAVE_ENDIF_ID); |
|
ppline.set_id(BOOST_WAVE_LINE_ID); |
|
pperror.set_id(BOOST_WAVE_ERROR_ID); |
|
ppwarning.set_id(BOOST_WAVE_WARNING_ID); |
|
pppragma.set_id(BOOST_WAVE_PRAGMA_ID); |
|
illformed.set_id(BOOST_WAVE_ILLFORMED_ID); |
|
ppsp.set_id(BOOST_WAVE_PPSPACE_ID); |
|
ppqualifiedname.set_id(BOOST_WAVE_PPQUALIFIEDNAME_ID); |
|
#if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0 |
|
ppregion.set_id(BOOST_WAVE_REGION_ID); |
|
ppendregion.set_id(BOOST_WAVE_ENDREGION_ID); |
|
#endif |
|
|
|
#if BOOST_WAVE_DUMP_PARSE_TREE != 0 |
|
self.map_rule_id_to_name.init_rule_id_to_name_map(self); |
|
#endif |
|
|
|
// 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 |
|
= ( plain_define |
|
// | include_file |
|
// | system_include_file |
|
| ppif |
|
| ppelif |
|
| ppifndef |
|
| ppifdef |
|
| undefine |
|
// | ppelse |
|
| macro_include_file |
|
| ppline |
|
| pppragma |
|
| pperror |
|
| ppwarning |
|
// | ppendif |
|
#if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0 |
|
| ppregion |
|
| ppendregion |
|
#endif |
|
| illformed |
|
) |
|
>> eol_tokens |
|
[ store_found_eoltokens_type(self.found_eoltokens) ] |
|
// In parser debug mode it is useful not to flush the underlying stream |
|
// to allow its investigation in the debugger and to see the correct |
|
// output in the printed debug log.. |
|
// Note: this may break the parser, though. |
|
#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) && |
|
; |
|
|
|
// // #include ... |
|
// include_file // include "..." |
|
// = ch_p(T_PP_QHEADER) |
|
// [ store_found_directive_type(self.found_directive) ] |
|
// #if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0 |
|
// | ch_p(T_PP_QHEADER_NEXT) |
|
// [ store_found_directive_type(self.found_directive) ] |
|
// #endif |
|
// ; |
|
|
|
// system_include_file // include <...> |
|
// = ch_p(T_PP_HHEADER) |
|
// [ store_found_directive_type(self.found_directive) ] |
|
// #if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0 |
|
// | ch_p(T_PP_HHEADER_NEXT) |
|
// [ store_found_directive_type(self.found_directive) ] |
|
// #endif |
|
// ; |
|
|
|
macro_include_file // include ...anything else... |
|
= no_node_d |
|
[ |
|
ch_p(T_PP_INCLUDE) |
|
[ store_found_directive_type(self.found_directive) ] |
|
#if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0 |
|
| ch_p(T_PP_INCLUDE_NEXT) |
|
[ store_found_directive_type(self.found_directive) ] |
|
#endif |
|
] |
|
>> *( 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_type(self.found_directive) ] |
|
>> +ppsp |
|
] |
|
>> ( ch_p(T_IDENTIFIER) |
|
| pattern_p(KeywordTokenType, |
|
TokenTypeMask|PPTokenFlag) |
|
| pattern_p(OperatorTokenType|AltExtTokenType, |
|
ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc. |
|
| pattern_p(BoolLiteralTokenType, |
|
TokenTypeMask|PPTokenFlag) // true/false |
|
) |
|
>> ( ( no_node_d[eps_p(ch_p(T_LEFTPAREN))] |
|
>> macro_parameters |
|
>> !macro_definition |
|
) |
|
| !( no_node_d[+ppsp] |
|
>> 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|PPTokenFlag) |
|
| pattern_p(OperatorTokenType|AltExtTokenType, |
|
ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc. |
|
| pattern_p(BoolLiteralTokenType, |
|
TokenTypeMask|PPTokenFlag) // true/false |
|
#if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0 |
|
| ch_p(T_ELLIPSIS) |
|
#endif |
|
), |
|
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_type(self.found_directive) ] |
|
>> +ppsp |
|
] |
|
>> ( ch_p(T_IDENTIFIER) |
|
| pattern_p(KeywordTokenType, |
|
TokenTypeMask|PPTokenFlag) |
|
| pattern_p(OperatorTokenType|AltExtTokenType, |
|
ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc. |
|
| pattern_p(BoolLiteralTokenType, |
|
TokenTypeMask|PPTokenFlag) // true/false |
|
) |
|
; |
|
|
|
// #ifdef et.al. |
|
ppifdef |
|
= no_node_d |
|
[ |
|
ch_p(T_PP_IFDEF) |
|
[ store_found_directive_type(self.found_directive) ] |
|
>> +ppsp |
|
] |
|
>> ppqualifiedname |
|
; |
|
|
|
ppifndef |
|
= no_node_d |
|
[ |
|
ch_p(T_PP_IFNDEF) |
|
[ store_found_directive_type(self.found_directive) ] |
|
>> +ppsp |
|
] |
|
>> ppqualifiedname |
|
; |
|
|
|
ppif |
|
= no_node_d |
|
[ |
|
ch_p(T_PP_IF) |
|
[ store_found_directive_type(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_type(self.found_directive) ] |
|
// ] |
|
// ; |
|
|
|
ppelif |
|
= no_node_d |
|
[ |
|
ch_p(T_PP_ELIF) |
|
[ store_found_directive_type(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_type(self.found_directive) ] |
|
// ] |
|
// ; |
|
|
|
// #line ... |
|
ppline |
|
= no_node_d |
|
[ |
|
ch_p(T_PP_LINE) |
|
[ store_found_directive_type(self.found_directive) ] |
|
>> *ppsp |
|
] |
|
>> +( anychar_p - |
|
(ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) |
|
) |
|
; |
|
|
|
#if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0 |
|
// #region ... |
|
ppregion |
|
= no_node_d |
|
[ |
|
ch_p(T_MSEXT_PP_REGION) |
|
[ store_found_directive_type(self.found_directive) ] |
|
>> +ppsp |
|
] |
|
>> ppqualifiedname |
|
; |
|
|
|
// #endregion |
|
ppendregion |
|
= no_node_d |
|
[ |
|
ch_p(T_MSEXT_PP_ENDREGION) |
|
[ store_found_directive_type(self.found_directive) ] |
|
] |
|
; |
|
#endif |
|
|
|
// # something else (ill formed preprocessor directive) |
|
illformed // for error reporting |
|
= no_node_d |
|
[ |
|
pattern_p(T_POUND, MainTokenMask) |
|
>> *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_type(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_type(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_type(self.found_directive) ] |
|
] |
|
>> *( anychar_p - |
|
(ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF)) |
|
) |
|
; |
|
|
|
ppqualifiedname |
|
= no_node_d[*ppsp] |
|
>> ( ch_p(T_IDENTIFIER) |
|
| pattern_p(KeywordTokenType, |
|
TokenTypeMask|PPTokenFlag) |
|
| pattern_p(OperatorTokenType|AltExtTokenType, |
|
ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc. |
|
| pattern_p(BoolLiteralTokenType, |
|
TokenTypeMask|PPTokenFlag) // true/false |
|
) |
|
; |
|
|
|
// 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 |
|
[ |
|
*( ch_p(T_SPACE) |
|
| ch_p(T_CCOMMENT) |
|
) |
|
>> ( ch_p(T_NEWLINE) |
|
| ch_p(T_CPPCOMMENT) |
|
| ch_p(T_EOF) |
|
[ store_found_eof_type(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); |
|
BOOST_SPIRIT_DEBUG_TRACE_RULE(ppqualifiedname, TRACE_CPP_GRAMMAR); |
|
#if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0 |
|
BOOST_SPIRIT_DEBUG_TRACE_RULE(ppregion, TRACE_CPP_GRAMMAR); |
|
BOOST_SPIRIT_DEBUG_TRACE_RULE(ppendregion, TRACE_CPP_GRAMMAR); |
|
#endif |
|
} |
|
|
|
// start rule of this grammar |
|
rule_type const& start() const |
|
{ return pp_statement; } |
|
}; |
|
|
|
bool &found_eof; |
|
TokenT &found_directive; |
|
ContainerT &found_eoltokens; |
|
|
|
cpp_grammar(bool &found_eof_, TokenT &found_directive_, |
|
ContainerT &found_eoltokens_) |
|
: found_eof(found_eof_), |
|
found_directive(found_directive_), |
|
found_eoltokens(found_eoltokens_) |
|
{ |
|
BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(*this, "cpp_grammar", |
|
TRACE_CPP_GRAMMAR); |
|
} |
|
|
|
#if BOOST_WAVE_DUMP_PARSE_TREE != 0 |
|
// helper function and data to get readable names of the rules known to us |
|
struct map_ruleid_to_name : |
|
public std::map<boost::spirit::classic::parser_id, std::string> |
|
{ |
|
typedef std::map<boost::spirit::classic::parser_id, std::string> base_type; |
|
|
|
void init_rule_id_to_name_map(cpp_grammar const &self) |
|
{ |
|
struct { |
|
int parser_id; |
|
char const *rule_name; |
|
} |
|
init_ruleid_name_map[] = { |
|
{ BOOST_WAVE_PP_STATEMENT_ID, "pp_statement" }, |
|
// { BOOST_WAVE_INCLUDE_FILE_ID, "include_file" }, |
|
// { BOOST_WAVE_SYSINCLUDE_FILE_ID, "system_include_file" }, |
|
{ BOOST_WAVE_MACROINCLUDE_FILE_ID, "macro_include_file" }, |
|
{ BOOST_WAVE_PLAIN_DEFINE_ID, "plain_define" }, |
|
{ BOOST_WAVE_MACRO_PARAMETERS_ID, "macro_parameters" }, |
|
{ BOOST_WAVE_MACRO_DEFINITION_ID, "macro_definition" }, |
|
{ BOOST_WAVE_UNDEFINE_ID, "undefine" }, |
|
{ BOOST_WAVE_IFDEF_ID, "ppifdef" }, |
|
{ BOOST_WAVE_IFNDEF_ID, "ppifndef" }, |
|
{ BOOST_WAVE_IF_ID, "ppif" }, |
|
{ BOOST_WAVE_ELIF_ID, "ppelif" }, |
|
// { BOOST_WAVE_ELSE_ID, "ppelse" }, |
|
// { BOOST_WAVE_ENDIF_ID, "ppendif" }, |
|
{ BOOST_WAVE_LINE_ID, "ppline" }, |
|
{ BOOST_WAVE_ERROR_ID, "pperror" }, |
|
{ BOOST_WAVE_WARNING_ID, "ppwarning" }, |
|
{ BOOST_WAVE_PRAGMA_ID, "pppragma" }, |
|
{ BOOST_WAVE_ILLFORMED_ID, "illformed" }, |
|
{ BOOST_WAVE_PPSPACE_ID, "ppspace" }, |
|
{ BOOST_WAVE_PPQUALIFIEDNAME_ID, "ppqualifiedname" }, |
|
#if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0 |
|
{ BOOST_WAVE_REGION_ID, "ppregion" }, |
|
{ BOOST_WAVE_ENDREGION_ID, "ppendregion" }, |
|
#endif |
|
{ 0 } |
|
}; |
|
|
|
// initialize parser_id to rule_name map |
|
for (int i = 0; 0 != init_ruleid_name_map[i].parser_id; ++i) |
|
base_type::insert(base_type::value_type( |
|
boost::spirit::classic::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 // WAVE_DUMP_PARSE_TREE != 0 |
|
}; |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
#undef TRACE_CPP_GRAMMAR |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// Special parse function generating a parse tree using a given node_factory. |
|
// |
|
/////////////////////////////////////////////////////////////////////////////// |
|
template <typename NodeFactoryT, typename IteratorT, typename ParserT> |
|
inline boost::spirit::classic::tree_parse_info<IteratorT, NodeFactoryT> |
|
parsetree_parse(IteratorT const& first_, IteratorT const& last, |
|
boost::spirit::classic::parser<ParserT> const& p) |
|
{ |
|
using namespace boost::spirit::classic; |
|
|
|
typedef pt_match_policy<IteratorT, NodeFactoryT> pt_match_policy_type; |
|
typedef scanner_policies<iteration_policy, pt_match_policy_type> |
|
scanner_policies_type; |
|
typedef scanner<IteratorT, scanner_policies_type> scanner_type; |
|
|
|
scanner_policies_type policies; |
|
IteratorT first = first_; |
|
scanner_type scan(first, last, policies); |
|
tree_match<IteratorT, NodeFactoryT> hit = p.derived().parse(scan); |
|
return tree_parse_info<IteratorT, NodeFactoryT>( |
|
first, hit, hit && (first == last), hit.length(), hit.trees); |
|
} |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
// |
|
// The following parse function is defined here, to allow the separation of |
|
// the compilation of the cpp_grammar from the function using it. |
|
// |
|
/////////////////////////////////////////////////////////////////////////////// |
|
|
|
#if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0 |
|
#define BOOST_WAVE_GRAMMAR_GEN_INLINE |
|
#else |
|
#define BOOST_WAVE_GRAMMAR_GEN_INLINE inline |
|
#endif |
|
|
|
template <typename LexIteratorT, typename TokenContainerT> |
|
BOOST_WAVE_GRAMMAR_GEN_INLINE |
|
boost::spirit::classic::tree_parse_info< |
|
LexIteratorT, |
|
typename cpp_grammar_gen<LexIteratorT, TokenContainerT>::node_factory_type |
|
> |
|
cpp_grammar_gen<LexIteratorT, TokenContainerT>::parse_cpp_grammar ( |
|
LexIteratorT const &first, LexIteratorT const &last, |
|
position_type const &act_pos, bool &found_eof, |
|
token_type &found_directive, token_container_type &found_eoltokens) |
|
{ |
|
using namespace boost::spirit::classic; |
|
using namespace boost::wave; |
|
|
|
cpp_grammar<token_type, TokenContainerT> g(found_eof, found_directive, found_eoltokens); |
|
tree_parse_info<LexIteratorT, node_factory_type> hit = |
|
parsetree_parse<node_factory_type>(first, last, g); |
|
|
|
#if BOOST_WAVE_DUMP_PARSE_TREE != 0 |
|
if (hit.match) { |
|
tree_to_xml (BOOST_WAVE_DUMP_PARSE_TREE_OUT, hit.trees, "", |
|
g.map_rule_id_to_name, &token_type::get_token_id, |
|
&token_type::get_token_value); |
|
} |
|
#endif |
|
|
|
return hit; |
|
} |
|
|
|
#undef BOOST_WAVE_GRAMMAR_GEN_INLINE |
|
|
|
/////////////////////////////////////////////////////////////////////////////// |
|
} // namespace grammars |
|
} // namespace wave |
|
} // namespace boost |
|
|
|
// the suffix header occurs after all of the code |
|
#ifdef BOOST_HAS_ABI_HEADERS |
|
#include BOOST_ABI_SUFFIX |
|
#endif |
|
|
|
#endif // !defined(CPP_GRAMMAR_HPP_FEAEBC2E_2734_428B_A7CA_85E5A415E23E_INCLUDED)
|
|
|