rule_parser.hpp 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142
  1. /*==============================================================================
  2. Copyright (c) 2006 Tobias Schwinger
  3. http://spirit.sourceforge.net/
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. ==============================================================================*/
  7. // The comment below contains a unnamed 'namespace {', which is flagged by the
  8. // Boost inspect tool as a violation of common C++ programming rules. Since it's
  9. // in a comment, well, we switch it off :-P
  10. // boostinspect:nounnamed
  11. //
  12. // About:
  13. // =====
  14. //
  15. // Using a typeof operator or Boost.Typeof to automatically set the type of
  16. // variables (as done in the Spirit example demonstrating typeof) is by far not
  17. // all we can do to tighten up our grammars as there are some significant
  18. // drawbacks of this approach:
  19. // - the types complexity scales with the complexity of the grammar (sooner or
  20. // later hitting the limits of the compiler),
  21. // - recursive grammars are not possible, and
  22. // - all parser objects are embedded by value.
  23. //
  24. // The Spirit documentation therefore recommends creating custom parser classes
  25. // (derived from the a sub_grammar template):
  26. //
  27. // http://www.boost.org/libs/spirit/doc/techniques.html#no_rules
  28. // http://www.boost.org/libs/spirit/doc/techniques.html#typeof
  29. //
  30. // In practice manually applying this technique leads to rather lengthy code and
  31. // overthis requires the user to have a solid understanding of Spirit details.
  32. //
  33. // Here is a generalized, macro-based approach to easily create typeof-based
  34. // grammars that can be recursive and arbitrarily complex.
  35. //
  36. //
  37. // Quick manual:
  38. // ============
  39. //
  40. // 1. Setup
  41. //
  42. // Before the rule parser macro (the protagonist of the facility) can be used
  43. // the user must define the macro BOOST_SPIRIT__NAMESPACE (note the double
  44. // underscore characeter) and setup a registration group for Boost.Typeof.
  45. //
  46. // Examples:
  47. //
  48. // // should come after regular #includeS
  49. // #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
  50. //
  51. // // [...]
  52. //
  53. // #define BOOST_SPIRIT__NAMESPACE (2,(my_project, my_module))
  54. // // | | +- outer +- inner
  55. // // ! space ! -+ | namespace namespace
  56. // // |
  57. // // +--- number of nested namespaces
  58. //
  59. // namespace my_project { namespace my_module {
  60. //
  61. // // [...]
  62. //
  63. // ---
  64. //
  65. // // should come after regular #includeS
  66. // #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
  67. //
  68. // // [...]
  69. //
  70. // #define BOOST_SPIRIT__NAMESPACE (2,(my_project, (anonymous) ))
  71. //
  72. // namespace my_project { namespace {
  73. //
  74. // // [...]
  75. //
  76. // ---
  77. //
  78. // // should come after regular #includeS
  79. // #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
  80. //
  81. // // [...]
  82. //
  83. //
  84. // #define BOOST_SPIRIT__NAMESPACE -
  85. // // we're working at root namespace
  86. //
  87. //
  88. // Why do I have to do this?
  89. //
  90. // Boost.Typeof needs to assign a unique ID for each registration. This ID is
  91. // created composed of the line number and the registration group. The
  92. // facility performs Typeof registration and thus requires the source file to
  93. // have its own registration group. Further Boost.Typeof requires registration
  94. // to happen at root namespace so we have to close and reopen the namespace
  95. // we're in.
  96. //
  97. //
  98. // 2. The rule parser macro
  99. //
  100. // A simple rule parser definition looks like that:
  101. //
  102. // // we're at namespace scope here
  103. //
  104. // // Skip parser for C/C++ comments and whitespace
  105. // BOOST_SPIRIT_RULE_PARSER(skipper,
  106. // -,-,-,
  107. //
  108. // +( confix_p("//",*anychar_p,eol_p)
  109. // | confix_p("/*",*anychar_p,"*/")
  110. // | space_p
  111. // )
  112. // )
  113. //
  114. // Now we can use 'skipper' in other Spirit expressions.
  115. //
  116. // The code above creates a parser (template) class 'skpper_t' and (in this
  117. // case, because there are no parameters) a static const instance 'skipper' of
  118. // that class. The class is automatically registered with Boost.Typeof. The type
  119. // name our parser is skipper_t here.
  120. //
  121. //
  122. // 2.1. Parametrized rule parsers
  123. //
  124. // Rule parser definitions can have parameters.
  125. //
  126. // Parameters are passed to the BOOST_SPIRIT_RULE_PARSER macro as its second
  127. // argument (just pass '-' if there are no parameters) with the following
  128. // format:
  129. //
  130. // (N,( param1,param2, / ... / paramN ))
  131. // +-- number of parameters
  132. //
  133. // Example of a whole rule parser:
  134. //
  135. // BOOST_SPIRIT_RULE_PARSER(new_name,
  136. // (1,( symbol_table )),-,-,
  137. //
  138. // lexeme_d[ (alpha_p >> *alnum_p)[ symbol_table.add ] ]
  139. // )
  140. //
  141. // The expression 'new_name(my_symbols)' parses a string literal and adds it to
  142. // the symbol table 'my_symbols'.
  143. //
  144. // The rule parser macro creates a function template as called 'new_name' that
  145. // takes one parameter of deduced reference type and returns a specialization of
  146. // 'new_name_t' in this case.
  147. //
  148. // Since parsers that require to be fast and lightweight often also require to
  149. // be reentrant, it's quite common to pass in some semantic controller (the
  150. // symbol table in the example above).
  151. // However, parameters are templated so they can be anything (including parsers
  152. // of course) so refactoring tasks can be abstracted with rule parsers as well.
  153. //
  154. // BOOST_SPIRIT_RULE_PARSER(enumeration_parser,
  155. // (2,( element_parser, delimiter_parser )),-,-,
  156. //
  157. // element_parser >> *(delimiter_parser >> element_parser)
  158. // )
  159. //
  160. // The expression 'enumeration_parser(int_p[ some_action ], ',')' creates a
  161. // parser for a comma-separated list of integers.
  162. //
  163. //
  164. // 2.2. Rule parsrs and semantic actions
  165. //
  166. // While semantic actions can be globally attached to a rule parser or passed
  167. // to a parametrized rule parser as (part of) an argument, even more control is
  168. // possible by using action placeholders. E.g:
  169. //
  170. // BOOST_SPIRIT_ACTION_PLACEHOLDER(int_action)
  171. //
  172. // BOOST_SPIRIT_RULE_PARSER(int_list,
  173. // -,(1,( int_action )),-,
  174. //
  175. // int_p[ int_action ] >> *(',' >> int_p[ int_action ])
  176. // )
  177. //
  178. // The expression 'int_list[ my_action ]' parses a comma separated list of
  179. // integers and calls 'my_action' for every integer parsed therein.
  180. //
  181. // Of course multiple actions can be attached to one placeholder as usual (in
  182. // this case 'int_list[ my_action1 ][ my_action2 ] would call two actions).
  183. //
  184. // Further there can be multiple action placeholders for a single rule parser:
  185. //
  186. // BOOST_SPIRIT_ACTION_PLACEHOLDER(feed_int)
  187. // BOOST_SPIRIT_ACTION_PLACEHOLDER(next_int)
  188. //
  189. // BOOST_SPIRIT_RULE_PARSER(int_list,
  190. // -,(2,( feed_int, next_int )),-,
  191. //
  192. // int_p[ feed_int ] >> *(',' >> int_p[ next_int ][ feed_int ])
  193. // )
  194. //
  195. // The expression 'int_list[ (feed_int = my_action1), (next_int = my_action2) ]'
  196. // creates a parser for a comma separated list of integers with the actions
  197. // attached appropriately.
  198. //
  199. // int_list[ feed_int = my_action1,my_action2, next_int = my_action3 ]
  200. //
  201. // works too (in this case the action placeholder 'feed_int' has two actions
  202. // attached to it).
  203. //
  204. // You can both override and append actions associated with an action
  205. // placeholder:
  206. //
  207. // var = int_list[ feed_int = my_action1, next_int = my_action2 ]
  208. //
  209. // // [...]
  210. //
  211. // ... var[ feed_int = another_action ]
  212. // // 'another_action' overrides the actions previously attached to 'feed_int'
  213. //
  214. // ... var[ next_int += another_action ]
  215. // // 'another_action' is appended to the list of actions attached to
  216. // // 'next_int'
  217. //
  218. // Action placeholders are not entirely for free -- they add to the size and the
  219. // initialization time of the rule parser. However, the impact on an already
  220. // initialized rule parser instance should be quite small.
  221. //
  222. //
  223. // 2.3. Member variables
  224. //
  225. // You can add member variables to the rule parser class using the third
  226. // parameter of the rule parser macro:
  227. //
  228. // BOOST_SPIRIT_RULE_PARSER( calc,
  229. // -,
  230. // -,
  231. // (3,( ((subrule<0>),expression,()),
  232. // ((subrule<1>),term,()),
  233. // ((subrule<2>),factor,() )) ),
  234. //
  235. // // [...]
  236. //
  237. // adds three subrules to the rule parser.
  238. // Each parameter must have the following type to allow commas to be handled
  239. // safely from within the preprocessing code:
  240. //
  241. // ((type)),name,(constructor argument(s)))
  242. //
  243. //
  244. // 2.4. The opaque rule parser
  245. //
  246. // Rule parsers usually are templates. Building large grammars pushes the
  247. // compiler really hard (and eventually to its limits) because of the
  248. // metafunction complexity involved.
  249. // If a rule parser without parameters and action placeholders is defined, a
  250. // non-template class is created. Non-templated rule parsers can also be created
  251. // explicitly by using BOOST_SPIRIT_OPAQUE_RULE_PARSER.
  252. // Opaque rule parsers can have parameters and member variables (note: no action
  253. // placeholders are possible). The parameters of an opaque rule parsers are
  254. // strictly typed, e.g:
  255. //
  256. // BOOST_SPIRIT_OPAQUE_RULE_PARSER(new_identifier,
  257. // (1,( ((my_symbol_table_t &),symbol_table) ))
  258. // ,-,
  259. // (alpha_p >> *alnum_p) [ symbol_table.add ]
  260. // )
  261. //
  262. // Note it's also possible to have opaque rule parsers accept parameters of
  263. // non-const reference types which is not possible with regular rule parsers.
  264. //
  265. //
  266. // 3. Utilities for by-reference embedding
  267. //
  268. // When using parsers mutiple times or recursively it can be helpful to embed
  269. // them by-reference into the final parser expression.
  270. // For this purpose the library provides a wrapper template 'parser_reference'.
  271. // There is also a function template to create a wrapped parser which can deduce
  272. // the parser's type from its argument.
  273. //
  274. // --- --- - - --- - - --- - - - - --- - - - - - - - - - - - - - - - - - - - - -
  275. #if !defined(BOOST_SPIRIT_UTILITY_RULE_PARSER_HPP_INCLUDED)
  276. # define BOOST_SPIRIT_UTILITY_RULE_PARSER_HPP_INCLUDED
  277. //==============================================================================
  278. // Dependencies
  279. //==============================================================================
  280. # include <boost/config.hpp>
  281. # include <boost/detail/workaround.hpp>
  282. # include <boost/call_traits.hpp>
  283. # include <boost/typeof/typeof.hpp>
  284. # include <boost/spirit/home/classic/namespace.hpp>
  285. # include <boost/spirit/home/classic/core/parser.hpp>
  286. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  287. # include <boost/preprocessor/cat.hpp>
  288. # include <boost/preprocessor/seq/seq.hpp>
  289. # include <boost/preprocessor/seq/for_each_i.hpp>
  290. # include <boost/preprocessor/tuple/eat.hpp>
  291. # include <boost/preprocessor/tuple/to_seq.hpp>
  292. # include <boost/preprocessor/array/size.hpp>
  293. # include <boost/preprocessor/control/if.hpp>
  294. # include <boost/preprocessor/control/iif.hpp>
  295. # include <boost/preprocessor/control/expr_iif.hpp>
  296. # include <boost/preprocessor/logical/or.hpp>
  297. # include <boost/preprocessor/logical/nor.hpp>
  298. # include <boost/preprocessor/logical/not.hpp>
  299. # include <boost/preprocessor/logical/compl.hpp>
  300. # include <boost/preprocessor/arithmetic/inc.hpp>
  301. # include <boost/preprocessor/arithmetic/dec.hpp>
  302. # include <boost/preprocessor/arithmetic/add.hpp>
  303. # include <boost/preprocessor/detail/is_unary.hpp>
  304. # include <boost/preprocessor/detail/is_binary.hpp>
  305. # include <boost/preprocessor/repetition/repeat.hpp>
  306. # include <boost/preprocessor/repetition/enum_params.hpp>
  307. # include <boost/preprocessor/repetition/enum_binary_params.hpp>
  308. # include <boost/preprocessor/repetition/enum_shifted_params.hpp>
  309. # include <boost/preprocessor/repetition/enum_trailing_params.hpp>
  310. # include <boost/preprocessor/punctuation/comma.hpp>
  311. # include <boost/preprocessor/punctuation/comma_if.hpp>
  312. # include <boost/preprocessor/facilities/empty.hpp>
  313. # include <boost/preprocessor/facilities/identity.hpp>
  314. # include <boost/preprocessor/facilities/intercept.hpp>
  315. //==============================================================================
  316. // Interface
  317. //==============================================================================
  318. // Creates a rule parser. Use at namespace scope.
  319. # define BOOST_SPIRIT_RULE_PARSER(name,params,actions,members,rule) \
  320. BOOST_SPIRIT_RP_IMPL_I(name,params,actions,members,rule)
  321. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  322. // Creates a non-templated rule parser. Use at namespace scope.
  323. # define BOOST_SPIRIT_OPAQUE_RULE_PARSER(name,params,members,rule) \
  324. BOOST_SPIRIT_RP_OPAQUE_IMPL_I(name,params,members,rule)
  325. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  326. // Defines an action placeholder. Use at namespace scope.
  327. # define BOOST_SPIRIT_ACTION_PLACEHOLDER(name) \
  328. BOOST_SPIRIT_RP_AP_IMPL(name,::BOOST_SPIRIT_CLASSIC_NS::type_of)
  329. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  330. // Utilities to embed parsers by reference.
  331. namespace boost
  332. {
  333. namespace spirit
  334. {
  335. BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
  336. template<class P> class parser_reference;
  337. template<class P> parser_reference<P> embed_by_reference(parser<P> const &);
  338. BOOST_SPIRIT_CLASSIC_NAMESPACE_END
  339. }
  340. }
  341. //==============================================================================
  342. // Implementation
  343. //==============================================================================
  344. #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
  345. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  346. // RP_REGISTER_TEMPLATE
  347. //
  348. // Boost.Typeof registration from within BOOST_SPIRIT__NAMESPACE
  349. # define BOOST_SPIRIT_RP_REGISTER_TEMPLATE(name,params) \
  350. BOOST_SPIRIT_RP_EMIT(NS_CLOSE,BOOST_SPIRIT__NAMESPACE,-) \
  351. BOOST_TYPEOF_REGISTER_TEMPLATE( \
  352. BOOST_SPIRIT_RP_EMIT(NS_QUALIFY,BOOST_SPIRIT__NAMESPACE,-) name, \
  353. params) \
  354. BOOST_SPIRIT_RP_EMIT(NS_OPEN,BOOST_SPIRIT__NAMESPACE,-)
  355. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  356. // RP_REGISTER_TYPE
  357. //
  358. // Boost.Typeof registration from within BOOST_SPIRIT__NAMESPACE
  359. # define BOOST_SPIRIT_RP_REGISTER_TYPE(name) \
  360. BOOST_SPIRIT_RP_EMIT(NS_CLOSE,BOOST_SPIRIT__NAMESPACE,-) \
  361. BOOST_TYPEOF_REGISTER_TYPE( \
  362. BOOST_SPIRIT_RP_EMIT(NS_QUALIFY,BOOST_SPIRIT__NAMESPACE,-) name ) \
  363. BOOST_SPIRIT_RP_EMIT(NS_OPEN,BOOST_SPIRIT__NAMESPACE,-)
  364. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  365. // RP_AP_IMPL
  366. //
  367. // The action placeholder definition
  368. # define BOOST_SPIRIT_RP_AP_IMPL(name,ns) \
  369. namespace __action_placeholder \
  370. { \
  371. struct name \
  372. { \
  373. template<typename Action> \
  374. ns :: action_chain< name, ns :: replace, Action> \
  375. operator=(Action const & __a) const \
  376. { return ns :: action_chain< name, ns :: replace, Action>(__a); } \
  377. \
  378. template<typename Action> \
  379. ns :: action_chain< name, ns :: append, Action> \
  380. operator+=(Action const & __a) const \
  381. { return ns :: action_chain< name, ns :: append, Action> (__a); } \
  382. }; \
  383. } \
  384. __action_placeholder:: name const name = __action_placeholder:: name ();
  385. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  386. // RP_IMPL_I
  387. //
  388. // Does some precalculation so RP_IMPL_II can look cleaner
  389. # define BOOST_SPIRIT_RP_IMPL_I(name,pars,acts,mbrs,expr) \
  390. BOOST_SPIRIT_RP_IMPL_II(name, name ## _t , \
  391. pars, BOOST_SPIRIT_RP_ARRAY_SIZE(pars), \
  392. acts, BOOST_SPIRIT_RP_ARRAY_SIZE(acts), \
  393. mbrs, BOOST_SPIRIT_RP_ARRAY_SIZE(mbrs), expr)
  394. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  395. // RP_IMPL_II
  396. # define BOOST_SPIRIT_RP_IMPL_II(name,name_t,pars,np,acts,na,mbrs,nm,x) \
  397. BOOST_PP_IIF(BOOST_PP_OR(np,na),BOOST_SPIRIT_RP_IMPL_III, \
  398. BOOST_SPIRIT_RP_OPAQUE_IMPL_II) \
  399. (name,name_t,pars,np,acts,na,mbrs,nm,x)
  400. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  401. // RP_IMPL_III
  402. //
  403. // The rule parser definition
  404. # define BOOST_SPIRIT_RP_IMPL_III(name,name_t,pars,np,acts,na,mbrs,nm,x) \
  405. \
  406. template< BOOST_SPIRIT_RP_TPL_PARAMS(pars,acts,typename __,1) > \
  407. class name_t \
  408. : public ::BOOST_SPIRIT_CLASSIC_NS::parser< name_t \
  409. < BOOST_SPIRIT_RP_TPL_PARAMS(pars,acts,__,0) > > \
  410. { \
  411. class __rule \
  412. { \
  413. BOOST_SPIRIT_RP_EMIT(PM_STATIC,pars,__T) \
  414. BOOST_SPIRIT_RP_EMIT(AP_STATIC,acts,-) \
  415. BOOST_SPIRIT_RP_EMIT(MV_STATIC,mbrs,BOOST_PP_IDENTITY(typename)) \
  416. public: \
  417. BOOST_TYPEOF_NESTED_TYPEDEF_TPL(__expr, \
  418. ::BOOST_SPIRIT_CLASSIC_NS::type_of::depend_on_type<__Dummy>(x) ) \
  419. }; \
  420. \
  421. public: \
  422. \
  423. typedef name_t self_t; \
  424. typedef typename __rule::__expr::type::parser_category_t \
  425. parser_category_t; \
  426. \
  427. BOOST_PP_EXPR_IIF(BOOST_PP_NOR(np,na),typedef self_t const & embed_t;) \
  428. \
  429. protected: \
  430. \
  431. BOOST_SPIRIT_RP_EMIT(MV_NONSTATIC,mbrs,BOOST_PP_IDENTITY(typename)) \
  432. BOOST_SPIRIT_RP_IF(na,SPIRIT_RP_AP_EXTRA_MBRS,2)(np,na) \
  433. \
  434. typename __rule::__expr::type::embed_t __parser; \
  435. \
  436. public: \
  437. \
  438. explicit name_t ( BOOST_SPIRIT_RP_CTOR(PARAMS,pars,np,acts) ) \
  439. : BOOST_SPIRIT_RP_EMIT(MV_CTOR_INIT_LIST,mbrs,-) \
  440. BOOST_PP_COMMA_IF(nm) \
  441. BOOST_SPIRIT_RP_IF(na,SPIRIT_RP_CTOR_COMMA,4)(INIT_LIST,pars,np,acts)\
  442. __parser(x) \
  443. { } \
  444. \
  445. name_t( name_t const & that) \
  446. : BOOST_SPIRIT_RP_EMIT(MV_CTOR_COPY_INIT_LIST,mbrs,that) \
  447. BOOST_PP_COMMA_IF(nm) \
  448. BOOST_SPIRIT_RP_IF(na,SPIRIT_RP_CTOR_COMMA,4) \
  449. (COPY_INIT_LIST,pars,np,acts) \
  450. __parser(that.__parser) \
  451. { } \
  452. \
  453. template<typename Scanner> struct result \
  454. { \
  455. typedef typename ::BOOST_SPIRIT_CLASSIC_NS::parser_result< \
  456. typename __rule::__expr::type, Scanner>::type type; \
  457. }; \
  458. \
  459. template<typename Scanner> \
  460. typename ::BOOST_SPIRIT_CLASSIC_NS::parser_result<self_t, Scanner>::type \
  461. parse(Scanner const & s) const { return __parser.parse(s); } \
  462. \
  463. BOOST_SPIRIT_RP_IF(na,SPIRIT_RP_AP_HANDLER,5) \
  464. (name_t,np,acts,na,::BOOST_SPIRIT_CLASSIC_NS::type_of) \
  465. }; \
  466. \
  467. BOOST_PP_IF(np,BOOST_SPIRIT_RP_GEN_FUNC,BOOST_SPIRIT_RP_GLOB_VAR) \
  468. (name,name_t,np,na) \
  469. BOOST_SPIRIT_RP_REGISTER_TEMPLATE \
  470. (name_t,BOOST_PP_INC(BOOST_PP_ADD(np,na)))
  471. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  472. // RP_OPAQUE_IMPL_I
  473. //
  474. # define BOOST_SPIRIT_RP_OPAQUE_IMPL_I(name,pars,mbrs,expr) \
  475. BOOST_SPIRIT_RP_OPAQUE_IMPL_II(name, name ## _t, \
  476. pars,BOOST_SPIRIT_RP_ARRAY_SIZE(pars),-,-,\
  477. mbrs,BOOST_SPIRIT_RP_ARRAY_SIZE(mbrs),expr)
  478. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  479. // RP_OPAQUE_IMPL_II
  480. //
  481. # define BOOST_SPIRIT_RP_OPAQUE_IMPL_II(name,name_t,pars,np,_1,_2,mbrs,nm,x) \
  482. class name_t; \
  483. \
  484. BOOST_SPIRIT_RP_REGISTER_TYPE(name_t) \
  485. \
  486. class name_t \
  487. : public ::BOOST_SPIRIT_CLASSIC_NS::parser< name_t > \
  488. { \
  489. class __rule \
  490. { \
  491. BOOST_SPIRIT_RP_EMIT(PM_OPAQUE_STATIC,pars,-) \
  492. BOOST_SPIRIT_RP_EMIT(MV_STATIC,mbrs,BOOST_PP_EMPTY) \
  493. public: \
  494. BOOST_TYPEOF_NESTED_TYPEDEF(__expr,x) \
  495. }; \
  496. \
  497. public: \
  498. \
  499. typedef name_t self_t; \
  500. typedef __rule::__expr::type::parser_category_t parser_category_t; \
  501. BOOST_PP_EXPR_IIF(BOOST_PP_NOT(np),typedef self_t const & embed_t;) \
  502. \
  503. protected: \
  504. \
  505. BOOST_SPIRIT_RP_EMIT(MV_NONSTATIC,mbrs,BOOST_PP_EMPTY) \
  506. \
  507. __rule::__expr::type::embed_t __parser; \
  508. \
  509. public: \
  510. \
  511. explicit name_t (BOOST_SPIRIT_RP_EMIT(PM_OPAQUE_CTOR_PARAMS,pars,-)) \
  512. : BOOST_SPIRIT_RP_EMIT(MV_CTOR_INIT_LIST,mbrs,-) \
  513. BOOST_PP_COMMA_IF(nm) __parser(x) \
  514. { } \
  515. \
  516. name_t(name_t const & that) \
  517. : BOOST_SPIRIT_RP_EMIT(MV_CTOR_COPY_INIT_LIST,mbrs,that) \
  518. BOOST_PP_COMMA_IF(nm) __parser(that.__parser) \
  519. { } \
  520. \
  521. template<typename Scanner> struct result \
  522. { \
  523. typedef typename ::BOOST_SPIRIT_CLASSIC_NS::parser_result< \
  524. __rule::__expr::type, Scanner>::type type; \
  525. }; \
  526. \
  527. template<typename Scanner> \
  528. typename ::BOOST_SPIRIT_CLASSIC_NS::parser_result<self_t, Scanner>::type \
  529. parse(Scanner const & s) const { return __parser.parse(s); } \
  530. }; \
  531. \
  532. BOOST_PP_IF(np,BOOST_SPIRIT_RP_GEN_OPAQUE,BOOST_SPIRIT_RP_GLOB_OPAQUE) \
  533. (name,name_t,np,pars)
  534. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  535. // RP_AP_HANDLER
  536. //
  537. // Part of the rule parser definition for handling action placeholders
  538. # define BOOST_SPIRIT_RP_AP_HANDLER(name_t,np,acts,na,ns) \
  539. private: \
  540. template<typename A> struct __rebound_1st \
  541. { \
  542. typedef name_t < void BOOST_PP_ENUM_TRAILING_PARAMS(np,__T) , \
  543. typename ns ::action_concatenator<__A0,A>::type \
  544. BOOST_PP_COMMA_IF(BOOST_PP_DEC(na)) \
  545. BOOST_PP_ENUM_SHIFTED_PARAMS(na,__A) \
  546. > type; \
  547. }; \
  548. \
  549. template<typename X> struct __rebound \
  550. { \
  551. typedef name_t < \
  552. void BOOST_PP_ENUM_TRAILING_PARAMS(np,__T) \
  553. BOOST_SPIRIT_RP_EMIT(AP_REBOUND_TPL_ARGS,acts,X) \
  554. > type; \
  555. }; \
  556. public: \
  557. template<typename A> \
  558. typename __rebound_1st<A>::type const operator[](A const & a) const \
  559. { \
  560. return typename __rebound_1st<A>::type ( \
  561. BOOST_PP_ENUM_PARAMS(np,__p) BOOST_PP_COMMA_IF(np) \
  562. ns ::concatenate_actions(__a0,a) \
  563. BOOST_PP_COMMA_IF(BOOST_PP_DEC(na)) \
  564. BOOST_PP_ENUM_SHIFTED_PARAMS(na,__a) ); \
  565. } \
  566. template<class PH, ns ::action_chain_mode M, typename A> \
  567. typename __rebound< ns ::action_chain<PH,M,A> >::type const \
  568. operator[]( ns ::action_chain<PH,M,A> const & x) const \
  569. { \
  570. return typename __rebound< ns ::action_chain<PH,M,A> >::type ( \
  571. BOOST_PP_ENUM_PARAMS(np,__p) BOOST_PP_COMMA_IF(np) \
  572. BOOST_SPIRIT_RP_EMIT(AP_REBOUND_ARGS,acts,x) ); \
  573. } \
  574. template<class Head, class Tail> \
  575. typename __rebound< ns ::action_chains<Head,Tail> >::type const \
  576. operator[]( ns ::action_chains<Head,Tail> const & x) const \
  577. { \
  578. return typename __rebound< ns ::action_chains<Head,Tail> >::type ( \
  579. BOOST_PP_ENUM_PARAMS(np,__p) BOOST_PP_COMMA_IF(np) \
  580. BOOST_SPIRIT_RP_EMIT(AP_REBOUND_ARGS,acts,x) ); \
  581. }
  582. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  583. // RP_AP_EXTRA_MBRS
  584. //
  585. // Extra members we need for rebinding if there are action placeholders
  586. # define BOOST_SPIRIT_RP_AP_EXTRA_MBRS(np,na) \
  587. private: \
  588. BOOST_PP_REPEAT(np,BOOST_SPIRIT_RP_PM_MBRS,-) \
  589. BOOST_PP_REPEAT(na,BOOST_SPIRIT_RP_AP_MBRS,-)
  590. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  591. // RP_PM_MBRS
  592. //
  593. // Member variables to remember parameters if there are action placeholder
  594. # define BOOST_SPIRIT_RP_PM_MBRS(z,i,d) __T ## i __p ## i ;
  595. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  596. // RP_AP_MBRS
  597. //
  598. // Member variables to remember action placeholder substitutes
  599. # define BOOST_SPIRIT_RP_AP_MBRS(z,i,d) __A ## i __a ## i ;
  600. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  601. // RP_CTOR
  602. //
  603. // Expands to a fragment of a constructor (parameters or init-list)
  604. # define BOOST_SPIRIT_RP_CTOR(what,pars,np,acts) \
  605. BOOST_SPIRIT_RP_EMIT(PM_CTOR_ ## what,pars,__T) \
  606. BOOST_SPIRIT_RP_EMIT(AP_CTOR_ ## what,acts,np)
  607. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  608. // RP_CTOR_COMMA
  609. //
  610. // RP_CTOR with a trailing comma
  611. # define BOOST_SPIRIT_RP_CTOR_COMMA(what,pars,np,acts) \
  612. BOOST_SPIRIT_RP_CTOR(what,pars,np,acts) ,
  613. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  614. // RP_TPL_PARAMS
  615. //
  616. // Expands to the template parameters or arguments of the rule parser template
  617. # define BOOST_SPIRIT_RP_TPL_PARAMS(pars,acts,prefix,defaults) \
  618. prefix ## Dummy \
  619. BOOST_SPIRIT_RP_EMIT(PM_TEMPLATE_PARAMS,pars,prefix ## T) \
  620. BOOST_SPIRIT_RP_EMIT(AP_TEMPLATE_PARAMS,acts,(prefix ## A,defaults))
  621. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  622. // RP_GEN_FUNC
  623. //
  624. // Generator function
  625. # define BOOST_SPIRIT_RP_GEN_FUNC(name,name_t,np,na) \
  626. template< BOOST_PP_ENUM_PARAMS(np,typename T) > \
  627. inline name_t < void BOOST_PP_ENUM_TRAILING_PARAMS(np,T) > \
  628. name( BOOST_PP_ENUM_BINARY_PARAMS(np,T, const & p) ) \
  629. { return name_t < void BOOST_PP_ENUM_TRAILING_PARAMS(np,T) > \
  630. (BOOST_PP_ENUM_PARAMS(np,p) BOOST_PP_ENUM_TRAILING_PARAMS(na, \
  631. ::BOOST_SPIRIT_CLASSIC_NS::type_of::nop_functor() BOOST_PP_INTERCEPT) ); \
  632. }
  633. // RP_GEN_OPAQUE
  634. //
  635. // non-templated version for opaque rule parsers.
  636. # define BOOST_SPIRIT_RP_GEN_OPAQUE(name,name_t,np,pars) \
  637. inline name_t name( BOOST_SPIRIT_RP_EMIT(PM_OPAQUE_GEN_PARAMS,pars,p)) \
  638. { return name_t (BOOST_PP_ENUM_PARAMS(np,p)); }
  639. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  640. // RP_GLOB_VAR
  641. //
  642. // Global variable -- used instead of the generator function if there are no
  643. // parameters
  644. # define BOOST_SPIRIT_RP_GLOB_VAR(name,name_t,np,na) \
  645. static name_t <void> const name = name_t <void>(BOOST_PP_ENUM_PARAMS(na, \
  646. ::BOOST_SPIRIT_CLASSIC_NS::type_of::nop_functor() BOOST_PP_INTERCEPT) );
  647. // RP_GLOB_OPAQUE
  648. //
  649. // non-templated version for opaque rule parsers.
  650. # define BOOST_SPIRIT_RP_GLOB_OPAQUE(name,name_t,np,pars) \
  651. static name_t const name = name_t () ;
  652. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  653. // PP_EMIT operations (fragment emittion based on array input)
  654. // - - Namespace handling
  655. // NS_OPEN
  656. # define BOOST_SPIRIT_RP__NS_OPEN(r,data,i,elem) \
  657. namespace BOOST_SPIRIT_RP_OPTIONAL(elem) {
  658. // NS_QUALIFY
  659. # define BOOST_SPIRIT_RP__NS_QUALIFY(r,data,i,elem) \
  660. BOOST_SPIRIT_RP_OPTIONAL(elem ::)
  661. // NS_CLOSE
  662. # define BOOST_SPIRIT_RP__NS_CLOSE(r,data,i,elem) }
  663. // - - Parameter handling
  664. // PM_STATIC
  665. # define BOOST_SPIRIT_RP__PM_STATIC(r,data,i,elem) \
  666. static typename ::boost::call_traits< data ## i >::reference elem ;
  667. // PM_CTOR_PARAMS
  668. # define BOOST_SPIRIT_RP__PM_CTOR_PARAMS(r,data,i,elem) \
  669. BOOST_PP_COMMA_IF(i) \
  670. typename ::boost::call_traits< data ## i >::param_type elem
  671. // PM_CTOR_ARGS
  672. # define BOOST_SPIRIT_RP__PM_CTOR_ARGS(r,data,i,elem) \
  673. BOOST_PP_COMMA_IF(i) elem
  674. // PM_CTOR_INIT_LIST
  675. # define BOOST_SPIRIT_RP__PM_CTOR_INIT_LIST(r,data,i,elem) \
  676. BOOST_PP_COMMA_IF(i) __p ## i ( elem )
  677. // PM_CTOR_COPY_INIT_LIST
  678. # define BOOST_SPIRIT_RP__PM_CTOR_COPY_INIT_LIST(r,data,i,elem) \
  679. BOOST_PP_COMMA_IF(i) __p ## i ( that. __p ## i )
  680. // PM_TEMPLATE_PARAMS
  681. # define BOOST_SPIRIT_RP__PM_TEMPLATE_PARAMS(r,data,i,elem) , data ## i
  682. // - strictly typed parameters of the opaque rule_parser
  683. // PM_OPAQUE_STATIC
  684. # define BOOST_SPIRIT_RP__PM_OPAQUE_STATIC(r,data,i,elem) \
  685. static ::boost::call_traits< \
  686. BOOST_SPIRIT_RP_TYPE(BOOST_PP_TUPLE_ELEM(2,0,elem)) \
  687. >::reference BOOST_PP_TUPLE_ELEM(2,1,elem) ;
  688. // PM_OPAQUE_CTOR_PARAMS
  689. # define BOOST_SPIRIT_RP__PM_OPAQUE_CTOR_PARAMS(r,data,i,elem) \
  690. BOOST_PP_COMMA_IF(i) ::boost::call_traits< \
  691. BOOST_SPIRIT_RP_TYPE(BOOST_PP_TUPLE_ELEM(2,0,elem)) \
  692. >::param_type BOOST_PP_TUPLE_ELEM(2,1,elem)
  693. // PM_OPAQUE_GEN_PARAMS
  694. # define BOOST_SPIRIT_RP__PM_OPAQUE_GEN_PARAMS(r,data,i,elem) \
  695. BOOST_PP_COMMA_IF(i) ::boost::call_traits< \
  696. BOOST_SPIRIT_RP_TYPE(BOOST_PP_TUPLE_ELEM(2,0,elem)) \
  697. >::param_type data ## i
  698. // - - Member variable handling
  699. // MV_NONSTATIC
  700. # define BOOST_SPIRIT_RP__MV_NONSTATIC(r,data,i,elem) \
  701. data() BOOST_SPIRIT_RP_TYPE(BOOST_PP_TUPLE_ELEM(3,0,elem)) \
  702. BOOST_PP_TUPLE_ELEM(3,1,elem) ;
  703. // MV_STATIC
  704. # define BOOST_SPIRIT_RP__MV_STATIC(r,data,i,elem) \
  705. static data() ::boost::call_traits< \
  706. data() BOOST_SPIRIT_RP_TYPE(BOOST_PP_TUPLE_ELEM(3,0,elem)) \
  707. >::reference BOOST_PP_TUPLE_ELEM(3,1,elem) ;
  708. // MV_CTOR_INIT_LIST
  709. # define BOOST_SPIRIT_RP__MV_CTOR_INIT_LIST(r,data,i,elem) \
  710. BOOST_PP_COMMA_IF(i) \
  711. BOOST_PP_TUPLE_ELEM(3,1,elem) BOOST_PP_TUPLE_ELEM(3,2,elem)
  712. // MV_CTOR_COPY_INIT_LIST
  713. # define BOOST_SPIRIT_RP__MV_CTOR_COPY_INIT_LIST(r,data,i,elem) \
  714. BOOST_PP_COMMA_IF(i) \
  715. BOOST_PP_TUPLE_ELEM(3,1,elem) (data . BOOST_PP_TUPLE_ELEM(3,1,elem))
  716. // - - Action placeholder handling
  717. // AP_STATIC
  718. # define BOOST_SPIRIT_RP__AP_STATIC(r,data,i,elem) static __A ## i & elem ;
  719. // AP_CTOR_PARAMS
  720. # define BOOST_SPIRIT_RP__AP_CTOR_PARAMS(r,data,i,elem) \
  721. BOOST_SPIRIT_RP_COMMA_IF_OR(data,i) \
  722. typename ::boost::call_traits< __A ## i >::param_type elem
  723. // AP_CTOR_ARGS
  724. # define BOOST_SPIRIT_RP__AP_CTOR_ARGS(r,data,i,elem) \
  725. BOOST_SPIRIT_RP_COMMA_IF_OR(data,i) elem
  726. // AP_CTOR_INIT_LIST
  727. # define BOOST_SPIRIT_RP__AP_CTOR_INIT_LIST(r,data,i,elem) \
  728. BOOST_SPIRIT_RP_COMMA_IF_OR(data,i) __a ## i ( elem )
  729. // AP_CTOR_COPY_INIT_LIST
  730. # define BOOST_SPIRIT_RP__AP_CTOR_COPY_INIT_LIST(r,data,i,elem) \
  731. BOOST_SPIRIT_RP_COMMA_IF_OR(data,i) __a ## i ( that. __a ## i )
  732. // AP_TEMPLATE_PARAMS
  733. # define BOOST_SPIRIT_RP__AP_TEMPLATE_PARAMS(r,data,i,elem) \
  734. , BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2,0,data),i) \
  735. BOOST_PP_EXPR_IIF(BOOST_PP_TUPLE_ELEM(2,1,data), \
  736. = ::BOOST_SPIRIT_CLASSIC_NS::type_of::nop_functor)
  737. // AP_REBOUND_ARGS
  738. # define BOOST_SPIRIT_RP__AP_REBOUND_ARGS(r,data,i,elem) \
  739. BOOST_PP_COMMA_IF(i) \
  740. ::BOOST_SPIRIT_CLASSIC_NS::type_of::get_placeholdee< __action_placeholder:: elem > \
  741. ( __a ## i , data )
  742. // AP_REBOUND_TPL_ARGS
  743. # define BOOST_SPIRIT_RP__AP_REBOUND_TPL_ARGS(r,data,i,elem) \
  744. , typename ::BOOST_SPIRIT_CLASSIC_NS::type_of::placeholdee< \
  745. __action_placeholder:: elem , __A ## i, data >::type
  746. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  747. // PP_EMIT
  748. //
  749. // Performs one of the operations in the above section on an optional array.
  750. //
  751. # define BOOST_SPIRIT_RP_EMIT(op, array, data) \
  752. BOOST_SPIRIT_RP_ARRAY_FOR_EACH_I(BOOST_SPIRIT_RP__ ## op,data,array)
  753. // --- --- - - --- - - --- - - - - --- - - - - - - - - - - - - - - - - - - - - -
  754. // RP_ARRAY_FOR_EACH_I
  755. //
  756. // Iterates an optional array. That is you can pass e.g.'-' or 'none' to denote
  757. // emptiness.
  758. # define BOOST_SPIRIT_RP_ARRAY_FOR_EACH_I(macro,data,optional_array) \
  759. BOOST_PP_IIF(BOOST_PP_IS_BINARY(optional_array), \
  760. BOOST_SPIRIT_RP_ARRAY_FOR_EACH_I_IMPL, \
  761. BOOST_PP_TUPLE_EAT(3))(macro,data,optional_array)
  762. // RP_ARRAY_FOR_EACH_I_IMPL
  763. # define BOOST_SPIRIT_RP_ARRAY_FOR_EACH_I_IMPL(macro,data,array) \
  764. BOOST_SPIRIT_RP_IF(BOOST_PP_ARRAY_SIZE(array),PP_SEQ_FOR_EACH_I,3) \
  765. (macro,data, BOOST_SPIRIT_RP_IF(BOOST_PP_ARRAY_SIZE(array), \
  766. PP_TUPLE_TO_SEQ,2) array)
  767. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  768. // RP_ARRAY_SIZE
  769. //
  770. // Expands to the size of an "optional array".
  771. //
  772. // Examples:
  773. //
  774. // BOOST_SPIRIT_RP_ARRAY_SIZE( (2,(a,b)) ) // 2
  775. // BOOST_SPIRIT_RP_ARRAY_SIZE( (0,()) ) // 0
  776. // BOOST_SPIRIT_RP_ARRAY_SIZE( none ) // 0
  777. // BOOST_SPIRIT_RP_ARRAY_SIZE( - ) // 0
  778. //
  779. # define BOOST_SPIRIT_RP_ARRAY_SIZE(optional_array) \
  780. BOOST_PP_IIF(BOOST_PP_IS_BINARY(optional_array), \
  781. BOOST_PP_ARRAY_SIZE, 0 BOOST_PP_TUPLE_EAT(1))(optional_array)
  782. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  783. // RP_OPTIONAL
  784. //
  785. // Expands to nothing if the argument is parenthesized.
  786. //
  787. // Examples:
  788. //
  789. // BOOST_SPIRIT_RP_OPTIONAL( foobar ) // foobar
  790. // BOOST_SPIRIT_RP_OPTIONAL( (none) ) // evaluates to nothing
  791. //
  792. # define BOOST_SPIRIT_RP_OPTIONAL(elem) \
  793. BOOST_PP_EXPR_IIF(BOOST_PP_COMPL(BOOST_PP_IS_UNARY(elem)),elem)
  794. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  795. // RP_COMMA_IF_OR
  796. //
  797. // Expands to nothing if both arguments are zero, otherwise expands to a comma.
  798. //
  799. # define BOOST_SPIRIT_RP_COMMA_IF_OR(a,b) \
  800. BOOST_PP_IIF(BOOST_PP_OR(a,b),BOOST_PP_COMMA,BOOST_PP_EMPTY)()
  801. // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  802. // RP_IF
  803. //
  804. // BOOST_SPIRIT_RP_IF(cond,name,arity)
  805. //
  806. // is equivalent to:
  807. //
  808. // BOOST_PP_IF(cond,BOOST_name,BOOST_PP_TUPLE_EAT(arity))
  809. //
  810. # define BOOST_SPIRIT_RP_IF(cond,name,arity) \
  811. BOOST_PP_IF(cond,BOOST_ ## name,BOOST_PP_TUPLE_EAT(arity))
  812. //------------------------------------------------------------------------------
  813. // Wrapper and gernator function to embed a parser by reference
  814. //------------------------------------------------------------------------------
  815. namespace boost { namespace spirit {
  816. BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
  817. // Wrapper to embed a parser by reference
  818. template<class P> class parser_reference
  819. : public parser< parser_reference<P> >
  820. {
  821. P const & ref_that;
  822. public:
  823. parser_reference(P & that)
  824. // we allow implicit conversion but forbid temporaries.
  825. : ref_that(that)
  826. { }
  827. typedef parser_reference<P> self_t;
  828. typedef self_t const & embed_t;
  829. typedef typename P::parser_category_t parser_category_t;
  830. template<typename ScannerT> struct result
  831. { typedef typename P::BOOST_NESTED_TEMPLATE result<ScannerT>::type type; };
  832. template<typename ScannerT>
  833. typename result<ScannerT>::type
  834. parse(ScannerT const & scan) const
  835. { return this->ref_that.parse(scan); }
  836. };
  837. template<class P> parser_reference<P>
  838. embed_by_reference(::BOOST_SPIRIT_CLASSIC_NS::parser<P> & p)
  839. { return p; }
  840. BOOST_SPIRIT_CLASSIC_NAMESPACE_END
  841. } } // namespace ::BOOST_SPIRIT_CLASSIC_NS
  842. BOOST_TYPEOF_REGISTER_TEMPLATE(BOOST_SPIRIT_CLASSIC_NS::parser_reference, 1)
  843. //------------------------------------------------------------------------------
  844. // Expression templates for action placeholders.
  845. //------------------------------------------------------------------------------
  846. namespace boost { namespace spirit {
  847. BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
  848. namespace type_of {
  849. // No-operation functor
  850. struct nop_functor
  851. {
  852. template<typename T>
  853. bool operator()(T const &) const
  854. { return false; }
  855. template<typename T, typename U>
  856. bool operator()(T const &, U const &) const
  857. { return false; }
  858. typedef bool result_type;
  859. };
  860. // Composite action
  861. template<typename Action1, typename Action2>
  862. class composite_action
  863. {
  864. Action1 fnc_a1;
  865. Action2 fnc_a2;
  866. public:
  867. composite_action(Action1 const & a1, Action2 const & a2)
  868. : fnc_a1(a1), fnc_a2(a2)
  869. { }
  870. template<typename T>
  871. void operator()(T const & inp) const
  872. { fnc_a1(inp); fnc_a2(inp); }
  873. template<typename T, typename U>
  874. void operator()(T const & inp1, U const inp2) const
  875. { fnc_a1(inp1, inp2); fnc_a2(inp1, inp2); }
  876. };
  877. // Action concatenation (and optimize away nop_functorS)
  878. template<typename Action1, typename Action2>
  879. struct action_concatenator
  880. {
  881. typedef composite_action<Action1,Action2> type;
  882. static type concatenate(Action1 const & a1, Action2 const & a2)
  883. { return composite_action<Action1,Action2>(a1,a2); }
  884. };
  885. template<typename Action> struct action_concatenator<nop_functor, Action>
  886. {
  887. typedef Action type;
  888. static type concatenate(nop_functor const &, Action const & a)
  889. { return a; }
  890. };
  891. template<typename Action> struct action_concatenator<Action, nop_functor>
  892. {
  893. typedef Action type;
  894. static type concatenate(Action const & a, nop_functor const &)
  895. { return a; }
  896. };
  897. template<> struct action_concatenator<nop_functor, nop_functor>
  898. {
  899. typedef nop_functor type;
  900. static type concatenate(nop_functor const &, nop_functor const &)
  901. { return nop_functor(); }
  902. };
  903. template<typename Action1, typename Action2>
  904. typename action_concatenator<Action1,Action2>::type
  905. concatenate_actions(Action1 const & a1, Action2 const & a2)
  906. {
  907. return action_concatenator<Action1,Action2>::concatenate(a1,a2);
  908. }
  909. // Action chains
  910. enum action_chain_mode { replace, append };
  911. template<class Placeholder, action_chain_mode Mode, typename Action>
  912. class action_chain
  913. {
  914. Action fnc_action;
  915. public:
  916. action_chain(Action const & a)
  917. : fnc_action(a)
  918. { }
  919. typedef Action action_type;
  920. Action const & action() const { return fnc_action; }
  921. };
  922. // This operator adds actions to an action chain definition
  923. template<class PH, action_chain_mode M, typename A1, typename A2>
  924. action_chain<PH, M, typename action_concatenator<A1,A2>::type>
  925. operator, (action_chain<PH,M,A1> const & chain, A2 const & a)
  926. {
  927. return action_chain<PH,M,typename action_concatenator<A1,A2>::type>
  928. ( concatenate_actions(chain.action(), a) );
  929. }
  930. // Expression template for mutiple action chain assignments
  931. template<class ChainOrChains, class LastChain>
  932. class action_chains
  933. {
  934. ChainOrChains obj_head;
  935. LastChain obj_tail;
  936. public:
  937. action_chains(ChainOrChains const & head, LastChain const & tail)
  938. : obj_head(head), obj_tail(tail)
  939. { }
  940. typedef ChainOrChains head_type;
  941. typedef LastChain tail_type;
  942. head_type const & head() const { return obj_head; }
  943. tail_type const & tail() const { return obj_tail; }
  944. };
  945. // Action chain concatenation
  946. template<class Head, class Tail>
  947. action_chains<Head,Tail> make_chain(Head const & h, Tail const & t)
  948. { return action_chains<Head,Tail>(h,t); }
  949. template<class PH1, action_chain_mode M1, typename A1,
  950. class PH2, action_chain_mode M2, typename A2>
  951. action_chains< action_chain<PH1,M1,A1>, action_chain<PH2,M2,A2> >
  952. operator, (action_chain<PH1,M1,A1> const & h,
  953. action_chain<PH2,M2,A2> const & t)
  954. { return make_chain(h,t); }
  955. template<class Head, class Tail,class PH, action_chain_mode M, typename A>
  956. action_chains< action_chains<Head,Tail>, action_chain<PH,M,A> >
  957. operator, (action_chains<Head,Tail> const & h, action_chain<PH,M,A> const & t)
  958. { return make_chain(h,t); }
  959. // Extract the (maybe composite) action associated with an action
  960. // placeholders from the chains with a fold algorithm.
  961. template<class Placeholder, typename StartAction, class NewChainOrChains>
  962. struct placeholdee
  963. {
  964. typedef StartAction type;
  965. static type get(StartAction const & a, NewChainOrChains const &)
  966. { return a; }
  967. };
  968. template<class Placeholder, // <-- non-deduced
  969. typename StartAction, class NewChainOrChains>
  970. typename placeholdee<Placeholder,StartAction,NewChainOrChains>::type
  971. get_placeholdee(StartAction const & a, NewChainOrChains const & c)
  972. { return placeholdee<Placeholder,StartAction,NewChainOrChains>::get(a,c); }
  973. template<class Placeholder, typename StartAction, class Head, class Tail>
  974. struct placeholdee
  975. < Placeholder, StartAction, action_chains<Head,Tail> >
  976. {
  977. typedef typename placeholdee<Placeholder,
  978. typename placeholdee<Placeholder,StartAction,Head>::type, Tail >::type
  979. type;
  980. static type get(StartAction const & a, action_chains<Head,Tail> const & c)
  981. {
  982. return get_placeholdee<Placeholder>(
  983. get_placeholdee<Placeholder>(a,c.head()), c.tail() );
  984. }
  985. };
  986. template<class Placeholder, typename StartAction, typename A>
  987. struct placeholdee
  988. < Placeholder, StartAction, action_chain<Placeholder,replace,A> >
  989. {
  990. typedef A type;
  991. static type get(StartAction const &,
  992. action_chain<Placeholder,replace,A> const & c)
  993. { return c.action(); }
  994. };
  995. template<class Placeholder, typename StartAction, typename A>
  996. struct placeholdee
  997. < Placeholder, StartAction, action_chain<Placeholder,append,A> >
  998. {
  999. typedef typename action_concatenator<StartAction,A>::type type;
  1000. static type get(StartAction const & a,
  1001. action_chain<Placeholder,append,A> const & c)
  1002. { return concatenate_actions(a,c.action()); }
  1003. };
  1004. }
  1005. BOOST_SPIRIT_CLASSIC_NAMESPACE_END
  1006. } } // namespace ::BOOST_SPIRIT_CLASSIC_NS::type_of
  1007. BOOST_TYPEOF_REGISTER_TYPE(BOOST_SPIRIT_CLASSIC_NS::type_of::nop_functor)
  1008. BOOST_TYPEOF_REGISTER_TEMPLATE(BOOST_SPIRIT_CLASSIC_NS::type_of::composite_action,2)
  1009. //------------------------------------------------------------------------------
  1010. // Misc.utilities
  1011. //------------------------------------------------------------------------------
  1012. namespace boost { namespace spirit {
  1013. BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
  1014. namespace type_of {
  1015. // Utility function to create a dependency to a template argument.
  1016. template<typename T, typename X>
  1017. X const & depend_on_type(X const & x)
  1018. { return x; }
  1019. // Utility to allow use parenthesized type expressions with commas inside
  1020. // as a type within macros. Thanks to Dave Abrahams for telling me this nice
  1021. // trick.
  1022. #define BOOST_SPIRIT_RP_TYPE(x) \
  1023. ::BOOST_SPIRIT_CLASSIC_NS::type_of::remove_special_fptr \
  1024. < ::BOOST_SPIRIT_CLASSIC_NS::type_of::special_result & (*) x >::type
  1025. struct special_result;
  1026. template<typename T> struct remove_special_fptr { };
  1027. template<typename T> struct remove_special_fptr< special_result & (*)(T) >
  1028. { typedef T type; };
  1029. }
  1030. BOOST_SPIRIT_CLASSIC_NAMESPACE_END
  1031. } } // namespace ::BOOST_SPIRIT_CLASSIC_NS::type_of
  1032. //------------------------------------------------------------------------------
  1033. #endif
  1034. //------------------------------------------------------------------------------