--- /dev/null
+/// \file\r
+/// Defines the implementation of the common node stream the default\r
+/// tree node stream used by ANTLR.\r
+///\r
+\r
+// [The "BSD licence"]\r
+// Copyright (c) 2005-2009 Jim Idle, Temporal Wave LLC\r
+// http://www.temporal-wave.com\r
+// http://www.linkedin.com/in/jimidle\r
+//\r
+// All rights reserved.\r
+//\r
+// Redistribution and use in source and binary forms, with or without\r
+// modification, are permitted provided that the following conditions\r
+// are met:\r
+// 1. Redistributions of source code must retain the above copyright\r
+// notice, this list of conditions and the following disclaimer.\r
+// 2. Redistributions in binary form must reproduce the above copyright\r
+// notice, this list of conditions and the following disclaimer in the\r
+// documentation and/or other materials provided with the distribution.\r
+// 3. The name of the author may not be used to endorse or promote products\r
+// derived from this software without specific prior written permission.\r
+//\r
+// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\r
+// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\r
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\r
+// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
+// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\r
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\r
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\r
+// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+\r
+#include <antlr3commontreenodestream.h>\r
+\r
+#ifdef ANTLR3_WINDOWS\r
+#pragma warning( disable : 4100 )\r
+#endif\r
+\r
+// COMMON TREE STREAM API\r
+//\r
+static void addNavigationNode (pANTLR3_COMMON_TREE_NODE_STREAM ctns, ANTLR3_UINT32 ttype);\r
+static ANTLR3_BOOLEAN hasUniqueNavigationNodes (pANTLR3_COMMON_TREE_NODE_STREAM ctns);\r
+static pANTLR3_BASE_TREE newDownNode (pANTLR3_COMMON_TREE_NODE_STREAM ctns);\r
+static pANTLR3_BASE_TREE newUpNode (pANTLR3_COMMON_TREE_NODE_STREAM ctns);\r
+static void reset (pANTLR3_COMMON_TREE_NODE_STREAM ctns);\r
+static void push (pANTLR3_COMMON_TREE_NODE_STREAM ctns, ANTLR3_INT32 index);\r
+static ANTLR3_INT32 pop (pANTLR3_COMMON_TREE_NODE_STREAM ctns);\r
+//static ANTLR3_INT32 index (pANTLR3_COMMON_TREE_NODE_STREAM ctns);\r
+static ANTLR3_UINT32 getLookaheadSize (pANTLR3_COMMON_TREE_NODE_STREAM ctns);\r
+// TREE NODE STREAM API\r
+//\r
+static pANTLR3_BASE_TREE_ADAPTOR getTreeAdaptor (pANTLR3_TREE_NODE_STREAM tns);\r
+static pANTLR3_BASE_TREE getTreeSource (pANTLR3_TREE_NODE_STREAM tns);\r
+static pANTLR3_BASE_TREE _LT (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_INT32 k);\r
+static pANTLR3_BASE_TREE get (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_INT32 k);\r
+static void setUniqueNavigationNodes (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_BOOLEAN uniqueNavigationNodes);\r
+static pANTLR3_STRING toString (pANTLR3_TREE_NODE_STREAM tns);\r
+static pANTLR3_STRING toStringSS (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE start, pANTLR3_BASE_TREE stop);\r
+static void toStringWork (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE start, pANTLR3_BASE_TREE stop, pANTLR3_STRING buf);\r
+static void replaceChildren (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE parent, ANTLR3_INT32 startChildIndex, ANTLR3_INT32 stopChildIndex, pANTLR3_BASE_TREE t);\r
+\r
+// INT STREAM API\r
+//\r
+static void consume (pANTLR3_INT_STREAM is);\r
+static ANTLR3_MARKER tindex (pANTLR3_INT_STREAM is);\r
+static ANTLR3_UINT32 _LA (pANTLR3_INT_STREAM is, ANTLR3_INT32 i);\r
+static ANTLR3_MARKER mark (pANTLR3_INT_STREAM is);\r
+static void release (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker);\r
+static void rewindMark (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker);\r
+static void rewindLast (pANTLR3_INT_STREAM is);\r
+static void seek (pANTLR3_INT_STREAM is, ANTLR3_MARKER index);\r
+static ANTLR3_UINT32 size (pANTLR3_INT_STREAM is);\r
+\r
+\r
+// Helper functions\r
+//\r
+static void fillBuffer (pANTLR3_COMMON_TREE_NODE_STREAM ctns, pANTLR3_BASE_TREE t);\r
+static void fillBufferRoot (pANTLR3_COMMON_TREE_NODE_STREAM ctns);\r
+\r
+// Constructors\r
+//\r
+static void antlr3TreeNodeStreamFree (pANTLR3_TREE_NODE_STREAM tns);\r
+static void antlr3CommonTreeNodeStreamFree (pANTLR3_COMMON_TREE_NODE_STREAM ctns);\r
+\r
+ANTLR3_API pANTLR3_TREE_NODE_STREAM\r
+antlr3TreeNodeStreamNew()\r
+{\r
+ pANTLR3_TREE_NODE_STREAM stream;\r
+\r
+ // Memory for the interface structure\r
+ //\r
+ stream = (pANTLR3_TREE_NODE_STREAM) ANTLR3_CALLOC(1, sizeof(ANTLR3_TREE_NODE_STREAM));\r
+\r
+ if (stream == NULL)\r
+ {\r
+ return NULL;\r
+ }\r
+\r
+ // Install basic API \r
+ //\r
+ stream->replaceChildren = replaceChildren;\r
+ stream->free = antlr3TreeNodeStreamFree;\r
+ \r
+ return stream;\r
+}\r
+\r
+static void\r
+antlr3TreeNodeStreamFree(pANTLR3_TREE_NODE_STREAM stream)\r
+{ \r
+ ANTLR3_FREE(stream);\r
+}\r
+\r
+ANTLR3_API pANTLR3_COMMON_TREE_NODE_STREAM\r
+antlr3CommonTreeNodeStreamNewTree(pANTLR3_BASE_TREE tree, ANTLR3_UINT32 hint)\r
+{\r
+ pANTLR3_COMMON_TREE_NODE_STREAM stream;\r
+\r
+ stream = antlr3CommonTreeNodeStreamNew(tree->strFactory, hint);\r
+\r
+ if (stream == NULL)\r
+ {\r
+ return NULL;\r
+ }\r
+ stream->root = tree;\r
+\r
+ return stream;\r
+}\r
+\r
+ANTLR3_API pANTLR3_COMMON_TREE_NODE_STREAM\r
+antlr3CommonTreeNodeStreamNewStream(pANTLR3_COMMON_TREE_NODE_STREAM inStream)\r
+{\r
+ pANTLR3_COMMON_TREE_NODE_STREAM stream;\r
+\r
+ // Memory for the interface structure\r
+ //\r
+ stream = (pANTLR3_COMMON_TREE_NODE_STREAM) ANTLR3_CALLOC(1, sizeof(ANTLR3_COMMON_TREE_NODE_STREAM));\r
+\r
+ if (stream == NULL)\r
+ {\r
+ return NULL;\r
+ }\r
+\r
+ // Copy in all the reusable parts of the originating stream and create new\r
+ // pieces where necessary.\r
+ //\r
+\r
+ // String factory for tree walker\r
+ //\r
+ stream->stringFactory = inStream->stringFactory;\r
+\r
+ // Create an adaptor for the common tree node stream\r
+ //\r
+ stream->adaptor = inStream->adaptor;\r
+\r
+ // Create space for the tree node stream interface\r
+ //\r
+ stream->tnstream = antlr3TreeNodeStreamNew();\r
+\r
+ if (stream->tnstream == NULL)\r
+ {\r
+ stream->free (stream);\r
+\r
+ return NULL;\r
+ }\r
+\r
+ // Create space for the INT_STREAM interface\r
+ //\r
+ stream->tnstream->istream = antlr3IntStreamNew();\r
+\r
+ if (stream->tnstream->istream == NULL)\r
+ {\r
+ stream->tnstream->free (stream->tnstream);\r
+ stream->free (stream);\r
+\r
+ return NULL;\r
+ }\r
+\r
+ // Install the common tree node stream API\r
+ //\r
+ stream->addNavigationNode = addNavigationNode;\r
+ stream->hasUniqueNavigationNodes = hasUniqueNavigationNodes;\r
+ stream->newDownNode = newDownNode;\r
+ stream->newUpNode = newUpNode;\r
+ stream->reset = reset;\r
+ stream->push = push;\r
+ stream->pop = pop;\r
+ stream->getLookaheadSize = getLookaheadSize;\r
+\r
+ stream->free = antlr3CommonTreeNodeStreamFree;\r
+\r
+ // Install the tree node stream API\r
+ //\r
+ stream->tnstream->getTreeAdaptor = getTreeAdaptor;\r
+ stream->tnstream->getTreeSource = getTreeSource;\r
+ stream->tnstream->_LT = _LT;\r
+ stream->tnstream->setUniqueNavigationNodes = setUniqueNavigationNodes;\r
+ stream->tnstream->toString = toString;\r
+ stream->tnstream->toStringSS = toStringSS;\r
+ stream->tnstream->toStringWork = toStringWork;\r
+ stream->tnstream->get = get;\r
+\r
+ // Install INT_STREAM interface\r
+ //\r
+ stream->tnstream->istream->consume = consume;\r
+ stream->tnstream->istream->index = tindex;\r
+ stream->tnstream->istream->_LA = _LA;\r
+ stream->tnstream->istream->mark = mark;\r
+ stream->tnstream->istream->release = release;\r
+ stream->tnstream->istream->rewind = rewindMark;\r
+ stream->tnstream->istream->rewindLast = rewindLast;\r
+ stream->tnstream->istream->seek = seek;\r
+ stream->tnstream->istream->size = size;\r
+\r
+ // Initialize data elements of INT stream\r
+ //\r
+ stream->tnstream->istream->type = ANTLR3_COMMONTREENODE;\r
+ stream->tnstream->istream->super = (stream->tnstream);\r
+\r
+ // Initialize data elements of TREE stream\r
+ //\r
+ stream->tnstream->ctns = stream;\r
+\r
+ // Initialize data elements of the COMMON TREE NODE stream\r
+ //\r
+ stream->super = NULL;\r
+ stream->uniqueNavigationNodes = ANTLR3_FALSE;\r
+ stream->markers = NULL;\r
+ stream->nodeStack = inStream->nodeStack;\r
+\r
+ // Create the node list map\r
+ //\r
+ stream->nodes = antlr3VectorNew(DEFAULT_INITIAL_BUFFER_SIZE);\r
+ stream->p = -1;\r
+\r
+ // Install the navigation nodes \r
+ //\r
+ \r
+ // Install the navigation nodes \r
+ //\r
+ antlr3SetCTAPI(&(stream->UP));\r
+ antlr3SetCTAPI(&(stream->DOWN));\r
+ antlr3SetCTAPI(&(stream->EOF_NODE));\r
+ antlr3SetCTAPI(&(stream->INVALID_NODE));\r
+\r
+ stream->UP.token = inStream->UP.token;\r
+ inStream->UP.token->strFactory = stream->stringFactory;\r
+ stream->DOWN.token = inStream->DOWN.token;\r
+ inStream->DOWN.token->strFactory = stream->stringFactory;\r
+ stream->EOF_NODE.token = inStream->EOF_NODE.token;\r
+ inStream->EOF_NODE.token->strFactory = stream->stringFactory;\r
+ stream->INVALID_NODE.token = inStream->INVALID_NODE.token;\r
+ inStream->INVALID_NODE.token->strFactory= stream->stringFactory;\r
+\r
+ // Reuse the root tree of the originating stream\r
+ //\r
+ stream->root = inStream->root;\r
+\r
+ // Signal that this is a rewriting stream so we don't\r
+ // free the originating tree. Anything that we rewrite or\r
+ // duplicate here will be done through the adaptor or \r
+ // the original tree factory.\r
+ //\r
+ stream->isRewriter = ANTLR3_TRUE;\r
+ return stream;\r
+}\r
+\r
+ANTLR3_API pANTLR3_COMMON_TREE_NODE_STREAM\r
+antlr3CommonTreeNodeStreamNew(pANTLR3_STRING_FACTORY strFactory, ANTLR3_UINT32 hint)\r
+{\r
+ pANTLR3_COMMON_TREE_NODE_STREAM stream;\r
+ pANTLR3_COMMON_TOKEN token;\r
+\r
+ // Memory for the interface structure\r
+ //\r
+ stream = (pANTLR3_COMMON_TREE_NODE_STREAM) ANTLR3_CALLOC(1, sizeof(ANTLR3_COMMON_TREE_NODE_STREAM));\r
+\r
+ if (stream == NULL)\r
+ {\r
+ return NULL;\r
+ }\r
+\r
+ // String factory for tree walker\r
+ //\r
+ stream->stringFactory = strFactory;\r
+\r
+ // Create an adaptor for the common tree node stream\r
+ //\r
+ stream->adaptor = ANTLR3_TREE_ADAPTORNew(strFactory);\r
+\r
+ if (stream->adaptor == NULL)\r
+ {\r
+ stream->free(stream);\r
+ return NULL;\r
+ }\r
+\r
+ // Create space for the tree node stream interface\r
+ //\r
+ stream->tnstream = antlr3TreeNodeStreamNew();\r
+\r
+ if (stream->tnstream == NULL)\r
+ {\r
+ stream->adaptor->free (stream->adaptor);\r
+ stream->free (stream);\r
+\r
+ return NULL;\r
+ }\r
+\r
+ // Create space for the INT_STREAM interface\r
+ //\r
+ stream->tnstream->istream = antlr3IntStreamNew();\r
+\r
+ if (stream->tnstream->istream == NULL)\r
+ {\r
+ stream->adaptor->free (stream->adaptor);\r
+ stream->tnstream->free (stream->tnstream);\r
+ stream->free (stream);\r
+\r
+ return NULL;\r
+ }\r
+\r
+ // Install the common tree node stream API\r
+ //\r
+ stream->addNavigationNode = addNavigationNode;\r
+ stream->hasUniqueNavigationNodes = hasUniqueNavigationNodes;\r
+ stream->newDownNode = newDownNode;\r
+ stream->newUpNode = newUpNode;\r
+ stream->reset = reset;\r
+ stream->push = push;\r
+ stream->pop = pop;\r
+\r
+ stream->free = antlr3CommonTreeNodeStreamFree;\r
+\r
+ // Install the tree node stream API\r
+ //\r
+ stream->tnstream->getTreeAdaptor = getTreeAdaptor;\r
+ stream->tnstream->getTreeSource = getTreeSource;\r
+ stream->tnstream->_LT = _LT;\r
+ stream->tnstream->setUniqueNavigationNodes = setUniqueNavigationNodes;\r
+ stream->tnstream->toString = toString;\r
+ stream->tnstream->toStringSS = toStringSS;\r
+ stream->tnstream->toStringWork = toStringWork;\r
+ stream->tnstream->get = get;\r
+\r
+ // Install INT_STREAM interface\r
+ //\r
+ stream->tnstream->istream->consume = consume;\r
+ stream->tnstream->istream->index = tindex;\r
+ stream->tnstream->istream->_LA = _LA;\r
+ stream->tnstream->istream->mark = mark;\r
+ stream->tnstream->istream->release = release;\r
+ stream->tnstream->istream->rewind = rewindMark;\r
+ stream->tnstream->istream->rewindLast = rewindLast;\r
+ stream->tnstream->istream->seek = seek;\r
+ stream->tnstream->istream->size = size;\r
+\r
+ // Initialize data elements of INT stream\r
+ //\r
+ stream->tnstream->istream->type = ANTLR3_COMMONTREENODE;\r
+ stream->tnstream->istream->super = (stream->tnstream);\r
+\r
+ // Initialize data elements of TREE stream\r
+ //\r
+ stream->tnstream->ctns = stream;\r
+\r
+ // Initialize data elements of the COMMON TREE NODE stream\r
+ //\r
+ stream->super = NULL;\r
+ stream->uniqueNavigationNodes = ANTLR3_FALSE;\r
+ stream->markers = NULL;\r
+ stream->nodeStack = antlr3StackNew(INITIAL_CALL_STACK_SIZE);\r
+\r
+ // Create the node list map\r
+ //\r
+ if (hint == 0)\r
+ {\r
+ hint = DEFAULT_INITIAL_BUFFER_SIZE;\r
+ }\r
+ stream->nodes = antlr3VectorNew(hint);\r
+ stream->p = -1;\r
+\r
+ // Install the navigation nodes \r
+ //\r
+ antlr3SetCTAPI(&(stream->UP));\r
+ antlr3SetCTAPI(&(stream->DOWN));\r
+ antlr3SetCTAPI(&(stream->EOF_NODE));\r
+ antlr3SetCTAPI(&(stream->INVALID_NODE));\r
+\r
+ token = antlr3CommonTokenNew(ANTLR3_TOKEN_UP);\r
+ token->strFactory = strFactory;\r
+ token->textState = ANTLR3_TEXT_CHARP;\r
+ token->tokText.chars = (pANTLR3_UCHAR)"UP";\r
+ stream->UP.token = token;\r
+\r
+ token = antlr3CommonTokenNew(ANTLR3_TOKEN_DOWN);\r
+ token->strFactory = strFactory;\r
+ token->textState = ANTLR3_TEXT_CHARP;\r
+ token->tokText.chars = (pANTLR3_UCHAR)"DOWN";\r
+ stream->DOWN.token = token;\r
+\r
+ token = antlr3CommonTokenNew(ANTLR3_TOKEN_EOF);\r
+ token->strFactory = strFactory;\r
+ token->textState = ANTLR3_TEXT_CHARP;\r
+ token->tokText.chars = (pANTLR3_UCHAR)"EOF";\r
+ stream->EOF_NODE.token = token;\r
+\r
+ token = antlr3CommonTokenNew(ANTLR3_TOKEN_INVALID);\r
+ token->strFactory = strFactory;\r
+ token->textState = ANTLR3_TEXT_CHARP;\r
+ token->tokText.chars = (pANTLR3_UCHAR)"INVALID";\r
+ stream->INVALID_NODE.token = token;\r
+\r
+\r
+ return stream;\r
+}\r
+\r
+/// Free up any resources that belong to this common tree node stream.\r
+///\r
+static void antlr3CommonTreeNodeStreamFree (pANTLR3_COMMON_TREE_NODE_STREAM ctns)\r
+{\r
+\r
+ // If this is a rewrting stream, then certain resources\r
+ // belong to the originating node stream and we do not\r
+ // free them here.\r
+ //\r
+ if (ctns->isRewriter != ANTLR3_TRUE)\r
+ {\r
+ ctns->adaptor ->free (ctns->adaptor);\r
+\r
+ if (ctns->nodeStack != NULL)\r
+ {\r
+ ctns->nodeStack->free(ctns->nodeStack);\r
+ }\r
+\r
+ ANTLR3_FREE(ctns->INVALID_NODE.token);\r
+ ANTLR3_FREE(ctns->EOF_NODE.token);\r
+ ANTLR3_FREE(ctns->DOWN.token);\r
+ ANTLR3_FREE(ctns->UP.token);\r
+ }\r
+ \r
+ if (ctns->nodes != NULL)\r
+ {\r
+ ctns->nodes ->free (ctns->nodes);\r
+ }\r
+ ctns->tnstream->istream ->free (ctns->tnstream->istream);\r
+ ctns->tnstream ->free (ctns->tnstream);\r
+\r
+\r
+ ANTLR3_FREE(ctns);\r
+}\r
+\r
+// ------------------------------------------------------------------------------\r
+// Local helpers\r
+//\r
+\r
+/// Walk and fill the tree node buffer from the root tree\r
+///\r
+static void\r
+fillBufferRoot(pANTLR3_COMMON_TREE_NODE_STREAM ctns)\r
+{\r
+ // Call the generic buffer routine with the root as the\r
+ // argument\r
+ //\r
+ fillBuffer(ctns, ctns->root);\r
+ ctns->p = 0; // Indicate we are at buffer start\r
+}\r
+\r
+/// Walk tree with depth-first-search and fill nodes buffer.\r
+/// Don't add in DOWN, UP nodes if the supplied tree is a list (t is isNilNode)\r
+// such as the root tree is.\r
+///\r
+static void\r
+fillBuffer(pANTLR3_COMMON_TREE_NODE_STREAM ctns, pANTLR3_BASE_TREE t)\r
+{\r
+ ANTLR3_BOOLEAN nilNode;\r
+ ANTLR3_UINT32 nCount;\r
+ ANTLR3_UINT32 c;\r
+\r
+ nilNode = ctns->adaptor->isNilNode(ctns->adaptor, t);\r
+\r
+ // If the supplied node is not a nil (list) node then we\r
+ // add in the node itself to the vector\r
+ //\r
+ if (nilNode == ANTLR3_FALSE)\r
+ {\r
+ ctns->nodes->add(ctns->nodes, t, NULL); \r
+ }\r
+\r
+ // Only add a DOWN node if the tree is not a nil tree and\r
+ // the tree does have children.\r
+ //\r
+ nCount = t->getChildCount(t);\r
+\r
+ if (nilNode == ANTLR3_FALSE && nCount>0)\r
+ {\r
+ ctns->addNavigationNode(ctns, ANTLR3_TOKEN_DOWN);\r
+ }\r
+\r
+ // We always add any children the tree contains, which is\r
+ // a recursive call to this function, which will cause similar\r
+ // recursion and implement a depth first addition\r
+ //\r
+ for (c = 0; c < nCount; c++)\r
+ {\r
+ fillBuffer(ctns, ctns->adaptor->getChild(ctns->adaptor, t, c));\r
+ }\r
+\r
+ // If the tree had children and was not a nil (list) node, then we\r
+ // we need to add an UP node here to match the DOWN node\r
+ //\r
+ if (nilNode == ANTLR3_FALSE && nCount > 0)\r
+ {\r
+ ctns->addNavigationNode(ctns, ANTLR3_TOKEN_UP);\r
+ }\r
+}\r
+\r
+\r
+// ------------------------------------------------------------------------------\r
+// Interface functions\r
+//\r
+\r
+/// Reset the input stream to the start of the input nodes.\r
+///\r
+static void \r
+reset (pANTLR3_COMMON_TREE_NODE_STREAM ctns)\r
+{\r
+ if (ctns->p != -1)\r
+ {\r
+ ctns->p = 0;\r
+ }\r
+ ctns->tnstream->istream->lastMarker = 0;\r
+\r
+\r
+ // Free and reset the node stack only if this is not\r
+ // a rewriter, which is going to reuse the originating\r
+ // node streams node stack\r
+ //\r
+ if (ctns->isRewriter != ANTLR3_TRUE)\r
+ {\r
+ if (ctns->nodeStack != NULL)\r
+ {\r
+ ctns->nodeStack->free(ctns->nodeStack);\r
+ ctns->nodeStack = antlr3StackNew(INITIAL_CALL_STACK_SIZE);\r
+ }\r
+ }\r
+}\r
+\r
+\r
+static pANTLR3_BASE_TREE\r
+LB(pANTLR3_TREE_NODE_STREAM tns, ANTLR3_INT32 k)\r
+{\r
+ if ( k==0)\r
+ {\r
+ return &(tns->ctns->INVALID_NODE.baseTree);\r
+ }\r
+\r
+ if ( (tns->ctns->p - k) < 0)\r
+ {\r
+ return &(tns->ctns->INVALID_NODE.baseTree);\r
+ }\r
+\r
+ return tns->ctns->nodes->get(tns->ctns->nodes, tns->ctns->p - k);\r
+}\r
+\r
+/// Get tree node at current input pointer + i ahead where i=1 is next node.\r
+/// i<0 indicates nodes in the past. So -1 is previous node and -2 is\r
+/// two nodes ago. LT(0) is undefined. For i>=n, return null.\r
+/// Return null for LT(0) and any index that results in an absolute address\r
+/// that is negative.\r
+///\r
+/// This is analogous to the _LT() method of the TokenStream, but this\r
+/// returns a tree node instead of a token. Makes code gen identical\r
+/// for both parser and tree grammars. :)\r
+///\r
+static pANTLR3_BASE_TREE \r
+_LT (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_INT32 k)\r
+{\r
+ if (tns->ctns->p == -1)\r
+ {\r
+ fillBufferRoot(tns->ctns);\r
+ }\r
+\r
+ if (k < 0)\r
+ {\r
+ return LB(tns, -k);\r
+ }\r
+ else if (k == 0)\r
+ {\r
+ return &(tns->ctns->INVALID_NODE.baseTree);\r
+ }\r
+\r
+ // k was a legitimate request, \r
+ //\r
+ if (( tns->ctns->p + k - 1) >= (ANTLR3_INT32)(tns->ctns->nodes->count))\r
+ {\r
+ return &(tns->ctns->EOF_NODE.baseTree);\r
+ }\r
+\r
+ return tns->ctns->nodes->get(tns->ctns->nodes, tns->ctns->p + k - 1);\r
+}\r
+\r
+/// Where is this stream pulling nodes from? This is not the name, but\r
+/// the object that provides node objects.\r
+///\r
+static pANTLR3_BASE_TREE \r
+getTreeSource (pANTLR3_TREE_NODE_STREAM tns)\r
+{\r
+ return tns->ctns->root;\r
+}\r
+\r
+/// Consume the next node from the input stream\r
+///\r
+static void \r
+consume (pANTLR3_INT_STREAM is)\r
+{\r
+ pANTLR3_TREE_NODE_STREAM tns;\r
+ pANTLR3_COMMON_TREE_NODE_STREAM ctns;\r
+\r
+ tns = (pANTLR3_TREE_NODE_STREAM)(is->super);\r
+ ctns = tns->ctns;\r
+\r
+ if (ctns->p == -1)\r
+ {\r
+ fillBufferRoot(ctns);\r
+ }\r
+ ctns->p++;\r
+}\r
+\r
+static ANTLR3_UINT32 \r
+_LA (pANTLR3_INT_STREAM is, ANTLR3_INT32 i)\r
+{\r
+ pANTLR3_TREE_NODE_STREAM tns;\r
+ pANTLR3_BASE_TREE t;\r
+\r
+ tns = (pANTLR3_TREE_NODE_STREAM)(is->super);\r
+\r
+ // Ask LT for the 'token' at that position\r
+ //\r
+ t = tns->_LT(tns, i);\r
+\r
+ if (t == NULL)\r
+ {\r
+ return ANTLR3_TOKEN_INVALID;\r
+ }\r
+\r
+ // Token node was there so return the type of it\r
+ //\r
+ return t->getType(t);\r
+}\r
+\r
+/// Mark the state of the input stream so that we can come back to it\r
+/// after a syntactic predicate and so on.\r
+///\r
+static ANTLR3_MARKER \r
+mark (pANTLR3_INT_STREAM is)\r
+{\r
+ pANTLR3_TREE_NODE_STREAM tns;\r
+ pANTLR3_COMMON_TREE_NODE_STREAM ctns;\r
+\r
+ tns = (pANTLR3_TREE_NODE_STREAM)(is->super);\r
+ ctns = tns->ctns;\r
+\r
+ if (tns->ctns->p == -1)\r
+ {\r
+ fillBufferRoot(tns->ctns);\r
+ }\r
+\r
+ // Return the current mark point\r
+ //\r
+ ctns->tnstream->istream->lastMarker = ctns->tnstream->istream->index(ctns->tnstream->istream);\r
+\r
+ return ctns->tnstream->istream->lastMarker;\r
+}\r
+\r
+static void \r
+release (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker)\r
+{\r
+}\r
+\r
+/// Rewind the current state of the tree walk to the state it\r
+/// was in when mark() was called and it returned marker. Also,\r
+/// wipe out the lookahead which will force reloading a few nodes\r
+/// but it is better than making a copy of the lookahead buffer\r
+/// upon mark().\r
+///\r
+static void \r
+rewindMark (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker)\r
+{\r
+ is->seek(is, marker);\r
+}\r
+\r
+static void \r
+rewindLast (pANTLR3_INT_STREAM is)\r
+{\r
+ is->seek(is, is->lastMarker);\r
+}\r
+\r
+/// consume() ahead until we hit index. Can't just jump ahead--must\r
+/// spit out the navigation nodes.\r
+///\r
+static void \r
+seek (pANTLR3_INT_STREAM is, ANTLR3_MARKER index)\r
+{\r
+ pANTLR3_TREE_NODE_STREAM tns;\r
+ pANTLR3_COMMON_TREE_NODE_STREAM ctns;\r
+\r
+ tns = (pANTLR3_TREE_NODE_STREAM)(is->super);\r
+ ctns = tns->ctns;\r
+\r
+ ctns->p = ANTLR3_UINT32_CAST(index);\r
+}\r
+\r
+static ANTLR3_MARKER \r
+tindex (pANTLR3_INT_STREAM is)\r
+{\r
+ pANTLR3_TREE_NODE_STREAM tns;\r
+ pANTLR3_COMMON_TREE_NODE_STREAM ctns;\r
+\r
+ tns = (pANTLR3_TREE_NODE_STREAM)(is->super);\r
+ ctns = tns->ctns;\r
+\r
+ return (ANTLR3_MARKER)(ctns->p);\r
+}\r
+\r
+/// Expensive to compute the size of the whole tree while parsing.\r
+/// This method only returns how much input has been seen so far. So\r
+/// after parsing it returns true size.\r
+///\r
+static ANTLR3_UINT32 \r
+size (pANTLR3_INT_STREAM is)\r
+{\r
+ pANTLR3_TREE_NODE_STREAM tns;\r
+ pANTLR3_COMMON_TREE_NODE_STREAM ctns;\r
+\r
+ tns = (pANTLR3_TREE_NODE_STREAM)(is->super);\r
+ ctns = tns->ctns;\r
+\r
+ if (ctns->p == -1)\r
+ {\r
+ fillBufferRoot(ctns);\r
+ }\r
+\r
+ return ctns->nodes->size(ctns->nodes);\r
+}\r
+\r
+/// As we flatten the tree, we use UP, DOWN nodes to represent\r
+/// the tree structure. When debugging we need unique nodes\r
+/// so instantiate new ones when uniqueNavigationNodes is true.\r
+///\r
+static void \r
+addNavigationNode (pANTLR3_COMMON_TREE_NODE_STREAM ctns, ANTLR3_UINT32 ttype)\r
+{\r
+ pANTLR3_BASE_TREE node;\r
+\r
+ node = NULL;\r
+\r
+ if (ttype == ANTLR3_TOKEN_DOWN)\r
+ {\r
+ if (ctns->hasUniqueNavigationNodes(ctns) == ANTLR3_TRUE)\r
+ {\r
+ node = ctns->newDownNode(ctns);\r
+ }\r
+ else\r
+ {\r
+ node = &(ctns->DOWN.baseTree);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ if (ctns->hasUniqueNavigationNodes(ctns) == ANTLR3_TRUE)\r
+ {\r
+ node = ctns->newUpNode(ctns);\r
+ }\r
+ else\r
+ {\r
+ node = &(ctns->UP.baseTree);\r
+ }\r
+ }\r
+\r
+ // Now add the node we decided upon.\r
+ //\r
+ ctns->nodes->add(ctns->nodes, node, NULL);\r
+}\r
+\r
+\r
+static pANTLR3_BASE_TREE_ADAPTOR \r
+getTreeAdaptor (pANTLR3_TREE_NODE_STREAM tns)\r
+{\r
+ return tns->ctns->adaptor;\r
+}\r
+\r
+static ANTLR3_BOOLEAN \r
+hasUniqueNavigationNodes (pANTLR3_COMMON_TREE_NODE_STREAM ctns)\r
+{\r
+ return ctns->uniqueNavigationNodes;\r
+}\r
+\r
+static void \r
+setUniqueNavigationNodes (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_BOOLEAN uniqueNavigationNodes)\r
+{\r
+ tns->ctns->uniqueNavigationNodes = uniqueNavigationNodes;\r
+}\r
+\r
+\r
+/// Print out the entire tree including DOWN/UP nodes. Uses\r
+/// a recursive walk. Mostly useful for testing as it yields\r
+/// the token types not text.\r
+///\r
+static pANTLR3_STRING \r
+toString (pANTLR3_TREE_NODE_STREAM tns)\r
+{\r
+\r
+ return tns->toStringSS(tns, tns->ctns->root, NULL);\r
+}\r
+\r
+static pANTLR3_STRING \r
+toStringSS (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE start, pANTLR3_BASE_TREE stop)\r
+{\r
+ pANTLR3_STRING buf;\r
+\r
+ buf = tns->ctns->stringFactory->newRaw(tns->ctns->stringFactory);\r
+\r
+ tns->toStringWork(tns, start, stop, buf);\r
+\r
+ return buf;\r
+}\r
+\r
+static void \r
+toStringWork (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE p, pANTLR3_BASE_TREE stop, pANTLR3_STRING buf)\r
+{\r
+\r
+ ANTLR3_UINT32 n;\r
+ ANTLR3_UINT32 c;\r
+\r
+ if (!p->isNilNode(p) )\r
+ {\r
+ pANTLR3_STRING text;\r
+\r
+ text = p->toString(p);\r
+\r
+ if (text == NULL)\r
+ {\r
+ text = tns->ctns->stringFactory->newRaw(tns->ctns->stringFactory);\r
+\r
+ text->addc (text, ' ');\r
+ text->addi (text, p->getType(p));\r
+ }\r
+\r
+ buf->appendS(buf, text);\r
+ }\r
+\r
+ if (p == stop)\r
+ {\r
+ return; /* Finished */\r
+ }\r
+\r
+ n = p->getChildCount(p);\r
+\r
+ if (n > 0 && ! p->isNilNode(p) )\r
+ {\r
+ buf->addc (buf, ' ');\r
+ buf->addi (buf, ANTLR3_TOKEN_DOWN);\r
+ }\r
+\r
+ for (c = 0; c<n ; c++)\r
+ {\r
+ pANTLR3_BASE_TREE child;\r
+\r
+ child = p->getChild(p, c);\r
+ tns->toStringWork(tns, child, stop, buf);\r
+ }\r
+\r
+ if (n > 0 && ! p->isNilNode(p) )\r
+ {\r
+ buf->addc (buf, ' ');\r
+ buf->addi (buf, ANTLR3_TOKEN_UP);\r
+ }\r
+}\r
+\r
+static ANTLR3_UINT32 \r
+getLookaheadSize (pANTLR3_COMMON_TREE_NODE_STREAM ctns)\r
+{\r
+ return ctns->tail < ctns->head \r
+ ? (ctns->lookAheadLength - ctns->head + ctns->tail)\r
+ : (ctns->tail - ctns->head);\r
+}\r
+\r
+static pANTLR3_BASE_TREE \r
+newDownNode (pANTLR3_COMMON_TREE_NODE_STREAM ctns)\r
+{\r
+ pANTLR3_COMMON_TREE dNode;\r
+ pANTLR3_COMMON_TOKEN token;\r
+\r
+ token = antlr3CommonTokenNew(ANTLR3_TOKEN_DOWN);\r
+ token->textState = ANTLR3_TEXT_CHARP;\r
+ token->tokText.chars = (pANTLR3_UCHAR)"DOWN";\r
+ dNode = antlr3CommonTreeNewFromToken(token);\r
+\r
+ return &(dNode->baseTree);\r
+}\r
+\r
+static pANTLR3_BASE_TREE \r
+newUpNode (pANTLR3_COMMON_TREE_NODE_STREAM ctns)\r
+{\r
+ pANTLR3_COMMON_TREE uNode;\r
+ pANTLR3_COMMON_TOKEN token;\r
+\r
+ token = antlr3CommonTokenNew(ANTLR3_TOKEN_UP);\r
+ token->textState = ANTLR3_TEXT_CHARP;\r
+ token->tokText.chars = (pANTLR3_UCHAR)"UP";\r
+ uNode = antlr3CommonTreeNewFromToken(token);\r
+\r
+ return &(uNode->baseTree);\r
+}\r
+\r
+/// Replace from start to stop child index of parent with t, which might\r
+/// be a list. Number of children may be different\r
+/// after this call. The stream is notified because it is walking the\r
+/// tree and might need to know you are monkey-ing with the underlying\r
+/// tree. Also, it might be able to modify the node stream to avoid\r
+/// re-streaming for future phases.\r
+///\r
+/// If parent is null, don't do anything; must be at root of overall tree.\r
+/// Can't replace whatever points to the parent externally. Do nothing.\r
+///\r
+static void \r
+replaceChildren (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE parent, ANTLR3_INT32 startChildIndex, ANTLR3_INT32 stopChildIndex, pANTLR3_BASE_TREE t)\r
+{\r
+ if (parent != NULL)\r
+ {\r
+ pANTLR3_BASE_TREE_ADAPTOR adaptor;\r
+ pANTLR3_COMMON_TREE_ADAPTOR cta;\r
+\r
+ adaptor = tns->getTreeAdaptor(tns);\r
+ cta = (pANTLR3_COMMON_TREE_ADAPTOR)(adaptor->super);\r
+\r
+ adaptor->replaceChildren(adaptor, parent, startChildIndex, stopChildIndex, t);\r
+ }\r
+}\r
+\r
+static pANTLR3_BASE_TREE\r
+get (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_INT32 k)\r
+{\r
+ if (tns->ctns->p == -1)\r
+ {\r
+ fillBufferRoot(tns->ctns);\r
+ }\r
+\r
+ return tns->ctns->nodes->get(tns->ctns->nodes, k);\r
+}\r
+\r
+static void\r
+push (pANTLR3_COMMON_TREE_NODE_STREAM ctns, ANTLR3_INT32 index)\r
+{\r
+ ctns->nodeStack->push(ctns->nodeStack, ANTLR3_FUNC_PTR(ctns->p), NULL); // Save current index\r
+ ctns->tnstream->istream->seek(ctns->tnstream->istream, index);\r
+}\r
+\r
+static ANTLR3_INT32\r
+pop (pANTLR3_COMMON_TREE_NODE_STREAM ctns)\r
+{\r
+ ANTLR3_INT32 retVal;\r
+\r
+ retVal = ANTLR3_UINT32_CAST(ctns->nodeStack->pop(ctns->nodeStack));\r
+ ctns->tnstream->istream->seek(ctns->tnstream->istream, retVal);\r
+ return retVal;\r
+}\r