namespace antlr3 { template RewriteRuleSubtreeStream::RewriteRuleSubtreeStream(TreeAdaptorType* adaptor, const char* description) : m_adaptor(adaptor) , m_elementDescription(description) , m_dirty(false) { m_cursor = m_elements.begin(); } template RewriteRuleSubtreeStream::RewriteRuleSubtreeStream(TreeAdaptorType* adaptor, const char* description, TreeType* oneElement ) : m_adaptor(adaptor) , m_elementDescription(description) , m_dirty(false) { if( oneElement != NULL ) { auto tree_clone = this->dup(oneElement); this->add( tree_clone ); } m_cursor = m_elements.begin(); } template RewriteRuleSubtreeStream::RewriteRuleSubtreeStream(TreeAdaptorType* adaptor, const char* description, TreeTypePtr& oneElement ) : m_adaptor(adaptor) , m_elementDescription(description) , m_dirty(false) { if( oneElement != NULL ) this->add( oneElement ); m_cursor = m_elements.begin(); } template RewriteRuleSubtreeStream::RewriteRuleSubtreeStream(TreeAdaptorType* adaptor, const char* description, const ElementsType& elements ) : m_adaptor(adaptor) , m_elementDescription(description) , m_dirty(false) , m_elements(elements) { m_cursor = m_elements.begin(); } template void RewriteRuleSubtreeStream::reset() { m_cursor = m_elements.begin(); m_dirty = true; } template void RewriteRuleSubtreeStream::add(TreeTypePtr& el) { if ( el == NULL ) return; m_elements.push_back(std::move(el)); m_cursor = m_elements.begin(); } template typename RewriteRuleSubtreeStream::ElementsType::iterator RewriteRuleSubtreeStream::_next() { if (m_elements.empty()) { // This means that the stream is empty // Caller must cope with this (TODO throw RewriteEmptyStreamException) return m_elements.end(); } if (m_dirty || m_cursor == m_elements.end()) { if( m_elements.size() == 1) { // Special case when size is single element, it will just dup a lot return m_elements.begin(); } // Out of elements and the size is not 1, so we cannot assume // that we just duplicate the entry n times (such as ID ent+ -> ^(ID ent)+) // This means we ran out of elements earlier than was expected. // return m_elements.end(); // Caller must cope with this (TODO throw RewriteEmptyStreamException) } // More than just a single element so we extract it from the // vector. return m_cursor++; } template typename RewriteRuleSubtreeStream::TreeTypePtr RewriteRuleSubtreeStream::nextTree() { if ( m_dirty || ( m_cursor == m_elements.end() && m_elements.size() == 1 )) { // if out of elements and size is 1, dup typename ElementsType::iterator el = this->_next(); return this->dup(*el); } // test size above then fetch typename ElementsType::iterator el = this->_next(); return std::move(*el); } /* template typename RewriteRuleSubtreeStream::TokenType* RewriteRuleSubtreeStream::nextToken() { return this->_next(); } template typename RewriteRuleSubtreeStream::TokenType* RewriteRuleSubtreeStream::next() { ANTLR_UINT32 s; s = this->size(); if ( (m_cursor >= s) && (s == 1) ) { TreeTypePtr el; el = this->_next(); return this->dup(el); } return this->_next(); } */ template typename RewriteRuleSubtreeStream::TreeTypePtr RewriteRuleSubtreeStream::dup(const TreeTypePtr& element) { return this->dupTree(element); } template typename RewriteRuleSubtreeStream::TreeTypePtr RewriteRuleSubtreeStream::dup(const TreeType* element) { return std::move(this->dupTree(element)); } template typename RewriteRuleSubtreeStream::TreeTypePtr RewriteRuleSubtreeStream::dupTree(const TreeTypePtr& element) { return std::move(m_adaptor->dupTree(element)); } template typename RewriteRuleSubtreeStream::TreeTypePtr RewriteRuleSubtreeStream::dupTree(const TreeType* element) { return std::move(m_adaptor->dupTree(element)); } template typename RewriteRuleSubtreeStream::ElementType* RewriteRuleSubtreeStream::toTree( ElementType* element) { return element; } template bool RewriteRuleSubtreeStream::hasNext() { return m_cursor != m_elements.end(); } /// Number of elements available in the stream /// template ANTLR_UINT32 RewriteRuleSubtreeStream::size() { return (ANTLR_UINT32)(m_elements.size()); } template typename RewriteRuleSubtreeStream::StringType RewriteRuleSubtreeStream::getDescription() { if ( m_elementDescription.empty() ) { m_elementDescription = ""; } return m_elementDescription; } template RewriteRuleSubtreeStream::~RewriteRuleSubtreeStream() { // Before placing the stream back in the pool, we // need to clear any vector it has. m_elements.clear(); } template typename RewriteRuleSubtreeStream::TreeTypePtr RewriteRuleSubtreeStream::nextNode() { //System.out.println("nextNode: elements="+elements+", singleElement="+((Tree)singleElement).toStringTree()); //ANTLR_UINT32 n = this->size(); if (m_dirty || (m_cursor == m_elements.end() && m_elements.size() == 1)) { // if out of elements and size is 1, dup (at most a single node // since this is for making root nodes). typename ElementsType::iterator el = this->_next(); return m_adaptor->dupNode(*el); } typename ElementsType::iterator el = this->_next(); //while (m_adaptor->isNilNode(el) && m_adaptor->getChildCount(el) == 1) // tree = m_adaptor->getChild(tree, 0); TreeTypePtr& node = leftestNode(*el); //System.out.println("_next="+((Tree)tree).toStringTree()); return m_adaptor->dupNode(node); // dup just the root (want node here) } template ANTLR_INLINE typename RewriteRuleSubtreeStream::TreeTypePtr& RewriteRuleSubtreeStream::leftestNode(TreeTypePtr& node) const { if(m_adaptor->isNilNode(node) && m_adaptor->getChildCount(node) == 1) return leftestNode(node->getChild(0)); else return node; } }