cpp_grammar.hpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  1. /*=============================================================================
  2. Boost.Wave: A Standard compliant C++ preprocessor library
  3. http://www.boost.org/
  4. Copyright (c) 2001-2012 Hartmut Kaiser. Distributed under the Boost
  5. Software License, Version 1.0. (See accompanying file
  6. LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. =============================================================================*/
  8. #if !defined(BOOST_CPP_GRAMMAR_HPP_FEAEBC2E_2734_428B_A7CA_85E5A415E23E_INCLUDED)
  9. #define BOOST_CPP_GRAMMAR_HPP_FEAEBC2E_2734_428B_A7CA_85E5A415E23E_INCLUDED
  10. #include <boost/spirit/include/classic_core.hpp>
  11. #include <boost/spirit/include/classic_parse_tree.hpp>
  12. #include <boost/spirit/include/classic_parse_tree_utils.hpp>
  13. #include <boost/spirit/include/classic_confix.hpp>
  14. #include <boost/spirit/include/classic_lists.hpp>
  15. #include <boost/wave/wave_config.hpp>
  16. #include <boost/pool/pool_alloc.hpp>
  17. #if BOOST_WAVE_DUMP_PARSE_TREE != 0
  18. #include <map>
  19. #include <boost/spirit/include/classic_tree_to_xml.hpp>
  20. #endif
  21. #include <boost/wave/token_ids.hpp>
  22. #include <boost/wave/grammars/cpp_grammar_gen.hpp>
  23. #include <boost/wave/util/pattern_parser.hpp>
  24. #include <boost/wave/cpp_exceptions.hpp>
  25. // this must occur after all of the includes and before any code appears
  26. #ifdef BOOST_HAS_ABI_HEADERS
  27. #include BOOST_ABI_PREFIX
  28. #endif
  29. ///////////////////////////////////////////////////////////////////////////////
  30. namespace boost {
  31. namespace wave {
  32. namespace grammars {
  33. namespace impl {
  34. ///////////////////////////////////////////////////////////////////////////////
  35. //
  36. // store_found_eof
  37. //
  38. // The store_found_eof functor sets a given flag if the T_EOF token was
  39. // found during the parsing process
  40. //
  41. ///////////////////////////////////////////////////////////////////////////////
  42. struct store_found_eof {
  43. store_found_eof(bool &found_eof_) : found_eof(found_eof_) {}
  44. template <typename TokenT>
  45. void operator()(TokenT const &/*token*/) const
  46. {
  47. found_eof = true;
  48. }
  49. bool &found_eof;
  50. };
  51. ///////////////////////////////////////////////////////////////////////////////
  52. //
  53. // store_found_directive
  54. //
  55. // The store_found_directive functor stores the token_id of the recognized
  56. // pp directive
  57. //
  58. ///////////////////////////////////////////////////////////////////////////////
  59. template <typename TokenT>
  60. struct store_found_directive {
  61. store_found_directive(TokenT &found_directive_)
  62. : found_directive(found_directive_) {}
  63. void operator()(TokenT const &token) const
  64. {
  65. found_directive = token;
  66. }
  67. TokenT &found_directive;
  68. };
  69. ///////////////////////////////////////////////////////////////////////////////
  70. //
  71. // store_found_eoltokens
  72. //
  73. // The store_found_eoltokens functor stores the token sequence of the
  74. // line ending for a particular pp directive
  75. //
  76. ///////////////////////////////////////////////////////////////////////////////
  77. template <typename ContainerT>
  78. struct store_found_eoltokens {
  79. store_found_eoltokens(ContainerT &found_eoltokens_)
  80. : found_eoltokens(found_eoltokens_) {}
  81. template <typename IteratorT>
  82. void operator()(IteratorT const &first, IteratorT const& last) const
  83. {
  84. std::copy(first, last,
  85. std::inserter(found_eoltokens, found_eoltokens.end()));
  86. }
  87. ContainerT &found_eoltokens;
  88. };
  89. ///////////////////////////////////////////////////////////////////////////////
  90. //
  91. // flush_underlying_parser
  92. //
  93. // The flush_underlying_parser flushes the underlying
  94. // multi_pass_iterator during the normal parsing process. This is
  95. // used at certain points during the parsing process, when it is
  96. // clear, that no backtracking is needed anymore and the input
  97. // gathered so far may be discarded.
  98. //
  99. ///////////////////////////////////////////////////////////////////////////////
  100. struct flush_underlying_parser
  101. : public boost::spirit::classic::parser<flush_underlying_parser>
  102. {
  103. typedef flush_underlying_parser this_t;
  104. template <typename ScannerT>
  105. typename boost::spirit::classic::parser_result<this_t, ScannerT>::type
  106. parse(ScannerT const& scan) const
  107. {
  108. scan.first.clear_queue();
  109. return scan.empty_match();
  110. }
  111. };
  112. flush_underlying_parser const
  113. flush_underlying_parser_p = flush_underlying_parser();
  114. } // anonymous namespace
  115. ///////////////////////////////////////////////////////////////////////////////
  116. // define, whether the rule's should generate some debug output
  117. #define TRACE_CPP_GRAMMAR \
  118. bool(BOOST_SPIRIT_DEBUG_FLAGS_CPP & BOOST_SPIRIT_DEBUG_FLAGS_CPP_GRAMMAR) \
  119. /**/
  120. ///////////////////////////////////////////////////////////////////////////////
  121. // Encapsulation of the C++ preprocessor grammar.
  122. template <typename TokenT, typename ContainerT>
  123. struct cpp_grammar :
  124. public boost::spirit::classic::grammar<cpp_grammar<TokenT, ContainerT> >
  125. {
  126. typedef typename TokenT::position_type position_type;
  127. typedef cpp_grammar<TokenT, ContainerT> grammar_type;
  128. typedef impl::store_found_eof store_found_eof_type;
  129. typedef impl::store_found_directive<TokenT> store_found_directive_type;
  130. typedef impl::store_found_eoltokens<ContainerT> store_found_eoltokens_type;
  131. template <typename ScannerT>
  132. struct definition
  133. {
  134. // non-parse_tree generating rule type
  135. typedef typename ScannerT::iteration_policy_t iteration_policy_t;
  136. typedef boost::spirit::classic::match_policy match_policy_t;
  137. typedef typename ScannerT::action_policy_t action_policy_t;
  138. typedef
  139. boost::spirit::classic::scanner_policies<
  140. iteration_policy_t, match_policy_t, action_policy_t>
  141. policies_t;
  142. typedef
  143. boost::spirit::classic::scanner<typename ScannerT::iterator_t, policies_t>
  144. non_tree_scanner_t;
  145. typedef
  146. boost::spirit::classic::rule<
  147. non_tree_scanner_t, boost::spirit::classic::dynamic_parser_tag>
  148. no_tree_rule_type;
  149. // 'normal' (parse_tree generating) rule type
  150. typedef
  151. boost::spirit::classic::rule<
  152. ScannerT, boost::spirit::classic::dynamic_parser_tag>
  153. rule_type;
  154. rule_type pp_statement, macro_include_file;
  155. // rule_type include_file, system_include_file;
  156. rule_type plain_define, macro_definition, macro_parameters;
  157. rule_type undefine;
  158. rule_type ppifdef, ppifndef, ppif, ppelif;
  159. // rule_type ppelse, ppendif;
  160. rule_type ppline;
  161. rule_type pperror;
  162. rule_type ppwarning;
  163. rule_type pppragma;
  164. rule_type illformed;
  165. rule_type ppqualifiedname;
  166. rule_type eol_tokens;
  167. no_tree_rule_type ppsp;
  168. #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0
  169. rule_type ppregion;
  170. rule_type ppendregion;
  171. #endif
  172. definition(cpp_grammar const &self)
  173. {
  174. // import the spirit and cpplexer namespaces here
  175. using namespace boost::spirit::classic;
  176. using namespace boost::wave;
  177. using namespace boost::wave::util;
  178. // set the rule id's for later use
  179. pp_statement.set_id(BOOST_WAVE_PP_STATEMENT_ID);
  180. // include_file.set_id(BOOST_WAVE_INCLUDE_FILE_ID);
  181. // system_include_file.set_id(BOOST_WAVE_SYSINCLUDE_FILE_ID);
  182. macro_include_file.set_id(BOOST_WAVE_MACROINCLUDE_FILE_ID);
  183. plain_define.set_id(BOOST_WAVE_PLAIN_DEFINE_ID);
  184. macro_parameters.set_id(BOOST_WAVE_MACRO_PARAMETERS_ID);
  185. macro_definition.set_id(BOOST_WAVE_MACRO_DEFINITION_ID);
  186. undefine.set_id(BOOST_WAVE_UNDEFINE_ID);
  187. ppifdef.set_id(BOOST_WAVE_IFDEF_ID);
  188. ppifndef.set_id(BOOST_WAVE_IFNDEF_ID);
  189. ppif.set_id(BOOST_WAVE_IF_ID);
  190. ppelif.set_id(BOOST_WAVE_ELIF_ID);
  191. // ppelse.set_id(BOOST_WAVE_ELSE_ID);
  192. // ppendif.set_id(BOOST_WAVE_ENDIF_ID);
  193. ppline.set_id(BOOST_WAVE_LINE_ID);
  194. pperror.set_id(BOOST_WAVE_ERROR_ID);
  195. ppwarning.set_id(BOOST_WAVE_WARNING_ID);
  196. pppragma.set_id(BOOST_WAVE_PRAGMA_ID);
  197. illformed.set_id(BOOST_WAVE_ILLFORMED_ID);
  198. ppsp.set_id(BOOST_WAVE_PPSPACE_ID);
  199. ppqualifiedname.set_id(BOOST_WAVE_PPQUALIFIEDNAME_ID);
  200. #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0
  201. ppregion.set_id(BOOST_WAVE_REGION_ID);
  202. ppendregion.set_id(BOOST_WAVE_ENDREGION_ID);
  203. #endif
  204. #if BOOST_WAVE_DUMP_PARSE_TREE != 0
  205. self.map_rule_id_to_name.init_rule_id_to_name_map(self);
  206. #endif
  207. // recognizes preprocessor directives only
  208. // C++ standard 16.1: A preprocessing directive consists of a sequence
  209. // of preprocessing tokens. The first token in the sequence is #
  210. // preprocessing token that is either the first character in the source
  211. // file (optionally after white space containing no new-line
  212. // characters) or that follows white space containing at least one
  213. // new-line character. The last token in the sequence is the first
  214. // new-line character that follows the first token in the sequence.
  215. pp_statement
  216. = ( plain_define
  217. // | include_file
  218. // | system_include_file
  219. | ppif
  220. | ppelif
  221. | ppifndef
  222. | ppifdef
  223. | undefine
  224. // | ppelse
  225. | macro_include_file
  226. | ppline
  227. | pppragma
  228. | pperror
  229. | ppwarning
  230. // | ppendif
  231. #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0
  232. | ppregion
  233. | ppendregion
  234. #endif
  235. | illformed
  236. )
  237. >> eol_tokens
  238. [ store_found_eoltokens_type(self.found_eoltokens) ]
  239. // In parser debug mode it is useful not to flush the underlying stream
  240. // to allow its investigation in the debugger and to see the correct
  241. // output in the printed debug log..
  242. // Note: this may break the parser, though.
  243. #if !(defined(BOOST_SPIRIT_DEBUG) && \
  244. (BOOST_SPIRIT_DEBUG_FLAGS_CPP & BOOST_SPIRIT_DEBUG_FLAGS_CPP_GRAMMAR) \
  245. )
  246. >> impl::flush_underlying_parser_p
  247. #endif // !(defined(BOOST_SPIRIT_DEBUG) &&
  248. ;
  249. // // #include ...
  250. // include_file // include "..."
  251. // = ch_p(T_PP_QHEADER)
  252. // [ store_found_directive_type(self.found_directive) ]
  253. // #if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
  254. // | ch_p(T_PP_QHEADER_NEXT)
  255. // [ store_found_directive_type(self.found_directive) ]
  256. // #endif
  257. // ;
  258. // system_include_file // include <...>
  259. // = ch_p(T_PP_HHEADER)
  260. // [ store_found_directive_type(self.found_directive) ]
  261. // #if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
  262. // | ch_p(T_PP_HHEADER_NEXT)
  263. // [ store_found_directive_type(self.found_directive) ]
  264. // #endif
  265. // ;
  266. macro_include_file // include ...anything else...
  267. = no_node_d
  268. [
  269. ch_p(T_PP_INCLUDE)
  270. [ store_found_directive_type(self.found_directive) ]
  271. #if BOOST_WAVE_SUPPORT_INCLUDE_NEXT != 0
  272. | ch_p(T_PP_INCLUDE_NEXT)
  273. [ store_found_directive_type(self.found_directive) ]
  274. #endif
  275. ]
  276. >> *( anychar_p -
  277. (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
  278. )
  279. ;
  280. // #define FOO foo (with optional parameters)
  281. plain_define
  282. = no_node_d
  283. [
  284. ch_p(T_PP_DEFINE)
  285. [ store_found_directive_type(self.found_directive) ]
  286. >> +ppsp
  287. ]
  288. >> ( ch_p(T_IDENTIFIER)
  289. | pattern_p(KeywordTokenType,
  290. TokenTypeMask|PPTokenFlag)
  291. | pattern_p(OperatorTokenType|AltExtTokenType,
  292. ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc.
  293. | pattern_p(BoolLiteralTokenType,
  294. TokenTypeMask|PPTokenFlag) // true/false
  295. )
  296. >> ( ( no_node_d[eps_p(ch_p(T_LEFTPAREN))]
  297. >> macro_parameters
  298. >> !macro_definition
  299. )
  300. | !( no_node_d[+ppsp]
  301. >> macro_definition
  302. )
  303. )
  304. ;
  305. // parameter list
  306. // normal C++ mode
  307. macro_parameters
  308. = confix_p(
  309. no_node_d[ch_p(T_LEFTPAREN) >> *ppsp],
  310. !list_p(
  311. ( ch_p(T_IDENTIFIER)
  312. | pattern_p(KeywordTokenType,
  313. TokenTypeMask|PPTokenFlag)
  314. | pattern_p(OperatorTokenType|AltExtTokenType,
  315. ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc.
  316. | pattern_p(BoolLiteralTokenType,
  317. TokenTypeMask|PPTokenFlag) // true/false
  318. #if BOOST_WAVE_SUPPORT_VARIADICS_PLACEMARKERS != 0
  319. | ch_p(T_ELLIPSIS)
  320. #endif
  321. ),
  322. no_node_d[*ppsp >> ch_p(T_COMMA) >> *ppsp]
  323. ),
  324. no_node_d[*ppsp >> ch_p(T_RIGHTPAREN)]
  325. )
  326. ;
  327. // macro body (anything left until eol)
  328. macro_definition
  329. = no_node_d[*ppsp]
  330. >> *( anychar_p -
  331. (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
  332. )
  333. ;
  334. // #undef FOO
  335. undefine
  336. = no_node_d
  337. [
  338. ch_p(T_PP_UNDEF)
  339. [ store_found_directive_type(self.found_directive) ]
  340. >> +ppsp
  341. ]
  342. >> ( ch_p(T_IDENTIFIER)
  343. | pattern_p(KeywordTokenType,
  344. TokenTypeMask|PPTokenFlag)
  345. | pattern_p(OperatorTokenType|AltExtTokenType,
  346. ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc.
  347. | pattern_p(BoolLiteralTokenType,
  348. TokenTypeMask|PPTokenFlag) // true/false
  349. )
  350. ;
  351. // #ifdef et.al.
  352. ppifdef
  353. = no_node_d
  354. [
  355. ch_p(T_PP_IFDEF)
  356. [ store_found_directive_type(self.found_directive) ]
  357. >> +ppsp
  358. ]
  359. >> ppqualifiedname
  360. ;
  361. ppifndef
  362. = no_node_d
  363. [
  364. ch_p(T_PP_IFNDEF)
  365. [ store_found_directive_type(self.found_directive) ]
  366. >> +ppsp
  367. ]
  368. >> ppqualifiedname
  369. ;
  370. ppif
  371. = no_node_d
  372. [
  373. ch_p(T_PP_IF)
  374. [ store_found_directive_type(self.found_directive) ]
  375. // >> *ppsp
  376. ]
  377. >> +( anychar_p -
  378. (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
  379. )
  380. ;
  381. // ppelse
  382. // = no_node_d
  383. // [
  384. // ch_p(T_PP_ELSE)
  385. // [ store_found_directive_type(self.found_directive) ]
  386. // ]
  387. // ;
  388. ppelif
  389. = no_node_d
  390. [
  391. ch_p(T_PP_ELIF)
  392. [ store_found_directive_type(self.found_directive) ]
  393. // >> *ppsp
  394. ]
  395. >> +( anychar_p -
  396. (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
  397. )
  398. ;
  399. // ppendif
  400. // = no_node_d
  401. // [
  402. // ch_p(T_PP_ENDIF)
  403. // [ store_found_directive_type(self.found_directive) ]
  404. // ]
  405. // ;
  406. // #line ...
  407. ppline
  408. = no_node_d
  409. [
  410. ch_p(T_PP_LINE)
  411. [ store_found_directive_type(self.found_directive) ]
  412. >> *ppsp
  413. ]
  414. >> +( anychar_p -
  415. (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
  416. )
  417. ;
  418. #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0
  419. // #region ...
  420. ppregion
  421. = no_node_d
  422. [
  423. ch_p(T_MSEXT_PP_REGION)
  424. [ store_found_directive_type(self.found_directive) ]
  425. >> +ppsp
  426. ]
  427. >> ppqualifiedname
  428. ;
  429. // #endregion
  430. ppendregion
  431. = no_node_d
  432. [
  433. ch_p(T_MSEXT_PP_ENDREGION)
  434. [ store_found_directive_type(self.found_directive) ]
  435. ]
  436. ;
  437. #endif
  438. // # something else (ill formed preprocessor directive)
  439. illformed // for error reporting
  440. = no_node_d
  441. [
  442. pattern_p(T_POUND, MainTokenMask)
  443. >> *ppsp
  444. ]
  445. >> ( anychar_p -
  446. (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
  447. )
  448. >> no_node_d
  449. [
  450. *( anychar_p -
  451. (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
  452. )
  453. ]
  454. ;
  455. // #error
  456. pperror
  457. = no_node_d
  458. [
  459. ch_p(T_PP_ERROR)
  460. [ store_found_directive_type(self.found_directive) ]
  461. >> *ppsp
  462. ]
  463. >> *( anychar_p -
  464. (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
  465. )
  466. ;
  467. // #warning
  468. ppwarning
  469. = no_node_d
  470. [
  471. ch_p(T_PP_WARNING)
  472. [ store_found_directive_type(self.found_directive) ]
  473. >> *ppsp
  474. ]
  475. >> *( anychar_p -
  476. (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
  477. )
  478. ;
  479. // #pragma ...
  480. pppragma
  481. = no_node_d
  482. [
  483. ch_p(T_PP_PRAGMA)
  484. [ store_found_directive_type(self.found_directive) ]
  485. ]
  486. >> *( anychar_p -
  487. (ch_p(T_NEWLINE) | ch_p(T_CPPCOMMENT) | ch_p(T_EOF))
  488. )
  489. ;
  490. ppqualifiedname
  491. = no_node_d[*ppsp]
  492. >> ( ch_p(T_IDENTIFIER)
  493. | pattern_p(KeywordTokenType,
  494. TokenTypeMask|PPTokenFlag)
  495. | pattern_p(OperatorTokenType|AltExtTokenType,
  496. ExtTokenTypeMask|PPTokenFlag) // and, bit_and etc.
  497. | pattern_p(BoolLiteralTokenType,
  498. TokenTypeMask|PPTokenFlag) // true/false
  499. )
  500. ;
  501. // auxiliary helper rules
  502. ppsp // valid space in a line with a preprocessor directive
  503. = ch_p(T_SPACE) | ch_p(T_CCOMMENT)
  504. ;
  505. // end of line tokens
  506. eol_tokens
  507. = no_node_d
  508. [
  509. *( ch_p(T_SPACE)
  510. | ch_p(T_CCOMMENT)
  511. )
  512. >> ( ch_p(T_NEWLINE)
  513. | ch_p(T_CPPCOMMENT)
  514. | ch_p(T_EOF)
  515. [ store_found_eof_type(self.found_eof) ]
  516. )
  517. ]
  518. ;
  519. BOOST_SPIRIT_DEBUG_TRACE_RULE(pp_statement, TRACE_CPP_GRAMMAR);
  520. // BOOST_SPIRIT_DEBUG_TRACE_RULE(include_file, TRACE_CPP_GRAMMAR);
  521. // BOOST_SPIRIT_DEBUG_TRACE_RULE(system_include_file, TRACE_CPP_GRAMMAR);
  522. BOOST_SPIRIT_DEBUG_TRACE_RULE(macro_include_file, TRACE_CPP_GRAMMAR);
  523. BOOST_SPIRIT_DEBUG_TRACE_RULE(plain_define, TRACE_CPP_GRAMMAR);
  524. BOOST_SPIRIT_DEBUG_TRACE_RULE(macro_definition, TRACE_CPP_GRAMMAR);
  525. BOOST_SPIRIT_DEBUG_TRACE_RULE(macro_parameters, TRACE_CPP_GRAMMAR);
  526. BOOST_SPIRIT_DEBUG_TRACE_RULE(undefine, TRACE_CPP_GRAMMAR);
  527. BOOST_SPIRIT_DEBUG_TRACE_RULE(ppifdef, TRACE_CPP_GRAMMAR);
  528. BOOST_SPIRIT_DEBUG_TRACE_RULE(ppifndef, TRACE_CPP_GRAMMAR);
  529. BOOST_SPIRIT_DEBUG_TRACE_RULE(ppif, TRACE_CPP_GRAMMAR);
  530. // BOOST_SPIRIT_DEBUG_TRACE_RULE(ppelse, TRACE_CPP_GRAMMAR);
  531. // BOOST_SPIRIT_DEBUG_TRACE_RULE(ppelif, TRACE_CPP_GRAMMAR);
  532. BOOST_SPIRIT_DEBUG_TRACE_RULE(ppendif, TRACE_CPP_GRAMMAR);
  533. BOOST_SPIRIT_DEBUG_TRACE_RULE(ppline, TRACE_CPP_GRAMMAR);
  534. BOOST_SPIRIT_DEBUG_TRACE_RULE(pperror, TRACE_CPP_GRAMMAR);
  535. BOOST_SPIRIT_DEBUG_TRACE_RULE(ppwarning, TRACE_CPP_GRAMMAR);
  536. BOOST_SPIRIT_DEBUG_TRACE_RULE(illformed, TRACE_CPP_GRAMMAR);
  537. BOOST_SPIRIT_DEBUG_TRACE_RULE(ppsp, TRACE_CPP_GRAMMAR);
  538. BOOST_SPIRIT_DEBUG_TRACE_RULE(ppqualifiedname, TRACE_CPP_GRAMMAR);
  539. #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0
  540. BOOST_SPIRIT_DEBUG_TRACE_RULE(ppregion, TRACE_CPP_GRAMMAR);
  541. BOOST_SPIRIT_DEBUG_TRACE_RULE(ppendregion, TRACE_CPP_GRAMMAR);
  542. #endif
  543. }
  544. // start rule of this grammar
  545. rule_type const& start() const
  546. { return pp_statement; }
  547. };
  548. bool &found_eof;
  549. TokenT &found_directive;
  550. ContainerT &found_eoltokens;
  551. cpp_grammar(bool &found_eof_, TokenT &found_directive_,
  552. ContainerT &found_eoltokens_)
  553. : found_eof(found_eof_),
  554. found_directive(found_directive_),
  555. found_eoltokens(found_eoltokens_)
  556. {
  557. BOOST_SPIRIT_DEBUG_TRACE_GRAMMAR_NAME(*this, "cpp_grammar",
  558. TRACE_CPP_GRAMMAR);
  559. }
  560. #if BOOST_WAVE_DUMP_PARSE_TREE != 0
  561. // helper function and data to get readable names of the rules known to us
  562. struct map_ruleid_to_name :
  563. public std::map<boost::spirit::classic::parser_id, std::string>
  564. {
  565. typedef std::map<boost::spirit::classic::parser_id, std::string> base_type;
  566. void init_rule_id_to_name_map(cpp_grammar const &self)
  567. {
  568. struct {
  569. int parser_id;
  570. char const *rule_name;
  571. }
  572. init_ruleid_name_map[] = {
  573. { BOOST_WAVE_PP_STATEMENT_ID, "pp_statement" },
  574. // { BOOST_WAVE_INCLUDE_FILE_ID, "include_file" },
  575. // { BOOST_WAVE_SYSINCLUDE_FILE_ID, "system_include_file" },
  576. { BOOST_WAVE_MACROINCLUDE_FILE_ID, "macro_include_file" },
  577. { BOOST_WAVE_PLAIN_DEFINE_ID, "plain_define" },
  578. { BOOST_WAVE_MACRO_PARAMETERS_ID, "macro_parameters" },
  579. { BOOST_WAVE_MACRO_DEFINITION_ID, "macro_definition" },
  580. { BOOST_WAVE_UNDEFINE_ID, "undefine" },
  581. { BOOST_WAVE_IFDEF_ID, "ppifdef" },
  582. { BOOST_WAVE_IFNDEF_ID, "ppifndef" },
  583. { BOOST_WAVE_IF_ID, "ppif" },
  584. { BOOST_WAVE_ELIF_ID, "ppelif" },
  585. // { BOOST_WAVE_ELSE_ID, "ppelse" },
  586. // { BOOST_WAVE_ENDIF_ID, "ppendif" },
  587. { BOOST_WAVE_LINE_ID, "ppline" },
  588. { BOOST_WAVE_ERROR_ID, "pperror" },
  589. { BOOST_WAVE_WARNING_ID, "ppwarning" },
  590. { BOOST_WAVE_PRAGMA_ID, "pppragma" },
  591. { BOOST_WAVE_ILLFORMED_ID, "illformed" },
  592. { BOOST_WAVE_PPSPACE_ID, "ppspace" },
  593. { BOOST_WAVE_PPQUALIFIEDNAME_ID, "ppqualifiedname" },
  594. #if BOOST_WAVE_SUPPORT_MS_EXTENSIONS != 0
  595. { BOOST_WAVE_REGION_ID, "ppregion" },
  596. { BOOST_WAVE_ENDREGION_ID, "ppendregion" },
  597. #endif
  598. { 0 }
  599. };
  600. // initialize parser_id to rule_name map
  601. for (int i = 0; 0 != init_ruleid_name_map[i].parser_id; ++i)
  602. base_type::insert(base_type::value_type(
  603. boost::spirit::classic::parser_id(init_ruleid_name_map[i].parser_id),
  604. std::string(init_ruleid_name_map[i].rule_name))
  605. );
  606. }
  607. };
  608. mutable map_ruleid_to_name map_rule_id_to_name;
  609. #endif // WAVE_DUMP_PARSE_TREE != 0
  610. };
  611. ///////////////////////////////////////////////////////////////////////////////
  612. #undef TRACE_CPP_GRAMMAR
  613. ///////////////////////////////////////////////////////////////////////////////
  614. //
  615. // Special parse function generating a parse tree using a given node_factory.
  616. //
  617. ///////////////////////////////////////////////////////////////////////////////
  618. template <typename NodeFactoryT, typename IteratorT, typename ParserT>
  619. inline boost::spirit::classic::tree_parse_info<IteratorT, NodeFactoryT>
  620. parsetree_parse(IteratorT const& first_, IteratorT const& last,
  621. boost::spirit::classic::parser<ParserT> const& p)
  622. {
  623. using namespace boost::spirit::classic;
  624. typedef pt_match_policy<IteratorT, NodeFactoryT> pt_match_policy_type;
  625. typedef scanner_policies<iteration_policy, pt_match_policy_type>
  626. scanner_policies_type;
  627. typedef scanner<IteratorT, scanner_policies_type> scanner_type;
  628. scanner_policies_type policies;
  629. IteratorT first = first_;
  630. scanner_type scan(first, last, policies);
  631. tree_match<IteratorT, NodeFactoryT> hit = p.derived().parse(scan);
  632. return tree_parse_info<IteratorT, NodeFactoryT>(
  633. first, hit, hit && (first == last), hit.length(), hit.trees);
  634. }
  635. ///////////////////////////////////////////////////////////////////////////////
  636. //
  637. // The following parse function is defined here, to allow the separation of
  638. // the compilation of the cpp_grammar from the function using it.
  639. //
  640. ///////////////////////////////////////////////////////////////////////////////
  641. #if BOOST_WAVE_SEPARATE_GRAMMAR_INSTANTIATION != 0
  642. #define BOOST_WAVE_GRAMMAR_GEN_INLINE
  643. #else
  644. #define BOOST_WAVE_GRAMMAR_GEN_INLINE inline
  645. #endif
  646. template <typename LexIteratorT, typename TokenContainerT>
  647. BOOST_WAVE_GRAMMAR_GEN_INLINE
  648. boost::spirit::classic::tree_parse_info<
  649. LexIteratorT,
  650. typename cpp_grammar_gen<LexIteratorT, TokenContainerT>::node_factory_type
  651. >
  652. cpp_grammar_gen<LexIteratorT, TokenContainerT>::parse_cpp_grammar (
  653. LexIteratorT const &first, LexIteratorT const &last,
  654. position_type const &act_pos, bool &found_eof,
  655. token_type &found_directive, token_container_type &found_eoltokens)
  656. {
  657. using namespace boost::spirit::classic;
  658. using namespace boost::wave;
  659. cpp_grammar<token_type, TokenContainerT> g(found_eof, found_directive, found_eoltokens);
  660. tree_parse_info<LexIteratorT, node_factory_type> hit =
  661. parsetree_parse<node_factory_type>(first, last, g);
  662. #if BOOST_WAVE_DUMP_PARSE_TREE != 0
  663. if (hit.match) {
  664. tree_to_xml (BOOST_WAVE_DUMP_PARSE_TREE_OUT, hit.trees, "",
  665. g.map_rule_id_to_name, &token_type::get_token_id,
  666. &token_type::get_token_value);
  667. }
  668. #endif
  669. return hit;
  670. }
  671. #undef BOOST_WAVE_GRAMMAR_GEN_INLINE
  672. ///////////////////////////////////////////////////////////////////////////////
  673. } // namespace grammars
  674. } // namespace wave
  675. } // namespace boost
  676. // the suffix header occurs after all of the code
  677. #ifdef BOOST_HAS_ABI_HEADERS
  678. #include BOOST_ABI_SUFFIX
  679. #endif
  680. #endif // !defined(BOOST_CPP_GRAMMAR_HPP_FEAEBC2E_2734_428B_A7CA_85E5A415E23E_INCLUDED)