X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.databoard%2Fcpp%2FDataBoardTest%2Flibantlr3c-3.2%2Fsrc%2Fantlr3rewritestreams.c;h=9afb6e1ec5141e1a4e61b58c2fb9423251914bb4;hp=ace786e3a32f8b6b661b427b87bd80b062a928fd;hb=refs%2Fchanges%2F38%2F238%2F2;hpb=24e2b34260f219f0d1644ca7a138894980e25b14 diff --git a/bundles/org.simantics.databoard/cpp/DataBoardTest/libantlr3c-3.2/src/antlr3rewritestreams.c b/bundles/org.simantics.databoard/cpp/DataBoardTest/libantlr3c-3.2/src/antlr3rewritestreams.c index ace786e3a..9afb6e1ec 100644 --- a/bundles/org.simantics.databoard/cpp/DataBoardTest/libantlr3c-3.2/src/antlr3rewritestreams.c +++ b/bundles/org.simantics.databoard/cpp/DataBoardTest/libantlr3c-3.2/src/antlr3rewritestreams.c @@ -1,844 +1,844 @@ -/// \file -/// Implementation of token/tree streams that are used by the -/// tree re-write rules to manipulate the tokens and trees produced -/// by rules that are subject to rewrite directives. -/// - -// [The "BSD licence"] -// Copyright (c) 2005-2009 Jim Idle, Temporal Wave LLC -// http://www.temporal-wave.com -// http://www.linkedin.com/in/jimidle -// -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// 3. The name of the author may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include - -// Static support function forward declarations for the stream types. -// -static void reset (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); -static void add (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * el, void (ANTLR3_CDECL *freePtr)(void *)); -static void * next (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); -static pANTLR3_BASE_TREE nextTree (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); -static void * nextToken (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); -static void * _next (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); -static void * dupTok (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * el); -static void * dupTree (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * el); -static void * dupTreeNode (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * el); -static pANTLR3_BASE_TREE toTree (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * element); -static pANTLR3_BASE_TREE toTreeNode (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * element); -static ANTLR3_BOOLEAN hasNext (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); -static pANTLR3_BASE_TREE nextNode (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); -static pANTLR3_BASE_TREE nextNodeNode (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); -static pANTLR3_BASE_TREE nextNodeToken (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); -static ANTLR3_UINT32 size (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); -static void * getDescription (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); -static void freeRS (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); -static void expungeRS (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); - - -// Place a now unused rewrite stream back on the rewrite stream pool -// so we can reuse it if we need to. -// -static void -freeRS (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) -{ - // Before placing the stream back in the pool, we - // need to clear any vector it has. This is so any - // free pointers that are associated with the - // entires are called. - // - if (stream->elements != NULL) - { - // Factory generated vectors can be returned to the - // vector factory for later reuse. - // - if (stream->elements->factoryMade == ANTLR3_TRUE) - { - pANTLR3_VECTOR_FACTORY factory = ((pANTLR3_COMMON_TREE_ADAPTOR)(stream->adaptor->super))->arboretum->vFactory; - factory->returnVector(factory, stream->elements); - - stream->elements = NULL; - } - else - { - // Other vectors we clear and allow to be reused if they come off the - // rewrite stream free stack and are reused. - // - stream->elements->clear(stream->elements); - stream->freeElements = ANTLR3_TRUE; - } - } - else - { - stream->freeElements = ANTLR3_FALSE; // Just in case - } - - // Add the stream into the recognizer stream stack vector - // adding the stream memory free routine so that - // it is thrown away when the stack vector is destroyed - // - stream->rec->state->rStreams->add(stream->rec->state->rStreams, stream, (void(*)(void *))expungeRS); -} - -/** Do special nilNode reuse detection for node streams. - */ -static void -freeNodeRS(pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) -{ - pANTLR3_BASE_TREE tree; - - // Before placing the stream back in the pool, we - // need to clear any vector it has. This is so any - // free pointers that are associated with the - // entires are called. However, if this particular function is called - // then we know that the entries in the stream are definately - // tree nodes. Hence we check to see if any of them were nilNodes as - // if they were, we can reuse them. - // - if (stream->elements != NULL) - { - // We have some elements to traverse - // - ANTLR3_UINT32 i; - - for (i = 1; i<= stream->elements->count; i++) - { - tree = (pANTLR3_BASE_TREE)(stream->elements->elements[i-1].element); - if (tree != NULL && tree->isNilNode(tree)) - { - // Had to remove this for now, check is not comprehensive enough - // tree->reuse(tree); - } - - } - // Factory generated vectors can be returned to the - // vector factory for later reuse. - // - if (stream->elements->factoryMade == ANTLR3_TRUE) - { - pANTLR3_VECTOR_FACTORY factory = ((pANTLR3_COMMON_TREE_ADAPTOR)(stream->adaptor->super))->arboretum->vFactory; - factory->returnVector(factory, stream->elements); - - stream->elements = NULL; - } - else - { - stream->elements->clear(stream->elements); - stream->freeElements = ANTLR3_TRUE; - } - } - else - { - if (stream->singleElement != NULL) - { - tree = (pANTLR3_BASE_TREE)(stream->singleElement); - if (tree->isNilNode(tree)) - { - // Had to remove this for now, check is not comprehensive enough - // tree->reuse(tree); - } - } - stream->singleElement = NULL; - stream->freeElements = ANTLR3_FALSE; // Just in case - } - - // Add the stream into the recognizer stream stack vector - // adding the stream memory free routine so that - // it is thrown away when the stack vector is destroyed - // - stream->rec->state->rStreams->add(stream->rec->state->rStreams, stream, (void(*)(void *))expungeRS); -} -static void -expungeRS(pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) -{ - - if (stream->freeElements == ANTLR3_TRUE && stream->elements != NULL) - { - stream->elements->free(stream->elements); - } - ANTLR3_FREE(stream); -} - -// Functions for creating streams -// -static pANTLR3_REWRITE_RULE_ELEMENT_STREAM -antlr3RewriteRuleElementStreamNewAE(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description) -{ - pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream; - - // First - do we already have a rewrite stream that was returned - // to the pool? If we do, then we will just reuse it by resetting - // the generic interface. - // - if (rec->state->rStreams->count > 0) - { - // Remove the entry from the vector. We do not - // cause it to be freed by using remove. - // - stream = rec->state->rStreams->remove(rec->state->rStreams, rec->state->rStreams->count - 1); - - // We found a stream we can reuse. - // If the stream had a vector, then it will have been cleared - // when the freeRS was called that put it in this stack - // - } - else - { - // Ok, we need to allocate a new one as there were none on the stack. - // First job is to create the memory we need. - // - stream = (pANTLR3_REWRITE_RULE_ELEMENT_STREAM) ANTLR3_MALLOC((size_t)(sizeof(ANTLR3_REWRITE_RULE_ELEMENT_STREAM))); - - if (stream == NULL) - { - return NULL; - } - stream->elements = NULL; - stream->freeElements = ANTLR3_FALSE; - } - - // Populate the generic interface - // - stream->rec = rec; - stream->reset = reset; - stream->add = add; - stream->next = next; - stream->nextTree = nextTree; - stream->nextNode = nextNode; - stream->nextToken = nextToken; - stream->_next = _next; - stream->hasNext = hasNext; - stream->size = size; - stream->getDescription = getDescription; - stream->toTree = toTree; - stream->free = freeRS; - stream->singleElement = NULL; - - // Reset the stream to empty. - // - - stream->cursor = 0; - stream->dirty = ANTLR3_FALSE; - - // Install the description - // - stream->elementDescription = description; - - // Install the adaptor - // - stream->adaptor = adaptor; - - return stream; -} - -static pANTLR3_REWRITE_RULE_ELEMENT_STREAM -antlr3RewriteRuleElementStreamNewAEE(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description, void * oneElement) -{ - pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream; - - // First job is to create the memory we need. - // - stream = antlr3RewriteRuleElementStreamNewAE(adaptor, rec, description); - - if (stream == NULL) - { - return NULL; - } - - // Stream seems good so we need to add the supplied element - // - if (oneElement != NULL) - { - stream->add(stream, oneElement, NULL); - } - return stream; -} - -static pANTLR3_REWRITE_RULE_ELEMENT_STREAM -antlr3RewriteRuleElementStreamNewAEV(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description, pANTLR3_VECTOR vector) -{ - pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream; - - // First job is to create the memory we need. - // - stream = antlr3RewriteRuleElementStreamNewAE(adaptor, rec, description); - - if (stream == NULL) - { - return stream; - } - - // Stream seems good so we need to install the vector we were - // given. We assume that someone else is going to free the - // vector. - // - if (stream->elements != NULL && stream->elements->factoryMade == ANTLR3_FALSE && stream->freeElements == ANTLR3_TRUE ) - { - stream->elements->free(stream->elements); - } - stream->elements = vector; - stream->freeElements = ANTLR3_FALSE; - return stream; -} - -// Token rewrite stream ... -// -ANTLR3_API pANTLR3_REWRITE_RULE_TOKEN_STREAM -antlr3RewriteRuleTOKENStreamNewAE(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description) -{ - pANTLR3_REWRITE_RULE_TOKEN_STREAM stream; - - // First job is to create the memory we need. - // - stream = antlr3RewriteRuleElementStreamNewAE(adaptor, rec, description); - - if (stream == NULL) - { - return stream; - } - - // Install the token based overrides - // - stream->dup = dupTok; - stream->nextNode = nextNodeToken; - - // No nextNode implementation for a token rewrite stream - // - return stream; -} - -ANTLR3_API pANTLR3_REWRITE_RULE_TOKEN_STREAM -antlr3RewriteRuleTOKENStreamNewAEE(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description, void * oneElement) -{ - pANTLR3_REWRITE_RULE_TOKEN_STREAM stream; - - // First job is to create the memory we need. - // - stream = antlr3RewriteRuleElementStreamNewAEE(adaptor, rec, description, oneElement); - - // Install the token based overrides - // - stream->dup = dupTok; - stream->nextNode = nextNodeToken; - - // No nextNode implementation for a token rewrite stream - // - return stream; -} - -ANTLR3_API pANTLR3_REWRITE_RULE_TOKEN_STREAM -antlr3RewriteRuleTOKENStreamNewAEV(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description, pANTLR3_VECTOR vector) -{ - pANTLR3_REWRITE_RULE_TOKEN_STREAM stream; - - // First job is to create the memory we need. - // - stream = antlr3RewriteRuleElementStreamNewAEV(adaptor, rec, description, vector); - - // Install the token based overrides - // - stream->dup = dupTok; - stream->nextNode = nextNodeToken; - - // No nextNode implementation for a token rewrite stream - // - return stream; -} - -// Subtree rewrite stream -// -ANTLR3_API pANTLR3_REWRITE_RULE_SUBTREE_STREAM -antlr3RewriteRuleSubtreeStreamNewAE(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description) -{ - pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream; - - // First job is to create the memory we need. - // - stream = antlr3RewriteRuleElementStreamNewAE(adaptor, rec, description); - - if (stream == NULL) - { - return stream; - } - - // Install the subtree based overrides - // - stream->dup = dupTree; - stream->nextNode = nextNode; - stream->free = freeNodeRS; - return stream; - -} -ANTLR3_API pANTLR3_REWRITE_RULE_SUBTREE_STREAM -antlr3RewriteRuleSubtreeStreamNewAEE(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description, void * oneElement) -{ - pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream; - - // First job is to create the memory we need. - // - stream = antlr3RewriteRuleElementStreamNewAEE(adaptor, rec, description, oneElement); - - if (stream == NULL) - { - return stream; - } - - // Install the subtree based overrides - // - stream->dup = dupTree; - stream->nextNode = nextNode; - stream->free = freeNodeRS; - - return stream; -} - -ANTLR3_API pANTLR3_REWRITE_RULE_SUBTREE_STREAM -antlr3RewriteRuleSubtreeStreamNewAEV(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description, pANTLR3_VECTOR vector) -{ - pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream; - - // First job is to create the memory we need. - // - stream = antlr3RewriteRuleElementStreamNewAEV(adaptor, rec, description, vector); - - if (stream == NULL) - { - return NULL; - } - - // Install the subtree based overrides - // - stream->dup = dupTree; - stream->nextNode = nextNode; - stream->free = freeNodeRS; - - return stream; -} -// Node rewrite stream ... -// -ANTLR3_API pANTLR3_REWRITE_RULE_NODE_STREAM -antlr3RewriteRuleNODEStreamNewAE(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description) -{ - pANTLR3_REWRITE_RULE_NODE_STREAM stream; - - // First job is to create the memory we need. - // - stream = antlr3RewriteRuleElementStreamNewAE(adaptor, rec, description); - - if (stream == NULL) - { - return stream; - } - - // Install the node based overrides - // - stream->dup = dupTreeNode; - stream->toTree = toTreeNode; - stream->nextNode = nextNodeNode; - stream->free = freeNodeRS; - - return stream; -} - -ANTLR3_API pANTLR3_REWRITE_RULE_NODE_STREAM -antlr3RewriteRuleNODEStreamNewAEE(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description, void * oneElement) -{ - pANTLR3_REWRITE_RULE_NODE_STREAM stream; - - // First job is to create the memory we need. - // - stream = antlr3RewriteRuleElementStreamNewAEE(adaptor, rec, description, oneElement); - - // Install the node based overrides - // - stream->dup = dupTreeNode; - stream->toTree = toTreeNode; - stream->nextNode = nextNodeNode; - stream->free = freeNodeRS; - - return stream; -} - -ANTLR3_API pANTLR3_REWRITE_RULE_NODE_STREAM -antlr3RewriteRuleNODEStreamNewAEV(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description, pANTLR3_VECTOR vector) -{ - pANTLR3_REWRITE_RULE_NODE_STREAM stream; - - // First job is to create the memory we need. - // - stream = antlr3RewriteRuleElementStreamNewAEV(adaptor, rec, description, vector); - - // Install the Node based overrides - // - stream->dup = dupTreeNode; - stream->toTree = toTreeNode; - stream->nextNode = nextNodeNode; - stream->free = freeNodeRS; - - return stream; -} - -//---------------------------------------------------------------------- -// Static support functions - -/// Reset the condition of this stream so that it appears we have -/// not consumed any of its elements. Elements themselves are untouched. -/// -static void -reset (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) -{ - stream->dirty = ANTLR3_TRUE; - stream->cursor = 0; -} - -// Add a new pANTLR3_BASE_TREE to this stream -// -static void -add (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * el, void (ANTLR3_CDECL *freePtr)(void *)) -{ - if (el== NULL) - { - return; - } - // As we may be reusing a stream, we may already have allocated - // a rewrite stream vector. If we have then is will be empty if - // we have either zero or just one element in the rewrite stream - // - if (stream->elements != NULL && stream->elements->count > 0) - { - // We already have >1 entries in the stream. So we can just add this new element to the existing - // collection. - // - stream->elements->add(stream->elements, el, freePtr); - return; - } - if (stream->singleElement == NULL) - { - stream->singleElement = el; - return; - } - - // If we got here then we had only the one element so far - // and we must now create a vector to hold a collection of them - // - if (stream->elements == NULL) - { - pANTLR3_VECTOR_FACTORY factory = ((pANTLR3_COMMON_TREE_ADAPTOR)(stream->adaptor->super))->arboretum->vFactory; - - - stream->elements = factory->newVector(factory); - stream->freeElements = ANTLR3_TRUE; // We 'ummed it, so we play it son. - } - - stream->elements->add (stream->elements, stream->singleElement, freePtr); - stream->elements->add (stream->elements, el, freePtr); - stream->singleElement = NULL; - - return; -} - -/// Return the next element in the stream. If out of elements, throw -/// an exception unless size()==1. If size is 1, then return elements[0]. -/// Return a duplicate node/subtree if stream is out of elements and -/// size==1. If we've already used the element, dup (dirty bit set). -/// -static pANTLR3_BASE_TREE -nextTree(pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) -{ - ANTLR3_UINT32 n; - void * el; - - n = stream->size(stream); - - if ( stream->dirty || (stream->cursor >=n && n==1) ) - { - // if out of elements and size is 1, dup - // - el = stream->_next(stream); - return stream->dup(stream, el); - } - - // test size above then fetch - // - el = stream->_next(stream); - return el; -} - -/// Return the next element for a caller that wants just the token -/// -static void * -nextToken (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) -{ - return stream->_next(stream); -} - -/// Return the next element in the stream. If out of elements, throw -/// an exception unless size()==1. If size is 1, then return elements[0]. -/// -static void * -next (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) -{ - ANTLR3_UINT32 s; - - s = stream->size(stream); - if (stream->cursor >= s && s == 1) - { - pANTLR3_BASE_TREE el; - - el = stream->_next(stream); - - return stream->dup(stream, el); - } - - return stream->_next(stream); -} - -/// Do the work of getting the next element, making sure that it's -/// a tree node or subtree. Deal with the optimization of single- -/// element list versus list of size > 1. Throw an exception (or something similar) -/// if the stream is empty or we're out of elements and size>1. -/// You can override in a 'subclass' if necessary. -/// -static void * -_next (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) -{ - ANTLR3_UINT32 n; - pANTLR3_BASE_TREE t; - - n = stream->size(stream); - - if (n == 0) - { - // This means that the stream is empty - // - return NULL; // Caller must cope with this - } - - // Traversed all the available elements already? - // - if (stream->cursor >= n) - { - if (n == 1) - { - // Special case when size is single element, it will just dup a lot - // - return stream->toTree(stream, stream->singleElement); - } - - // 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 NULL; // Caller must cope with this - } - - // Elements available either for duping or just available - // - if (stream->singleElement != NULL) - { - stream->cursor++; // Cursor advances even for single element as this tells us to dup() - return stream->toTree(stream, stream->singleElement); - } - - // More than just a single element so we extract it from the - // vector. - // - t = stream->toTree(stream, stream->elements->get(stream->elements, stream->cursor)); - stream->cursor++; - return t; -} - -#ifdef ANTLR3_WINDOWS -#pragma warning(push) -#pragma warning(disable : 4100) -#endif -/// When constructing trees, sometimes we need to dup a token or AST -/// subtree. Dup'ing a token means just creating another AST node -/// around it. For trees, you must call the adaptor.dupTree(). -/// -static void * -dupTok (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * el) -{ - ANTLR3_FPRINTF(stderr, "dup() cannot be called on a token rewrite stream!!"); - return NULL; -} -#ifdef ANTLR3_WINDOWS -#pragma warning(pop) -#endif - -/// When constructing trees, sometimes we need to dup a token or AST -/// subtree. Dup'ing a token means just creating another AST node -/// around it. For trees, you must call the adaptor.dupTree(). -/// -static void * -dupTree (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * element) -{ - return stream->adaptor->dupNode(stream->adaptor, (pANTLR3_BASE_TREE)element); -} - -#ifdef ANTLR3_WINDOWS -#pragma warning(push) -#pragma warning(disable : 4100) -#endif -/// When constructing trees, sometimes we need to dup a token or AST -/// subtree. Dup'ing a token means just creating another AST node -/// around it. For trees, you must call the adaptor.dupTree(). -/// -static void * -dupTreeNode (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * element) -{ - ANTLR3_FPRINTF(stderr, "dup() cannot be called on a node rewrite stream!!!"); - return NULL; -} - - -/// We don;t explicitly convert to a tree unless the call goes to -/// nextTree, which means rewrites are heterogeneous -/// -static pANTLR3_BASE_TREE -toTree (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * element) -{ - return (pANTLR3_BASE_TREE)element; -} -#ifdef ANTLR3_WINDOWS -#pragma warning(pop) -#endif - -/// Ensure stream emits trees; tokens must be converted to AST nodes. -/// AST nodes can be passed through unmolested. -/// -#ifdef ANTLR3_WINDOWS -#pragma warning(push) -#pragma warning(disable : 4100) -#endif - -static pANTLR3_BASE_TREE -toTreeNode (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * element) -{ - return stream->adaptor->dupNode(stream->adaptor, (pANTLR3_BASE_TREE)element); -} - -#ifdef ANTLR3_WINDOWS -#pragma warning(pop) -#endif - -/// Returns ANTLR3_TRUE if there is a next element available -/// -static ANTLR3_BOOLEAN -hasNext (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) -{ - if ( (stream->singleElement != NULL && stream->cursor < 1) - || (stream->elements != NULL && stream->cursor < stream->elements->size(stream->elements))) - { - return ANTLR3_TRUE; - } - else - { - return ANTLR3_FALSE; - } -} - -/// Get the next token from the list and create a node for it -/// This is the implementation for token streams. -/// -static pANTLR3_BASE_TREE -nextNodeToken(pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) -{ - return stream->adaptor->create(stream->adaptor, stream->_next(stream)); -} - -static pANTLR3_BASE_TREE -nextNodeNode(pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) -{ - return stream->_next(stream); -} - -/// Treat next element as a single node even if it's a subtree. -/// This is used instead of next() when the result has to be a -/// tree root node. Also prevents us from duplicating recently-added -/// children; e.g., ^(type ID)+ adds ID to type and then 2nd iteration -/// must dup the type node, but ID has been added. -/// -/// Referencing to a rule result twice is ok; dup entire tree as -/// we can't be adding trees; e.g., expr expr. -/// -static pANTLR3_BASE_TREE -nextNode (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) -{ - - ANTLR3_UINT32 n; - pANTLR3_BASE_TREE el = stream->_next(stream); - - n = stream->size(stream); - if (stream->dirty == ANTLR3_TRUE || (stream->cursor > n && n == 1)) - { - // We are out of elements and the size is 1, which means we just - // dup the node that we have - // - return stream->adaptor->dupNode(stream->adaptor, el); - } - - // We were not out of nodes, so the one we received is the one to return - // - return el; -} - -/// Number of elements available in the stream -/// -static ANTLR3_UINT32 -size (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) -{ - ANTLR3_UINT32 n = 0; - - /// Should be a count of one if singleElement is set. I copied this - /// logic from the java implementation, which I suspect is just guarding - /// against someone setting singleElement and forgetting to NULL it out - /// - if (stream->singleElement != NULL) - { - n = 1; - } - else - { - if (stream->elements != NULL) - { - return (ANTLR3_UINT32)(stream->elements->count); - } - } - return n; -} - -/// Returns the description string if there is one available (check for NULL). -/// -static void * -getDescription (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) -{ - if (stream->elementDescription == NULL) - { - stream->elementDescription = ""; - } - - return stream->elementDescription; -} +/// \file +/// Implementation of token/tree streams that are used by the +/// tree re-write rules to manipulate the tokens and trees produced +/// by rules that are subject to rewrite directives. +/// + +// [The "BSD licence"] +// Copyright (c) 2005-2009 Jim Idle, Temporal Wave LLC +// http://www.temporal-wave.com +// http://www.linkedin.com/in/jimidle +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. The name of the author may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +// Static support function forward declarations for the stream types. +// +static void reset (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); +static void add (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * el, void (ANTLR3_CDECL *freePtr)(void *)); +static void * next (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); +static pANTLR3_BASE_TREE nextTree (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); +static void * nextToken (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); +static void * _next (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); +static void * dupTok (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * el); +static void * dupTree (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * el); +static void * dupTreeNode (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * el); +static pANTLR3_BASE_TREE toTree (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * element); +static pANTLR3_BASE_TREE toTreeNode (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * element); +static ANTLR3_BOOLEAN hasNext (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); +static pANTLR3_BASE_TREE nextNode (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); +static pANTLR3_BASE_TREE nextNodeNode (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); +static pANTLR3_BASE_TREE nextNodeToken (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); +static ANTLR3_UINT32 size (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); +static void * getDescription (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); +static void freeRS (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); +static void expungeRS (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream); + + +// Place a now unused rewrite stream back on the rewrite stream pool +// so we can reuse it if we need to. +// +static void +freeRS (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) +{ + // Before placing the stream back in the pool, we + // need to clear any vector it has. This is so any + // free pointers that are associated with the + // entires are called. + // + if (stream->elements != NULL) + { + // Factory generated vectors can be returned to the + // vector factory for later reuse. + // + if (stream->elements->factoryMade == ANTLR3_TRUE) + { + pANTLR3_VECTOR_FACTORY factory = ((pANTLR3_COMMON_TREE_ADAPTOR)(stream->adaptor->super))->arboretum->vFactory; + factory->returnVector(factory, stream->elements); + + stream->elements = NULL; + } + else + { + // Other vectors we clear and allow to be reused if they come off the + // rewrite stream free stack and are reused. + // + stream->elements->clear(stream->elements); + stream->freeElements = ANTLR3_TRUE; + } + } + else + { + stream->freeElements = ANTLR3_FALSE; // Just in case + } + + // Add the stream into the recognizer stream stack vector + // adding the stream memory free routine so that + // it is thrown away when the stack vector is destroyed + // + stream->rec->state->rStreams->add(stream->rec->state->rStreams, stream, (void(*)(void *))expungeRS); +} + +/** Do special nilNode reuse detection for node streams. + */ +static void +freeNodeRS(pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) +{ + pANTLR3_BASE_TREE tree; + + // Before placing the stream back in the pool, we + // need to clear any vector it has. This is so any + // free pointers that are associated with the + // entires are called. However, if this particular function is called + // then we know that the entries in the stream are definately + // tree nodes. Hence we check to see if any of them were nilNodes as + // if they were, we can reuse them. + // + if (stream->elements != NULL) + { + // We have some elements to traverse + // + ANTLR3_UINT32 i; + + for (i = 1; i<= stream->elements->count; i++) + { + tree = (pANTLR3_BASE_TREE)(stream->elements->elements[i-1].element); + if (tree != NULL && tree->isNilNode(tree)) + { + // Had to remove this for now, check is not comprehensive enough + // tree->reuse(tree); + } + + } + // Factory generated vectors can be returned to the + // vector factory for later reuse. + // + if (stream->elements->factoryMade == ANTLR3_TRUE) + { + pANTLR3_VECTOR_FACTORY factory = ((pANTLR3_COMMON_TREE_ADAPTOR)(stream->adaptor->super))->arboretum->vFactory; + factory->returnVector(factory, stream->elements); + + stream->elements = NULL; + } + else + { + stream->elements->clear(stream->elements); + stream->freeElements = ANTLR3_TRUE; + } + } + else + { + if (stream->singleElement != NULL) + { + tree = (pANTLR3_BASE_TREE)(stream->singleElement); + if (tree->isNilNode(tree)) + { + // Had to remove this for now, check is not comprehensive enough + // tree->reuse(tree); + } + } + stream->singleElement = NULL; + stream->freeElements = ANTLR3_FALSE; // Just in case + } + + // Add the stream into the recognizer stream stack vector + // adding the stream memory free routine so that + // it is thrown away when the stack vector is destroyed + // + stream->rec->state->rStreams->add(stream->rec->state->rStreams, stream, (void(*)(void *))expungeRS); +} +static void +expungeRS(pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) +{ + + if (stream->freeElements == ANTLR3_TRUE && stream->elements != NULL) + { + stream->elements->free(stream->elements); + } + ANTLR3_FREE(stream); +} + +// Functions for creating streams +// +static pANTLR3_REWRITE_RULE_ELEMENT_STREAM +antlr3RewriteRuleElementStreamNewAE(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description) +{ + pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream; + + // First - do we already have a rewrite stream that was returned + // to the pool? If we do, then we will just reuse it by resetting + // the generic interface. + // + if (rec->state->rStreams->count > 0) + { + // Remove the entry from the vector. We do not + // cause it to be freed by using remove. + // + stream = rec->state->rStreams->remove(rec->state->rStreams, rec->state->rStreams->count - 1); + + // We found a stream we can reuse. + // If the stream had a vector, then it will have been cleared + // when the freeRS was called that put it in this stack + // + } + else + { + // Ok, we need to allocate a new one as there were none on the stack. + // First job is to create the memory we need. + // + stream = (pANTLR3_REWRITE_RULE_ELEMENT_STREAM) ANTLR3_MALLOC((size_t)(sizeof(ANTLR3_REWRITE_RULE_ELEMENT_STREAM))); + + if (stream == NULL) + { + return NULL; + } + stream->elements = NULL; + stream->freeElements = ANTLR3_FALSE; + } + + // Populate the generic interface + // + stream->rec = rec; + stream->reset = reset; + stream->add = add; + stream->next = next; + stream->nextTree = nextTree; + stream->nextNode = nextNode; + stream->nextToken = nextToken; + stream->_next = _next; + stream->hasNext = hasNext; + stream->size = size; + stream->getDescription = getDescription; + stream->toTree = toTree; + stream->free = freeRS; + stream->singleElement = NULL; + + // Reset the stream to empty. + // + + stream->cursor = 0; + stream->dirty = ANTLR3_FALSE; + + // Install the description + // + stream->elementDescription = description; + + // Install the adaptor + // + stream->adaptor = adaptor; + + return stream; +} + +static pANTLR3_REWRITE_RULE_ELEMENT_STREAM +antlr3RewriteRuleElementStreamNewAEE(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description, void * oneElement) +{ + pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream; + + // First job is to create the memory we need. + // + stream = antlr3RewriteRuleElementStreamNewAE(adaptor, rec, description); + + if (stream == NULL) + { + return NULL; + } + + // Stream seems good so we need to add the supplied element + // + if (oneElement != NULL) + { + stream->add(stream, oneElement, NULL); + } + return stream; +} + +static pANTLR3_REWRITE_RULE_ELEMENT_STREAM +antlr3RewriteRuleElementStreamNewAEV(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description, pANTLR3_VECTOR vector) +{ + pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream; + + // First job is to create the memory we need. + // + stream = antlr3RewriteRuleElementStreamNewAE(adaptor, rec, description); + + if (stream == NULL) + { + return stream; + } + + // Stream seems good so we need to install the vector we were + // given. We assume that someone else is going to free the + // vector. + // + if (stream->elements != NULL && stream->elements->factoryMade == ANTLR3_FALSE && stream->freeElements == ANTLR3_TRUE ) + { + stream->elements->free(stream->elements); + } + stream->elements = vector; + stream->freeElements = ANTLR3_FALSE; + return stream; +} + +// Token rewrite stream ... +// +ANTLR3_API pANTLR3_REWRITE_RULE_TOKEN_STREAM +antlr3RewriteRuleTOKENStreamNewAE(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description) +{ + pANTLR3_REWRITE_RULE_TOKEN_STREAM stream; + + // First job is to create the memory we need. + // + stream = antlr3RewriteRuleElementStreamNewAE(adaptor, rec, description); + + if (stream == NULL) + { + return stream; + } + + // Install the token based overrides + // + stream->dup = dupTok; + stream->nextNode = nextNodeToken; + + // No nextNode implementation for a token rewrite stream + // + return stream; +} + +ANTLR3_API pANTLR3_REWRITE_RULE_TOKEN_STREAM +antlr3RewriteRuleTOKENStreamNewAEE(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description, void * oneElement) +{ + pANTLR3_REWRITE_RULE_TOKEN_STREAM stream; + + // First job is to create the memory we need. + // + stream = antlr3RewriteRuleElementStreamNewAEE(adaptor, rec, description, oneElement); + + // Install the token based overrides + // + stream->dup = dupTok; + stream->nextNode = nextNodeToken; + + // No nextNode implementation for a token rewrite stream + // + return stream; +} + +ANTLR3_API pANTLR3_REWRITE_RULE_TOKEN_STREAM +antlr3RewriteRuleTOKENStreamNewAEV(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description, pANTLR3_VECTOR vector) +{ + pANTLR3_REWRITE_RULE_TOKEN_STREAM stream; + + // First job is to create the memory we need. + // + stream = antlr3RewriteRuleElementStreamNewAEV(adaptor, rec, description, vector); + + // Install the token based overrides + // + stream->dup = dupTok; + stream->nextNode = nextNodeToken; + + // No nextNode implementation for a token rewrite stream + // + return stream; +} + +// Subtree rewrite stream +// +ANTLR3_API pANTLR3_REWRITE_RULE_SUBTREE_STREAM +antlr3RewriteRuleSubtreeStreamNewAE(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description) +{ + pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream; + + // First job is to create the memory we need. + // + stream = antlr3RewriteRuleElementStreamNewAE(adaptor, rec, description); + + if (stream == NULL) + { + return stream; + } + + // Install the subtree based overrides + // + stream->dup = dupTree; + stream->nextNode = nextNode; + stream->free = freeNodeRS; + return stream; + +} +ANTLR3_API pANTLR3_REWRITE_RULE_SUBTREE_STREAM +antlr3RewriteRuleSubtreeStreamNewAEE(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description, void * oneElement) +{ + pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream; + + // First job is to create the memory we need. + // + stream = antlr3RewriteRuleElementStreamNewAEE(adaptor, rec, description, oneElement); + + if (stream == NULL) + { + return stream; + } + + // Install the subtree based overrides + // + stream->dup = dupTree; + stream->nextNode = nextNode; + stream->free = freeNodeRS; + + return stream; +} + +ANTLR3_API pANTLR3_REWRITE_RULE_SUBTREE_STREAM +antlr3RewriteRuleSubtreeStreamNewAEV(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description, pANTLR3_VECTOR vector) +{ + pANTLR3_REWRITE_RULE_SUBTREE_STREAM stream; + + // First job is to create the memory we need. + // + stream = antlr3RewriteRuleElementStreamNewAEV(adaptor, rec, description, vector); + + if (stream == NULL) + { + return NULL; + } + + // Install the subtree based overrides + // + stream->dup = dupTree; + stream->nextNode = nextNode; + stream->free = freeNodeRS; + + return stream; +} +// Node rewrite stream ... +// +ANTLR3_API pANTLR3_REWRITE_RULE_NODE_STREAM +antlr3RewriteRuleNODEStreamNewAE(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description) +{ + pANTLR3_REWRITE_RULE_NODE_STREAM stream; + + // First job is to create the memory we need. + // + stream = antlr3RewriteRuleElementStreamNewAE(adaptor, rec, description); + + if (stream == NULL) + { + return stream; + } + + // Install the node based overrides + // + stream->dup = dupTreeNode; + stream->toTree = toTreeNode; + stream->nextNode = nextNodeNode; + stream->free = freeNodeRS; + + return stream; +} + +ANTLR3_API pANTLR3_REWRITE_RULE_NODE_STREAM +antlr3RewriteRuleNODEStreamNewAEE(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description, void * oneElement) +{ + pANTLR3_REWRITE_RULE_NODE_STREAM stream; + + // First job is to create the memory we need. + // + stream = antlr3RewriteRuleElementStreamNewAEE(adaptor, rec, description, oneElement); + + // Install the node based overrides + // + stream->dup = dupTreeNode; + stream->toTree = toTreeNode; + stream->nextNode = nextNodeNode; + stream->free = freeNodeRS; + + return stream; +} + +ANTLR3_API pANTLR3_REWRITE_RULE_NODE_STREAM +antlr3RewriteRuleNODEStreamNewAEV(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_RECOGNIZER rec, pANTLR3_UINT8 description, pANTLR3_VECTOR vector) +{ + pANTLR3_REWRITE_RULE_NODE_STREAM stream; + + // First job is to create the memory we need. + // + stream = antlr3RewriteRuleElementStreamNewAEV(adaptor, rec, description, vector); + + // Install the Node based overrides + // + stream->dup = dupTreeNode; + stream->toTree = toTreeNode; + stream->nextNode = nextNodeNode; + stream->free = freeNodeRS; + + return stream; +} + +//---------------------------------------------------------------------- +// Static support functions + +/// Reset the condition of this stream so that it appears we have +/// not consumed any of its elements. Elements themselves are untouched. +/// +static void +reset (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) +{ + stream->dirty = ANTLR3_TRUE; + stream->cursor = 0; +} + +// Add a new pANTLR3_BASE_TREE to this stream +// +static void +add (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * el, void (ANTLR3_CDECL *freePtr)(void *)) +{ + if (el== NULL) + { + return; + } + // As we may be reusing a stream, we may already have allocated + // a rewrite stream vector. If we have then is will be empty if + // we have either zero or just one element in the rewrite stream + // + if (stream->elements != NULL && stream->elements->count > 0) + { + // We already have >1 entries in the stream. So we can just add this new element to the existing + // collection. + // + stream->elements->add(stream->elements, el, freePtr); + return; + } + if (stream->singleElement == NULL) + { + stream->singleElement = el; + return; + } + + // If we got here then we had only the one element so far + // and we must now create a vector to hold a collection of them + // + if (stream->elements == NULL) + { + pANTLR3_VECTOR_FACTORY factory = ((pANTLR3_COMMON_TREE_ADAPTOR)(stream->adaptor->super))->arboretum->vFactory; + + + stream->elements = factory->newVector(factory); + stream->freeElements = ANTLR3_TRUE; // We 'ummed it, so we play it son. + } + + stream->elements->add (stream->elements, stream->singleElement, freePtr); + stream->elements->add (stream->elements, el, freePtr); + stream->singleElement = NULL; + + return; +} + +/// Return the next element in the stream. If out of elements, throw +/// an exception unless size()==1. If size is 1, then return elements[0]. +/// Return a duplicate node/subtree if stream is out of elements and +/// size==1. If we've already used the element, dup (dirty bit set). +/// +static pANTLR3_BASE_TREE +nextTree(pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) +{ + ANTLR3_UINT32 n; + void * el; + + n = stream->size(stream); + + if ( stream->dirty || (stream->cursor >=n && n==1) ) + { + // if out of elements and size is 1, dup + // + el = stream->_next(stream); + return stream->dup(stream, el); + } + + // test size above then fetch + // + el = stream->_next(stream); + return el; +} + +/// Return the next element for a caller that wants just the token +/// +static void * +nextToken (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) +{ + return stream->_next(stream); +} + +/// Return the next element in the stream. If out of elements, throw +/// an exception unless size()==1. If size is 1, then return elements[0]. +/// +static void * +next (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) +{ + ANTLR3_UINT32 s; + + s = stream->size(stream); + if (stream->cursor >= s && s == 1) + { + pANTLR3_BASE_TREE el; + + el = stream->_next(stream); + + return stream->dup(stream, el); + } + + return stream->_next(stream); +} + +/// Do the work of getting the next element, making sure that it's +/// a tree node or subtree. Deal with the optimization of single- +/// element list versus list of size > 1. Throw an exception (or something similar) +/// if the stream is empty or we're out of elements and size>1. +/// You can override in a 'subclass' if necessary. +/// +static void * +_next (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) +{ + ANTLR3_UINT32 n; + pANTLR3_BASE_TREE t; + + n = stream->size(stream); + + if (n == 0) + { + // This means that the stream is empty + // + return NULL; // Caller must cope with this + } + + // Traversed all the available elements already? + // + if (stream->cursor >= n) + { + if (n == 1) + { + // Special case when size is single element, it will just dup a lot + // + return stream->toTree(stream, stream->singleElement); + } + + // 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 NULL; // Caller must cope with this + } + + // Elements available either for duping or just available + // + if (stream->singleElement != NULL) + { + stream->cursor++; // Cursor advances even for single element as this tells us to dup() + return stream->toTree(stream, stream->singleElement); + } + + // More than just a single element so we extract it from the + // vector. + // + t = stream->toTree(stream, stream->elements->get(stream->elements, stream->cursor)); + stream->cursor++; + return t; +} + +#ifdef ANTLR3_WINDOWS +#pragma warning(push) +#pragma warning(disable : 4100) +#endif +/// When constructing trees, sometimes we need to dup a token or AST +/// subtree. Dup'ing a token means just creating another AST node +/// around it. For trees, you must call the adaptor.dupTree(). +/// +static void * +dupTok (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * el) +{ + ANTLR3_FPRINTF(stderr, "dup() cannot be called on a token rewrite stream!!"); + return NULL; +} +#ifdef ANTLR3_WINDOWS +#pragma warning(pop) +#endif + +/// When constructing trees, sometimes we need to dup a token or AST +/// subtree. Dup'ing a token means just creating another AST node +/// around it. For trees, you must call the adaptor.dupTree(). +/// +static void * +dupTree (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * element) +{ + return stream->adaptor->dupNode(stream->adaptor, (pANTLR3_BASE_TREE)element); +} + +#ifdef ANTLR3_WINDOWS +#pragma warning(push) +#pragma warning(disable : 4100) +#endif +/// When constructing trees, sometimes we need to dup a token or AST +/// subtree. Dup'ing a token means just creating another AST node +/// around it. For trees, you must call the adaptor.dupTree(). +/// +static void * +dupTreeNode (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * element) +{ + ANTLR3_FPRINTF(stderr, "dup() cannot be called on a node rewrite stream!!!"); + return NULL; +} + + +/// We don;t explicitly convert to a tree unless the call goes to +/// nextTree, which means rewrites are heterogeneous +/// +static pANTLR3_BASE_TREE +toTree (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * element) +{ + return (pANTLR3_BASE_TREE)element; +} +#ifdef ANTLR3_WINDOWS +#pragma warning(pop) +#endif + +/// Ensure stream emits trees; tokens must be converted to AST nodes. +/// AST nodes can be passed through unmolested. +/// +#ifdef ANTLR3_WINDOWS +#pragma warning(push) +#pragma warning(disable : 4100) +#endif + +static pANTLR3_BASE_TREE +toTreeNode (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream, void * element) +{ + return stream->adaptor->dupNode(stream->adaptor, (pANTLR3_BASE_TREE)element); +} + +#ifdef ANTLR3_WINDOWS +#pragma warning(pop) +#endif + +/// Returns ANTLR3_TRUE if there is a next element available +/// +static ANTLR3_BOOLEAN +hasNext (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) +{ + if ( (stream->singleElement != NULL && stream->cursor < 1) + || (stream->elements != NULL && stream->cursor < stream->elements->size(stream->elements))) + { + return ANTLR3_TRUE; + } + else + { + return ANTLR3_FALSE; + } +} + +/// Get the next token from the list and create a node for it +/// This is the implementation for token streams. +/// +static pANTLR3_BASE_TREE +nextNodeToken(pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) +{ + return stream->adaptor->create(stream->adaptor, stream->_next(stream)); +} + +static pANTLR3_BASE_TREE +nextNodeNode(pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) +{ + return stream->_next(stream); +} + +/// Treat next element as a single node even if it's a subtree. +/// This is used instead of next() when the result has to be a +/// tree root node. Also prevents us from duplicating recently-added +/// children; e.g., ^(type ID)+ adds ID to type and then 2nd iteration +/// must dup the type node, but ID has been added. +/// +/// Referencing to a rule result twice is ok; dup entire tree as +/// we can't be adding trees; e.g., expr expr. +/// +static pANTLR3_BASE_TREE +nextNode (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) +{ + + ANTLR3_UINT32 n; + pANTLR3_BASE_TREE el = stream->_next(stream); + + n = stream->size(stream); + if (stream->dirty == ANTLR3_TRUE || (stream->cursor > n && n == 1)) + { + // We are out of elements and the size is 1, which means we just + // dup the node that we have + // + return stream->adaptor->dupNode(stream->adaptor, el); + } + + // We were not out of nodes, so the one we received is the one to return + // + return el; +} + +/// Number of elements available in the stream +/// +static ANTLR3_UINT32 +size (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) +{ + ANTLR3_UINT32 n = 0; + + /// Should be a count of one if singleElement is set. I copied this + /// logic from the java implementation, which I suspect is just guarding + /// against someone setting singleElement and forgetting to NULL it out + /// + if (stream->singleElement != NULL) + { + n = 1; + } + else + { + if (stream->elements != NULL) + { + return (ANTLR3_UINT32)(stream->elements->count); + } + } + return n; +} + +/// Returns the description string if there is one available (check for NULL). +/// +static void * +getDescription (pANTLR3_REWRITE_RULE_ELEMENT_STREAM stream) +{ + if (stream->elementDescription == NULL) + { + stream->elementDescription = ""; + } + + return stream->elementDescription; +}