/Src/Dependencies/Boost/boost/spirit/home/lex/lexer/lexertl/functor_data.hpp

http://hadesmem.googlecode.com/ · C++ Header · 552 lines · 360 code · 72 blank · 120 comment · 16 complexity · 9650bfa185e42cdd362b14808a3f2e8a MD5 · raw file

  1. // Copyright (c) 2001-2011 Hartmut Kaiser
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #if !defined(BOOST_SPIRIT_LEX_LEXER_FUNCTOR_DATA_JUN_10_2009_0954AM)
  6. #define BOOST_SPIRIT_LEX_LEXER_FUNCTOR_DATA_JUN_10_2009_0954AM
  7. #if defined(_MSC_VER)
  8. #pragma once
  9. #endif
  10. #include <boost/spirit/home/qi/detail/assign_to.hpp>
  11. #include <boost/spirit/home/support/detail/lexer/generator.hpp>
  12. #include <boost/spirit/home/support/detail/lexer/rules.hpp>
  13. #include <boost/spirit/home/support/detail/lexer/state_machine.hpp>
  14. #include <boost/spirit/home/lex/lexer/lexertl/iterator_tokenizer.hpp>
  15. #include <boost/spirit/home/lex/lexer/lexertl/semantic_action_data.hpp>
  16. #include <boost/spirit/home/lex/lexer/lexertl/wrap_action.hpp>
  17. #include <boost/mpl/bool.hpp>
  18. #include <boost/optional.hpp>
  19. namespace boost { namespace spirit { namespace lex { namespace lexertl
  20. {
  21. namespace detail
  22. {
  23. ///////////////////////////////////////////////////////////////////////
  24. template <typename Iterator, typename HasActors, typename HasState
  25. , typename TokenValue>
  26. class data; // no default specialization
  27. ///////////////////////////////////////////////////////////////////////
  28. // neither supports state, nor actors
  29. template <typename Iterator, typename TokenValue>
  30. class data<Iterator, mpl::false_, mpl::false_, TokenValue>
  31. {
  32. protected:
  33. typedef typename
  34. boost::detail::iterator_traits<Iterator>::value_type
  35. char_type;
  36. public:
  37. typedef Iterator base_iterator_type;
  38. typedef iterator_range<Iterator> token_value_type;
  39. typedef token_value_type get_value_type;
  40. typedef std::size_t state_type;
  41. typedef char_type const* state_name_type;
  42. typedef unused_type semantic_actions_type;
  43. typedef detail::wrap_action<unused_type, Iterator, data, std::size_t>
  44. wrap_action_type;
  45. typedef unused_type next_token_functor;
  46. typedef unused_type get_state_name_type;
  47. // initialize the shared data
  48. template <typename IterData>
  49. data (IterData const& data_, Iterator& first, Iterator const& last)
  50. : first_(first), last_(last)
  51. , state_machine_(data_.state_machine_)
  52. , rules_(data_.rules_)
  53. , bol_(data_.state_machine_.data()._seen_BOL_assertion) {}
  54. // The following functions are used by the implementation of the
  55. // placeholder '_state'.
  56. template <typename Char>
  57. void set_state_name (Char const*)
  58. {
  59. // some (random) versions of gcc instantiate this function even if it's not
  60. // needed leading to false static asserts
  61. #if !defined(__GNUC__)
  62. // If you see a compile time assertion below you're probably
  63. // using a token type not supporting lexer states (the 3rd
  64. // template parameter of the token is mpl::false_), but your
  65. // code uses state changes anyways.
  66. BOOST_STATIC_ASSERT(false);
  67. #endif
  68. }
  69. char_type const* get_state_name() const { return rules_.initial(); }
  70. std::size_t get_state_id (char_type const*) const
  71. {
  72. return 0;
  73. }
  74. // The function get_eoi() is used by the implementation of the
  75. // placeholder '_eoi'.
  76. Iterator const& get_eoi() const { return last_; }
  77. // The function less() is used by the implementation of the support
  78. // function lex::less(). Its functionality is equivalent to flex'
  79. // function yyless(): it returns an iterator positioned to the
  80. // nth input character beyond the current start iterator (i.e. by
  81. // assigning the return value to the placeholder '_end' it is
  82. // possible to return all but the first n characters of the current
  83. // token back to the input stream.
  84. //
  85. // This function does nothing as long as no semantic actions are
  86. // used.
  87. Iterator const& less(Iterator const& it, int)
  88. {
  89. // The following assertion fires most likely because you are
  90. // using lexer semantic actions without using the actor_lexer
  91. // as the base class for your token definition class.
  92. BOOST_ASSERT(false &&
  93. "Are you using lexer semantic actions without using the "
  94. "actor_lexer base?");
  95. return it;
  96. }
  97. // The function more() is used by the implementation of the support
  98. // function lex::more(). Its functionality is equivalent to flex'
  99. // function yymore(): it tells the lexer that the next time it
  100. // matches a rule, the corresponding token should be appended onto
  101. // the current token value rather than replacing it.
  102. //
  103. // These functions do nothing as long as no semantic actions are
  104. // used.
  105. void more()
  106. {
  107. // The following assertion fires most likely because you are
  108. // using lexer semantic actions without using the actor_lexer
  109. // as the base class for your token definition class.
  110. BOOST_ASSERT(false &&
  111. "Are you using lexer semantic actions without using the "
  112. "actor_lexer base?");
  113. }
  114. bool adjust_start() { return false; }
  115. void revert_adjust_start() {}
  116. // The function lookahead() is used by the implementation of the
  117. // support function lex::lookahead. It can be used to implement
  118. // lookahead for lexer engines not supporting constructs like flex'
  119. // a/b (match a, but only when followed by b):
  120. //
  121. // This function does nothing as long as no semantic actions are
  122. // used.
  123. bool lookahead(std::size_t, std::size_t /*state*/ = std::size_t(~0))
  124. {
  125. // The following assertion fires most likely because you are
  126. // using lexer semantic actions without using the actor_lexer
  127. // as the base class for your token definition class.
  128. BOOST_ASSERT(false &&
  129. "Are you using lexer semantic actions without using the "
  130. "actor_lexer base?");
  131. return false;
  132. }
  133. // the functions next, invoke_actions, and get_state are used by
  134. // the functor implementation below
  135. // The function next() tries to match the next token from the
  136. // underlying input sequence.
  137. std::size_t next(Iterator& end, std::size_t& unique_id, bool& prev_bol)
  138. {
  139. prev_bol = bol_;
  140. typedef basic_iterator_tokeniser<Iterator> tokenizer;
  141. return tokenizer::next(state_machine_, bol_, end, last_
  142. , unique_id);
  143. }
  144. // nothing to invoke, so this is empty
  145. BOOST_SCOPED_ENUM(pass_flags) invoke_actions(std::size_t
  146. , std::size_t, std::size_t, Iterator const&)
  147. {
  148. return pass_flags::pass_normal; // always accept
  149. }
  150. std::size_t get_state() const { return 0; }
  151. void set_state(std::size_t) {}
  152. void set_end(Iterator const& it) {}
  153. Iterator& get_first() { return first_; }
  154. Iterator const& get_first() const { return first_; }
  155. Iterator const& get_last() const { return last_; }
  156. iterator_range<Iterator> get_value() const
  157. {
  158. return iterator_range<Iterator>(first_, last_);
  159. }
  160. bool has_value() const { return false; }
  161. void reset_value() {}
  162. void reset_bol(bool bol) { bol_ = bol; }
  163. protected:
  164. Iterator& first_;
  165. Iterator last_;
  166. boost::lexer::basic_state_machine<char_type> const& state_machine_;
  167. boost::lexer::basic_rules<char_type> const& rules_;
  168. bool bol_; // helper storing whether last character was \n
  169. private:
  170. // silence MSVC warning C4512: assignment operator could not be generated
  171. data& operator= (data const&);
  172. };
  173. ///////////////////////////////////////////////////////////////////////
  174. // doesn't support lexer semantic actions, but supports state
  175. template <typename Iterator, typename TokenValue>
  176. class data<Iterator, mpl::false_, mpl::true_, TokenValue>
  177. : public data<Iterator, mpl::false_, mpl::false_, TokenValue>
  178. {
  179. protected:
  180. typedef data<Iterator, mpl::false_, mpl::false_, TokenValue> base_type;
  181. typedef typename base_type::char_type char_type;
  182. public:
  183. typedef Iterator base_iterator_type;
  184. typedef iterator_range<Iterator> token_value_type;
  185. typedef token_value_type get_value_type;
  186. typedef typename base_type::state_type state_type;
  187. typedef typename base_type::state_name_type state_name_type;
  188. typedef typename base_type::semantic_actions_type
  189. semantic_actions_type;
  190. // initialize the shared data
  191. template <typename IterData>
  192. data (IterData const& data_, Iterator& first, Iterator const& last)
  193. : base_type(data_, first, last)
  194. , state_(0) {}
  195. // The following functions are used by the implementation of the
  196. // placeholder '_state'.
  197. void set_state_name (char_type const* new_state)
  198. {
  199. std::size_t state_id = this->rules_.state(new_state);
  200. // If the following assertion fires you've probably been using
  201. // a lexer state name which was not defined in your token
  202. // definition.
  203. BOOST_ASSERT(state_id != boost::lexer::npos);
  204. if (state_id != boost::lexer::npos)
  205. state_ = state_id;
  206. }
  207. char_type const* get_state_name() const
  208. {
  209. return this->rules_.state(state_);
  210. }
  211. std::size_t get_state_id (char_type const* state) const
  212. {
  213. return this->rules_.state(state);
  214. }
  215. // the functions next() and get_state() are used by the functor
  216. // implementation below
  217. // The function next() tries to match the next token from the
  218. // underlying input sequence.
  219. std::size_t next(Iterator& end, std::size_t& unique_id, bool& prev_bol)
  220. {
  221. prev_bol = this->bol_;
  222. typedef basic_iterator_tokeniser<Iterator> tokenizer;
  223. return tokenizer::next(this->state_machine_, state_,
  224. this->bol_, end, this->get_eoi(), unique_id);
  225. }
  226. std::size_t& get_state() { return state_; }
  227. void set_state(std::size_t state) { state_ = state; }
  228. protected:
  229. std::size_t state_;
  230. private:
  231. // silence MSVC warning C4512: assignment operator could not be generated
  232. data& operator= (data const&);
  233. };
  234. ///////////////////////////////////////////////////////////////////////
  235. // does support lexer semantic actions, may support state
  236. template <typename Iterator, typename HasState, typename TokenValue>
  237. class data<Iterator, mpl::true_, HasState, TokenValue>
  238. : public data<Iterator, mpl::false_, HasState, TokenValue>
  239. {
  240. public:
  241. typedef semantic_actions<Iterator, HasState, data>
  242. semantic_actions_type;
  243. protected:
  244. typedef data<Iterator, mpl::false_, HasState, TokenValue> base_type;
  245. typedef typename base_type::char_type char_type;
  246. typedef typename semantic_actions_type::functor_wrapper_type
  247. functor_wrapper_type;
  248. public:
  249. typedef Iterator base_iterator_type;
  250. typedef TokenValue token_value_type;
  251. typedef TokenValue const& get_value_type;
  252. typedef typename base_type::state_type state_type;
  253. typedef typename base_type::state_name_type state_name_type;
  254. typedef detail::wrap_action<functor_wrapper_type
  255. , Iterator, data, std::size_t> wrap_action_type;
  256. template <typename IterData>
  257. data (IterData const& data_, Iterator& first, Iterator const& last)
  258. : base_type(data_, first, last)
  259. , actions_(data_.actions_), hold_()
  260. , value_(iterator_range<Iterator>(first, last))
  261. , has_value_(false), has_hold_(false) {}
  262. // invoke attached semantic actions, if defined
  263. BOOST_SCOPED_ENUM(pass_flags) invoke_actions(std::size_t state
  264. , std::size_t& id, std::size_t unique_id, Iterator& end)
  265. {
  266. return actions_.invoke_actions(state, id, unique_id, end, *this);
  267. }
  268. // The function less() is used by the implementation of the support
  269. // function lex::less(). Its functionality is equivalent to flex'
  270. // function yyless(): it returns an iterator positioned to the
  271. // nth input character beyond the current start iterator (i.e. by
  272. // assigning the return value to the placeholder '_end' it is
  273. // possible to return all but the first n characters of the current
  274. // token back to the input stream).
  275. Iterator const& less(Iterator& it, int n)
  276. {
  277. it = this->get_first();
  278. std::advance(it, n);
  279. return it;
  280. }
  281. // The function more() is used by the implementation of the support
  282. // function lex::more(). Its functionality is equivalent to flex'
  283. // function yymore(): it tells the lexer that the next time it
  284. // matches a rule, the corresponding token should be appended onto
  285. // the current token value rather than replacing it.
  286. void more()
  287. {
  288. hold_ = this->get_first();
  289. has_hold_ = true;
  290. }
  291. // The function lookahead() is used by the implementation of the
  292. // support function lex::lookahead. It can be used to implement
  293. // lookahead for lexer engines not supporting constructs like flex'
  294. // a/b (match a, but only when followed by b)
  295. bool lookahead(std::size_t id, std::size_t state = std::size_t(~0))
  296. {
  297. Iterator end = end_;
  298. std::size_t unique_id = boost::lexer::npos;
  299. bool bol = this->bol_;
  300. if (std::size_t(~0) == state)
  301. state = this->state_;
  302. typedef basic_iterator_tokeniser<Iterator> tokenizer;
  303. return id == tokenizer::next(this->state_machine_, state,
  304. bol, end, this->get_eoi(), unique_id);
  305. }
  306. // The adjust_start() and revert_adjust_start() are helper
  307. // functions needed to implement the functionality required for
  308. // lex::more(). It is called from the functor body below.
  309. bool adjust_start()
  310. {
  311. if (!has_hold_)
  312. return false;
  313. std::swap(this->get_first(), hold_);
  314. has_hold_ = false;
  315. return true;
  316. }
  317. void revert_adjust_start()
  318. {
  319. // this will be called only if adjust_start above returned true
  320. std::swap(this->get_first(), hold_);
  321. has_hold_ = true;
  322. }
  323. TokenValue const& get_value() const
  324. {
  325. if (!has_value_) {
  326. value_ = iterator_range<Iterator>(this->get_first(), end_);
  327. has_value_ = true;
  328. }
  329. return value_;
  330. }
  331. template <typename Value>
  332. void set_value(Value const& val)
  333. {
  334. value_ = val;
  335. has_value_ = true;
  336. }
  337. void set_end(Iterator const& it)
  338. {
  339. end_ = it;
  340. }
  341. bool has_value() const { return has_value_; }
  342. void reset_value() { has_value_ = false; }
  343. protected:
  344. semantic_actions_type const& actions_;
  345. Iterator hold_; // iterator needed to support lex::more()
  346. Iterator end_; // iterator pointing to end of matched token
  347. mutable TokenValue value_; // token value to use
  348. mutable bool has_value_; // 'true' if value_ is valid
  349. bool has_hold_; // 'true' if hold_ is valid
  350. private:
  351. // silence MSVC warning C4512: assignment operator could not be generated
  352. data& operator= (data const&);
  353. };
  354. ///////////////////////////////////////////////////////////////////////
  355. // does support lexer semantic actions, may support state, is used for
  356. // position_token exposing exactly one type
  357. template <typename Iterator, typename HasState, typename TokenValue>
  358. class data<Iterator, mpl::true_, HasState, boost::optional<TokenValue> >
  359. : public data<Iterator, mpl::false_, HasState, TokenValue>
  360. {
  361. public:
  362. typedef semantic_actions<Iterator, HasState, data>
  363. semantic_actions_type;
  364. protected:
  365. typedef data<Iterator, mpl::false_, HasState, TokenValue> base_type;
  366. typedef typename base_type::char_type char_type;
  367. typedef typename semantic_actions_type::functor_wrapper_type
  368. functor_wrapper_type;
  369. public:
  370. typedef Iterator base_iterator_type;
  371. typedef boost::optional<TokenValue> token_value_type;
  372. typedef boost::optional<TokenValue> const& get_value_type;
  373. typedef typename base_type::state_type state_type;
  374. typedef typename base_type::state_name_type state_name_type;
  375. typedef detail::wrap_action<functor_wrapper_type
  376. , Iterator, data, std::size_t> wrap_action_type;
  377. template <typename IterData>
  378. data (IterData const& data_, Iterator& first, Iterator const& last)
  379. : base_type(data_, first, last)
  380. , actions_(data_.actions_), hold_()
  381. , has_value_(false), has_hold_(false)
  382. {
  383. spirit::traits::assign_to(first, last, value_);
  384. has_value_ = true;
  385. }
  386. // invoke attached semantic actions, if defined
  387. BOOST_SCOPED_ENUM(pass_flags) invoke_actions(std::size_t state
  388. , std::size_t& id, std::size_t unique_id, Iterator& end)
  389. {
  390. return actions_.invoke_actions(state, id, unique_id, end, *this);
  391. }
  392. // The function less() is used by the implementation of the support
  393. // function lex::less(). Its functionality is equivalent to flex'
  394. // function yyless(): it returns an iterator positioned to the
  395. // nth input character beyond the current start iterator (i.e. by
  396. // assigning the return value to the placeholder '_end' it is
  397. // possible to return all but the first n characters of the current
  398. // token back to the input stream).
  399. Iterator const& less(Iterator& it, int n)
  400. {
  401. it = this->get_first();
  402. std::advance(it, n);
  403. return it;
  404. }
  405. // The function more() is used by the implementation of the support
  406. // function lex::more(). Its functionality is equivalent to flex'
  407. // function yymore(): it tells the lexer that the next time it
  408. // matches a rule, the corresponding token should be appended onto
  409. // the current token value rather than replacing it.
  410. void more()
  411. {
  412. hold_ = this->get_first();
  413. has_hold_ = true;
  414. }
  415. // The function lookahead() is used by the implementation of the
  416. // support function lex::lookahead. It can be used to implement
  417. // lookahead for lexer engines not supporting constructs like flex'
  418. // a/b (match a, but only when followed by b)
  419. bool lookahead(std::size_t id, std::size_t state = std::size_t(~0))
  420. {
  421. Iterator end = end_;
  422. std::size_t unique_id = boost::lexer::npos;
  423. bool bol = this->bol_;
  424. if (std::size_t(~0) == state)
  425. state = this->state_;
  426. typedef basic_iterator_tokeniser<Iterator> tokenizer;
  427. return id == tokenizer::next(this->state_machine_, state,
  428. bol, end, this->get_eoi(), unique_id);
  429. }
  430. // The adjust_start() and revert_adjust_start() are helper
  431. // functions needed to implement the functionality required for
  432. // lex::more(). It is called from the functor body below.
  433. bool adjust_start()
  434. {
  435. if (!has_hold_)
  436. return false;
  437. std::swap(this->get_first(), hold_);
  438. has_hold_ = false;
  439. return true;
  440. }
  441. void revert_adjust_start()
  442. {
  443. // this will be called only if adjust_start above returned true
  444. std::swap(this->get_first(), hold_);
  445. has_hold_ = true;
  446. }
  447. token_value_type const& get_value() const
  448. {
  449. if (!has_value_) {
  450. spirit::traits::assign_to(this->get_first(), end_, value_);
  451. has_value_ = true;
  452. }
  453. return value_;
  454. }
  455. template <typename Value>
  456. void set_value(Value const& val)
  457. {
  458. value_ = val;
  459. has_value_ = true;
  460. }
  461. void set_end(Iterator const& it)
  462. {
  463. end_ = it;
  464. }
  465. bool has_value() const { return has_value_; }
  466. void reset_value() { has_value_ = false; }
  467. protected:
  468. semantic_actions_type const& actions_;
  469. Iterator hold_; // iterator needed to support lex::more()
  470. Iterator end_; // iterator pointing to end of matched token
  471. mutable token_value_type value_; // token value to use
  472. mutable bool has_value_; // 'true' if value_ is valid
  473. bool has_hold_; // 'true' if hold_ is valid
  474. private:
  475. // silence MSVC warning C4512: assignment operator could not be generated
  476. data& operator= (data const&);
  477. };
  478. }
  479. }}}}
  480. #endif