// equivset.hpp // Copyright (c) 2005-2018 Ben Hanson (http://www.benhanson.net/) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef LEXERTL_EQUIVSET_HPP #define LEXERTL_EQUIVSET_HPP #include #include "../parser/tree/node.hpp" #include namespace lexertl { namespace detail { template struct basic_equivset { using index_set = std::set; using index_vector = std::vector; using node = basic_node; using node_vector = std::vector>; index_vector _index_vector; id_type _id; bool _greedy; node_vector _followpos; basic_equivset() : _index_vector(), _id(0), _greedy(true), _followpos() { } basic_equivset(const index_set &index_set_, const id_type id_, const bool greedy_, const node_vector &followpos_) : _index_vector(index_set_.begin(), index_set_.end()), _id(id_), _greedy(greedy_), _followpos(followpos_) { } bool empty() const { return _index_vector.empty() && _followpos.empty(); } void intersect(basic_equivset &rhs_, basic_equivset &overlap_) { intersect_indexes(rhs_._index_vector, overlap_._index_vector); if (!overlap_._index_vector.empty()) { // Note that the LHS takes priority in order to // respect rule ordering priority in the lex spec. overlap_._id = _id; overlap_._greedy = _greedy; overlap_._followpos = _followpos; auto overlap_begin_ = overlap_._followpos.cbegin(); auto overlap_end_ = overlap_._followpos.cend(); for (observer_ptr node_ : rhs_._followpos) { if (std::find(overlap_begin_, overlap_end_, node_) == overlap_end_) { overlap_._followpos.push_back(node_); overlap_begin_ = overlap_._followpos.begin(); overlap_end_ = overlap_._followpos.end(); } } if (_index_vector.empty()) { _followpos.clear(); } if (rhs_._index_vector.empty()) { rhs_._followpos.clear(); } } } private: void intersect_indexes(index_vector &rhs_, index_vector &overlap_) { std::set_intersection(_index_vector.begin(), _index_vector.end(), rhs_.begin(), rhs_.end(), std::back_inserter(overlap_)); if (!overlap_.empty()) { remove(overlap_, _index_vector); remove(overlap_, rhs_); } } void remove(const index_vector &source_, index_vector &dest_) { auto inter_ = source_.begin(); auto inter_end_ = source_.end(); auto reader_ = std::find(dest_.begin(), dest_.end(), *inter_); auto writer_ = reader_; auto dest_end_ = dest_.end(); while (writer_ != dest_end_ && inter_ != inter_end_) { if (*reader_ == *inter_) { ++inter_; ++reader_; } else { *writer_++ = *reader_++; } } while (reader_ != dest_end_) { *writer_++ = *reader_++; } dest_.resize(dest_.size() - source_.size()); } }; } } #endif