equivset.hpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. // equivset.hpp
  2. // Copyright (c) 2007-2009 Ben Hanson (http://www.benhanson.net/)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_LEXER_EQUIVSET_HPP
  7. #define BOOST_LEXER_EQUIVSET_HPP
  8. #include <algorithm>
  9. #include "../parser/tree/node.hpp"
  10. #include <set>
  11. #include "../size_t.hpp"
  12. namespace boost
  13. {
  14. namespace lexer
  15. {
  16. namespace detail
  17. {
  18. struct equivset
  19. {
  20. typedef std::set<std::size_t> index_set;
  21. typedef std::vector<std::size_t> index_vector;
  22. // Not owner of nodes:
  23. typedef std::vector<node *> node_vector;
  24. index_vector _index_vector;
  25. bool _greedy;
  26. std::size_t _id;
  27. node_vector _followpos;
  28. equivset () :
  29. _greedy (true),
  30. _id (0)
  31. {
  32. }
  33. equivset (const index_set &index_set_, const bool greedy_,
  34. const std::size_t id_, const node_vector &followpos_) :
  35. _greedy (greedy_),
  36. _id (id_),
  37. _followpos (followpos_)
  38. {
  39. index_set::const_iterator iter_ = index_set_.begin ();
  40. index_set::const_iterator end_ = index_set_.end ();
  41. for (; iter_ != end_; ++iter_)
  42. {
  43. _index_vector.push_back (*iter_);
  44. }
  45. }
  46. bool empty () const
  47. {
  48. return _index_vector.empty () && _followpos.empty ();
  49. }
  50. void intersect (equivset &rhs_, equivset &overlap_)
  51. {
  52. intersect_indexes (rhs_._index_vector, overlap_._index_vector);
  53. if (!overlap_._index_vector.empty ())
  54. {
  55. // Note that the LHS takes priority in order to
  56. // respect rule ordering priority in the lex spec.
  57. overlap_._id = _id;
  58. overlap_._greedy = _greedy;
  59. overlap_._followpos = _followpos;
  60. node_vector::const_iterator overlap_begin_ =
  61. overlap_._followpos.begin ();
  62. node_vector::const_iterator overlap_end_ =
  63. overlap_._followpos.end ();
  64. node_vector::const_iterator rhs_iter_ =
  65. rhs_._followpos.begin ();
  66. node_vector::const_iterator rhs_end_ =
  67. rhs_._followpos.end ();
  68. for (; rhs_iter_ != rhs_end_; ++rhs_iter_)
  69. {
  70. node *node_ = *rhs_iter_;
  71. if (std::find (overlap_begin_, overlap_end_, node_) ==
  72. overlap_end_)
  73. {
  74. overlap_._followpos.push_back (node_);
  75. overlap_begin_ = overlap_._followpos.begin ();
  76. overlap_end_ = overlap_._followpos.end ();
  77. }
  78. }
  79. if (_index_vector.empty ())
  80. {
  81. _followpos.clear ();
  82. }
  83. if (rhs_._index_vector.empty ())
  84. {
  85. rhs_._followpos.clear ();
  86. }
  87. }
  88. }
  89. private:
  90. void intersect_indexes (index_vector &rhs_, index_vector &overlap_)
  91. {
  92. index_vector::iterator iter_ = _index_vector.begin ();
  93. index_vector::iterator end_ = _index_vector.end ();
  94. index_vector::iterator rhs_iter_ = rhs_.begin ();
  95. index_vector::iterator rhs_end_ = rhs_.end ();
  96. while (iter_ != end_ && rhs_iter_ != rhs_end_)
  97. {
  98. const std::size_t index_ = *iter_;
  99. const std::size_t rhs_index_ = *rhs_iter_;
  100. if (index_ < rhs_index_)
  101. {
  102. ++iter_;
  103. }
  104. else if (index_ > rhs_index_)
  105. {
  106. ++rhs_iter_;
  107. }
  108. else
  109. {
  110. overlap_.push_back (index_);
  111. iter_ = _index_vector.erase (iter_);
  112. end_ = _index_vector.end ();
  113. rhs_iter_ = rhs_.erase (rhs_iter_);
  114. rhs_end_ = rhs_.end ();
  115. }
  116. }
  117. }
  118. };
  119. }
  120. }
  121. }
  122. #endif