blob: 9afb6e1ec5141e1a4e61b58c2fb9423251914bb4 [file] [log] [blame]
/// \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 <antlr3rewritestreams.h>
// 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 = "<unknown source>";
}
return stream->elementDescription;
}