position_iterator.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. /*=============================================================================
  2. Copyright (c) 2002 Juan Carlos Arevalo-Baeza
  3. Copyright (c) 2002-2006 Hartmut Kaiser
  4. Copyright (c) 2003 Giovanni Bajo
  5. http://spirit.sourceforge.net/
  6. Distributed under the Boost Software License, Version 1.0. (See accompanying
  7. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. =============================================================================*/
  9. #ifndef BOOST_SPIRIT_POSITION_ITERATOR_HPP
  10. #define BOOST_SPIRIT_POSITION_ITERATOR_HPP
  11. #include <string>
  12. #include <boost/config.hpp>
  13. #include <boost/spirit/home/classic/namespace.hpp>
  14. #include <boost/spirit/home/classic/iterator/position_iterator_fwd.hpp>
  15. namespace boost { namespace spirit {
  16. BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
  17. ///////////////////////////////////////////////////////////////////////////////
  18. //
  19. // file_position_without_column
  20. //
  21. // A structure to hold positional information. This includes the file,
  22. // and the line number
  23. //
  24. ///////////////////////////////////////////////////////////////////////////////
  25. template <typename String>
  26. struct file_position_without_column_base {
  27. String file;
  28. int line;
  29. file_position_without_column_base(String const& file_ = String(),
  30. int line_ = 1):
  31. file (file_),
  32. line (line_)
  33. {}
  34. bool operator==(const file_position_without_column_base& fp) const
  35. { return line == fp.line && file == fp.file; }
  36. };
  37. ///////////////////////////////////////////////////////////////////////////////
  38. //
  39. // file_position
  40. //
  41. // This structure holds complete file position, including file name,
  42. // line and column number
  43. //
  44. ///////////////////////////////////////////////////////////////////////////////
  45. template <typename String>
  46. struct file_position_base : public file_position_without_column_base<String> {
  47. int column;
  48. file_position_base(String const& file_ = String(),
  49. int line_ = 1, int column_ = 1):
  50. file_position_without_column_base<String> (file_, line_),
  51. column (column_)
  52. {}
  53. bool operator==(const file_position_base& fp) const
  54. { return column == fp.column && this->line == fp.line && this->file == fp.file; }
  55. };
  56. ///////////////////////////////////////////////////////////////////////////////
  57. //
  58. // position_policy<>
  59. //
  60. // This template is the policy to handle the file position. It is specialized
  61. // on the position type. Providing a custom file_position also requires
  62. // providing a specialization of this class.
  63. //
  64. // Policy interface:
  65. //
  66. // Default constructor of the custom position class must be accessible.
  67. // set_tab_chars(unsigned int chars) - Set the tabstop width
  68. // next_char(PositionT& pos) - Notify that a new character has been
  69. // processed
  70. // tabulation(PositionT& pos) - Notify that a tab character has been
  71. // processed
  72. // next_line(PositionT& pos) - Notify that a new line delimiter has
  73. // been reached.
  74. //
  75. ///////////////////////////////////////////////////////////////////////////////
  76. template <typename PositionT> class position_policy;
  77. ///////////////////////////////////////////////////////////////////////////////
  78. BOOST_SPIRIT_CLASSIC_NAMESPACE_END
  79. }} /* namespace BOOST_SPIRIT_CLASSIC_NS */
  80. // This must be included here for full compatibility with old MSVC
  81. #include <boost/spirit/home/classic/iterator/impl/position_iterator.ipp>
  82. ///////////////////////////////////////////////////////////////////////////////
  83. namespace boost { namespace spirit {
  84. BOOST_SPIRIT_CLASSIC_NAMESPACE_BEGIN
  85. ///////////////////////////////////////////////////////////////////////////////
  86. //
  87. // position_iterator
  88. //
  89. // It wraps an iterator, and keeps track of the current position in the input,
  90. // as it gets incremented.
  91. //
  92. // The wrapped iterator must be at least a Forward iterator. The position
  93. // iterator itself will always be a non-mutable Forward iterator.
  94. //
  95. // In order to have begin/end iterators constructed, the end iterator must be
  96. // empty constructed. Similar to what happens with stream iterators. The begin
  97. // iterator must be constructed from both, the begin and end iterators of the
  98. // wrapped iterator type. This is necessary to implement the lookahead of
  99. // characters necessary to parse CRLF sequences.
  100. //
  101. // In order to extract the current positional data from the iterator, you may
  102. // use the get_position member function.
  103. //
  104. // You can also use the set_position member function to reset the current
  105. // position to something new.
  106. //
  107. // The structure that holds the current position can be customized through a
  108. // template parameter, and the class position_policy must be specialized
  109. // on the new type to define how to handle it. Currently, it's possible
  110. // to choose between the file_position and file_position_without_column
  111. // (which saves some overhead if managing current column is not required).
  112. //
  113. ///////////////////////////////////////////////////////////////////////////////
  114. #if !defined(BOOST_ITERATOR_ADAPTORS_VERSION) || \
  115. BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
  116. #error "Please use at least Boost V1.31.0 while compiling the position_iterator class!"
  117. #else // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
  118. ///////////////////////////////////////////////////////////////////////////////
  119. //
  120. // Uses the newer iterator_adaptor version (should be released with
  121. // Boost V1.31.0)
  122. //
  123. ///////////////////////////////////////////////////////////////////////////////
  124. template <
  125. typename ForwardIteratorT,
  126. typename PositionT,
  127. typename SelfT
  128. >
  129. class position_iterator
  130. : public iterator_::impl::position_iterator_base_generator<
  131. SelfT,
  132. ForwardIteratorT,
  133. PositionT
  134. >::type,
  135. public position_policy<PositionT>
  136. {
  137. private:
  138. typedef position_policy<PositionT> position_policy_t;
  139. typedef typename iterator_::impl::position_iterator_base_generator<
  140. SelfT,
  141. ForwardIteratorT,
  142. PositionT
  143. >::type base_t;
  144. typedef typename iterator_::impl::position_iterator_base_generator<
  145. SelfT,
  146. ForwardIteratorT,
  147. PositionT
  148. >::main_iter_t main_iter_t;
  149. public:
  150. typedef PositionT position_t;
  151. position_iterator()
  152. : _isend(true)
  153. {}
  154. position_iterator(
  155. const ForwardIteratorT& begin,
  156. const ForwardIteratorT& end)
  157. : base_t(begin), _end(end), _pos(PositionT()), _isend(begin == end)
  158. {}
  159. template <typename FileNameT>
  160. position_iterator(
  161. const ForwardIteratorT& begin,
  162. const ForwardIteratorT& end,
  163. FileNameT fileName)
  164. : base_t(begin), _end(end), _pos(PositionT(fileName)),
  165. _isend(begin == end)
  166. {}
  167. template <typename FileNameT, typename LineT>
  168. position_iterator(
  169. const ForwardIteratorT& begin,
  170. const ForwardIteratorT& end,
  171. FileNameT fileName, LineT line)
  172. : base_t(begin), _end(end), _pos(PositionT(fileName, line)),
  173. _isend(begin == end)
  174. {}
  175. template <typename FileNameT, typename LineT, typename ColumnT>
  176. position_iterator(
  177. const ForwardIteratorT& begin,
  178. const ForwardIteratorT& end,
  179. FileNameT fileName, LineT line, ColumnT column)
  180. : base_t(begin), _end(end), _pos(PositionT(fileName, line, column)),
  181. _isend(begin == end)
  182. {}
  183. position_iterator(
  184. const ForwardIteratorT& begin,
  185. const ForwardIteratorT& end,
  186. const PositionT& pos)
  187. : base_t(begin), _end(end), _pos(pos), _isend(begin == end)
  188. {}
  189. position_iterator(const position_iterator& iter)
  190. : base_t(iter.base()), position_policy_t(iter),
  191. _end(iter._end), _pos(iter._pos), _isend(iter._isend)
  192. {}
  193. position_iterator& operator=(const position_iterator& iter)
  194. {
  195. base_t::operator=(iter);
  196. position_policy_t::operator=(iter);
  197. _end = iter._end;
  198. _pos = iter._pos;
  199. _isend = iter._isend;
  200. return *this;
  201. }
  202. void set_position(PositionT const& newpos) { _pos = newpos; }
  203. PositionT& get_position() { return _pos; }
  204. PositionT const& get_position() const { return _pos; }
  205. void set_tabchars(unsigned int chars)
  206. {
  207. // This function (which comes from the position_policy) has a
  208. // different name on purpose, to avoid messing with using
  209. // declarations or qualified calls to access the base template
  210. // function, which might break some compilers.
  211. this->position_policy_t::set_tab_chars(chars);
  212. }
  213. private:
  214. friend class boost::iterator_core_access;
  215. void increment()
  216. {
  217. typename base_t::reference val = *(this->base());
  218. if (val == '\n') {
  219. ++this->base_reference();
  220. this->next_line(_pos);
  221. static_cast<main_iter_t &>(*this).newline();
  222. }
  223. else if ( val == '\r') {
  224. ++this->base_reference();
  225. if (this->base_reference() == _end || *(this->base()) != '\n')
  226. {
  227. this->next_line(_pos);
  228. static_cast<main_iter_t &>(*this).newline();
  229. }
  230. }
  231. else if (val == '\t') {
  232. this->tabulation(_pos);
  233. ++this->base_reference();
  234. }
  235. else {
  236. this->next_char(_pos);
  237. ++this->base_reference();
  238. }
  239. // The iterator is at the end only if it's the same
  240. // of the
  241. _isend = (this->base_reference() == _end);
  242. }
  243. template <
  244. typename OtherDerivedT, typename OtherIteratorT,
  245. typename V, typename C, typename R, typename D
  246. >
  247. bool equal(iterator_adaptor<OtherDerivedT, OtherIteratorT, V, C, R, D>
  248. const &x) const
  249. {
  250. OtherDerivedT const &rhs = static_cast<OtherDerivedT const &>(x);
  251. bool x_is_end = rhs._isend;
  252. return (_isend == x_is_end) && (_isend || this->base() == rhs.base());
  253. }
  254. protected:
  255. void newline()
  256. {}
  257. ForwardIteratorT _end;
  258. PositionT _pos;
  259. bool _isend;
  260. };
  261. #endif // BOOST_ITERATOR_ADAPTORS_VERSION < 0x0200
  262. ///////////////////////////////////////////////////////////////////////////////
  263. //
  264. // position_iterator2
  265. //
  266. // Equivalent to position_iterator, but it is able to extract the current
  267. // line into a string. This is very handy for error reports.
  268. //
  269. // Notice that the footprint of this class is higher than position_iterator,
  270. // (how much depends on how bulky the underlying iterator is), so it should
  271. // be used only if necessary.
  272. //
  273. ///////////////////////////////////////////////////////////////////////////////
  274. template
  275. <
  276. typename ForwardIteratorT,
  277. typename PositionT
  278. >
  279. class position_iterator2
  280. : public position_iterator
  281. <
  282. ForwardIteratorT,
  283. PositionT,
  284. position_iterator2<ForwardIteratorT, PositionT>
  285. >
  286. {
  287. typedef position_iterator
  288. <
  289. ForwardIteratorT,
  290. PositionT,
  291. position_iterator2<ForwardIteratorT, PositionT> // JDG 4-15-03
  292. > base_t;
  293. public:
  294. typedef typename base_t::value_type value_type;
  295. typedef PositionT position_t;
  296. position_iterator2()
  297. {}
  298. position_iterator2(
  299. const ForwardIteratorT& begin,
  300. const ForwardIteratorT& end):
  301. base_t(begin, end),
  302. _startline(begin)
  303. {}
  304. template <typename FileNameT>
  305. position_iterator2(
  306. const ForwardIteratorT& begin,
  307. const ForwardIteratorT& end,
  308. FileNameT file):
  309. base_t(begin, end, file),
  310. _startline(begin)
  311. {}
  312. template <typename FileNameT, typename LineT>
  313. position_iterator2(
  314. const ForwardIteratorT& begin,
  315. const ForwardIteratorT& end,
  316. FileNameT file, LineT line):
  317. base_t(begin, end, file, line),
  318. _startline(begin)
  319. {}
  320. template <typename FileNameT, typename LineT, typename ColumnT>
  321. position_iterator2(
  322. const ForwardIteratorT& begin,
  323. const ForwardIteratorT& end,
  324. FileNameT file, LineT line, ColumnT column):
  325. base_t(begin, end, file, line, column),
  326. _startline(begin)
  327. {}
  328. position_iterator2(
  329. const ForwardIteratorT& begin,
  330. const ForwardIteratorT& end,
  331. const PositionT& pos):
  332. base_t(begin, end, pos),
  333. _startline(begin)
  334. {}
  335. position_iterator2(const position_iterator2& iter)
  336. : base_t(iter), _startline(iter._startline)
  337. {}
  338. position_iterator2& operator=(const position_iterator2& iter)
  339. {
  340. base_t::operator=(iter);
  341. _startline = iter._startline;
  342. return *this;
  343. }
  344. ForwardIteratorT get_currentline_begin() const
  345. { return _startline; }
  346. ForwardIteratorT get_currentline_end() const
  347. { return get_endline(); }
  348. std::basic_string<value_type> get_currentline() const
  349. {
  350. return std::basic_string<value_type>
  351. (get_currentline_begin(), get_currentline_end());
  352. }
  353. protected:
  354. ForwardIteratorT _startline;
  355. friend class position_iterator<ForwardIteratorT, PositionT,
  356. position_iterator2<ForwardIteratorT, PositionT> >;
  357. ForwardIteratorT get_endline() const
  358. {
  359. ForwardIteratorT endline = _startline;
  360. while (endline != this->_end && *endline != '\r' && *endline != '\n')
  361. {
  362. ++endline;
  363. }
  364. return endline;
  365. }
  366. void newline()
  367. { _startline = this->base(); }
  368. };
  369. BOOST_SPIRIT_CLASSIC_NAMESPACE_END
  370. }} // namespace BOOST_SPIRIT_CLASSIC_NS
  371. #endif