📄 cpp_grammar.hpp
字号:
/*============================================================================= Boost.Wave: A Standard compliant C++ preprocessor library http://www.boost.org/ Copyright (c) 2001-2008 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) | pattern_p(OperatorTokenType|AltExtTokenType, ExtTokenTypeMask) // and, bit_and etc. | pattern_p(BoolLiteralTokenType, TokenTypeMask) // 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) | pattern_p(OperatorTokenType|AltExtTokenType, ExtTokenTypeMask) // and, bit_and etc. | pattern_p(BoolLiteralTokenType, TokenTypeMask) // 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -