/// \file /// Defines the implementation of the common node stream the default /// tree node stream used by ANTLR. /// // [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 <antlr3commontreenodestream.h> #ifdef ANTLR3_WINDOWS #pragma warning( disable : 4100 ) #endif // COMMON TREE STREAM API // static void addNavigationNode (pANTLR3_COMMON_TREE_NODE_STREAM ctns, ANTLR3_UINT32 ttype); static ANTLR3_BOOLEAN hasUniqueNavigationNodes (pANTLR3_COMMON_TREE_NODE_STREAM ctns); static pANTLR3_BASE_TREE newDownNode (pANTLR3_COMMON_TREE_NODE_STREAM ctns); static pANTLR3_BASE_TREE newUpNode (pANTLR3_COMMON_TREE_NODE_STREAM ctns); static void reset (pANTLR3_COMMON_TREE_NODE_STREAM ctns); static void push (pANTLR3_COMMON_TREE_NODE_STREAM ctns, ANTLR3_INT32 index); static ANTLR3_INT32 pop (pANTLR3_COMMON_TREE_NODE_STREAM ctns); //static ANTLR3_INT32 index (pANTLR3_COMMON_TREE_NODE_STREAM ctns); static ANTLR3_UINT32 getLookaheadSize (pANTLR3_COMMON_TREE_NODE_STREAM ctns); // TREE NODE STREAM API // static pANTLR3_BASE_TREE_ADAPTOR getTreeAdaptor (pANTLR3_TREE_NODE_STREAM tns); static pANTLR3_BASE_TREE getTreeSource (pANTLR3_TREE_NODE_STREAM tns); static pANTLR3_BASE_TREE _LT (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_INT32 k); static pANTLR3_BASE_TREE get (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_INT32 k); static void setUniqueNavigationNodes (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_BOOLEAN uniqueNavigationNodes); static pANTLR3_STRING toString (pANTLR3_TREE_NODE_STREAM tns); static pANTLR3_STRING toStringSS (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE start, pANTLR3_BASE_TREE stop); static void toStringWork (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE start, pANTLR3_BASE_TREE stop, pANTLR3_STRING buf); static void replaceChildren (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE parent, ANTLR3_INT32 startChildIndex, ANTLR3_INT32 stopChildIndex, pANTLR3_BASE_TREE t); // INT STREAM API // static void consume (pANTLR3_INT_STREAM is); static ANTLR3_MARKER tindex (pANTLR3_INT_STREAM is); static ANTLR3_UINT32 _LA (pANTLR3_INT_STREAM is, ANTLR3_INT32 i); static ANTLR3_MARKER mark (pANTLR3_INT_STREAM is); static void release (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker); static void rewindMark (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker); static void rewindLast (pANTLR3_INT_STREAM is); static void seek (pANTLR3_INT_STREAM is, ANTLR3_MARKER index); static ANTLR3_UINT32 size (pANTLR3_INT_STREAM is); // Helper functions // static void fillBuffer (pANTLR3_COMMON_TREE_NODE_STREAM ctns, pANTLR3_BASE_TREE t); static void fillBufferRoot (pANTLR3_COMMON_TREE_NODE_STREAM ctns); // Constructors // static void antlr3TreeNodeStreamFree (pANTLR3_TREE_NODE_STREAM tns); static void antlr3CommonTreeNodeStreamFree (pANTLR3_COMMON_TREE_NODE_STREAM ctns); ANTLR3_API pANTLR3_TREE_NODE_STREAM antlr3TreeNodeStreamNew() { pANTLR3_TREE_NODE_STREAM stream; // Memory for the interface structure // stream = (pANTLR3_TREE_NODE_STREAM) ANTLR3_CALLOC(1, sizeof(ANTLR3_TREE_NODE_STREAM)); if (stream == NULL) { return NULL; } // Install basic API // stream->replaceChildren = replaceChildren; stream->free = antlr3TreeNodeStreamFree; return stream; } static void antlr3TreeNodeStreamFree(pANTLR3_TREE_NODE_STREAM stream) { ANTLR3_FREE(stream); } ANTLR3_API pANTLR3_COMMON_TREE_NODE_STREAM antlr3CommonTreeNodeStreamNewTree(pANTLR3_BASE_TREE tree, ANTLR3_UINT32 hint) { pANTLR3_COMMON_TREE_NODE_STREAM stream; stream = antlr3CommonTreeNodeStreamNew(tree->strFactory, hint); if (stream == NULL) { return NULL; } stream->root = tree; return stream; } ANTLR3_API pANTLR3_COMMON_TREE_NODE_STREAM antlr3CommonTreeNodeStreamNewStream(pANTLR3_COMMON_TREE_NODE_STREAM inStream) { pANTLR3_COMMON_TREE_NODE_STREAM stream; // Memory for the interface structure // stream = (pANTLR3_COMMON_TREE_NODE_STREAM) ANTLR3_CALLOC(1, sizeof(ANTLR3_COMMON_TREE_NODE_STREAM)); if (stream == NULL) { return NULL; } // Copy in all the reusable parts of the originating stream and create new // pieces where necessary. // // String factory for tree walker // stream->stringFactory = inStream->stringFactory; // Create an adaptor for the common tree node stream // stream->adaptor = inStream->adaptor; // Create space for the tree node stream interface // stream->tnstream = antlr3TreeNodeStreamNew(); if (stream->tnstream == NULL) { stream->free (stream); return NULL; } // Create space for the INT_STREAM interface // stream->tnstream->istream = antlr3IntStreamNew(); if (stream->tnstream->istream == NULL) { stream->tnstream->free (stream->tnstream); stream->free (stream); return NULL; } // Install the common tree node stream API // stream->addNavigationNode = addNavigationNode; stream->hasUniqueNavigationNodes = hasUniqueNavigationNodes; stream->newDownNode = newDownNode; stream->newUpNode = newUpNode; stream->reset = reset; stream->push = push; stream->pop = pop; stream->getLookaheadSize = getLookaheadSize; stream->free = antlr3CommonTreeNodeStreamFree; // Install the tree node stream API // stream->tnstream->getTreeAdaptor = getTreeAdaptor; stream->tnstream->getTreeSource = getTreeSource; stream->tnstream->_LT = _LT; stream->tnstream->setUniqueNavigationNodes = setUniqueNavigationNodes; stream->tnstream->toString = toString; stream->tnstream->toStringSS = toStringSS; stream->tnstream->toStringWork = toStringWork; stream->tnstream->get = get; // Install INT_STREAM interface // stream->tnstream->istream->consume = consume; stream->tnstream->istream->index = tindex; stream->tnstream->istream->_LA = _LA; stream->tnstream->istream->mark = mark; stream->tnstream->istream->release = release; stream->tnstream->istream->rewind = rewindMark; stream->tnstream->istream->rewindLast = rewindLast; stream->tnstream->istream->seek = seek; stream->tnstream->istream->size = size; // Initialize data elements of INT stream // stream->tnstream->istream->type = ANTLR3_COMMONTREENODE; stream->tnstream->istream->super = (stream->tnstream); // Initialize data elements of TREE stream // stream->tnstream->ctns = stream; // Initialize data elements of the COMMON TREE NODE stream // stream->super = NULL; stream->uniqueNavigationNodes = ANTLR3_FALSE; stream->markers = NULL; stream->nodeStack = inStream->nodeStack; // Create the node list map // stream->nodes = antlr3VectorNew(DEFAULT_INITIAL_BUFFER_SIZE); stream->p = -1; // Install the navigation nodes // // Install the navigation nodes // antlr3SetCTAPI(&(stream->UP)); antlr3SetCTAPI(&(stream->DOWN)); antlr3SetCTAPI(&(stream->EOF_NODE)); antlr3SetCTAPI(&(stream->INVALID_NODE)); stream->UP.token = inStream->UP.token; inStream->UP.token->strFactory = stream->stringFactory; stream->DOWN.token = inStream->DOWN.token; inStream->DOWN.token->strFactory = stream->stringFactory; stream->EOF_NODE.token = inStream->EOF_NODE.token; inStream->EOF_NODE.token->strFactory = stream->stringFactory; stream->INVALID_NODE.token = inStream->INVALID_NODE.token; inStream->INVALID_NODE.token->strFactory= stream->stringFactory; // Reuse the root tree of the originating stream // stream->root = inStream->root; // Signal that this is a rewriting stream so we don't // free the originating tree. Anything that we rewrite or // duplicate here will be done through the adaptor or // the original tree factory. // stream->isRewriter = ANTLR3_TRUE; return stream; } ANTLR3_API pANTLR3_COMMON_TREE_NODE_STREAM antlr3CommonTreeNodeStreamNew(pANTLR3_STRING_FACTORY strFactory, ANTLR3_UINT32 hint) { pANTLR3_COMMON_TREE_NODE_STREAM stream; pANTLR3_COMMON_TOKEN token; // Memory for the interface structure // stream = (pANTLR3_COMMON_TREE_NODE_STREAM) ANTLR3_CALLOC(1, sizeof(ANTLR3_COMMON_TREE_NODE_STREAM)); if (stream == NULL) { return NULL; } // String factory for tree walker // stream->stringFactory = strFactory; // Create an adaptor for the common tree node stream // stream->adaptor = ANTLR3_TREE_ADAPTORNew(strFactory); if (stream->adaptor == NULL) { stream->free(stream); return NULL; } // Create space for the tree node stream interface // stream->tnstream = antlr3TreeNodeStreamNew(); if (stream->tnstream == NULL) { stream->adaptor->free (stream->adaptor); stream->free (stream); return NULL; } // Create space for the INT_STREAM interface // stream->tnstream->istream = antlr3IntStreamNew(); if (stream->tnstream->istream == NULL) { stream->adaptor->free (stream->adaptor); stream->tnstream->free (stream->tnstream); stream->free (stream); return NULL; } // Install the common tree node stream API // stream->addNavigationNode = addNavigationNode; stream->hasUniqueNavigationNodes = hasUniqueNavigationNodes; stream->newDownNode = newDownNode; stream->newUpNode = newUpNode; stream->reset = reset; stream->push = push; stream->pop = pop; stream->free = antlr3CommonTreeNodeStreamFree; // Install the tree node stream API // stream->tnstream->getTreeAdaptor = getTreeAdaptor; stream->tnstream->getTreeSource = getTreeSource; stream->tnstream->_LT = _LT; stream->tnstream->setUniqueNavigationNodes = setUniqueNavigationNodes; stream->tnstream->toString = toString; stream->tnstream->toStringSS = toStringSS; stream->tnstream->toStringWork = toStringWork; stream->tnstream->get = get; // Install INT_STREAM interface // stream->tnstream->istream->consume = consume; stream->tnstream->istream->index = tindex; stream->tnstream->istream->_LA = _LA; stream->tnstream->istream->mark = mark; stream->tnstream->istream->release = release; stream->tnstream->istream->rewind = rewindMark; stream->tnstream->istream->rewindLast = rewindLast; stream->tnstream->istream->seek = seek; stream->tnstream->istream->size = size; // Initialize data elements of INT stream // stream->tnstream->istream->type = ANTLR3_COMMONTREENODE; stream->tnstream->istream->super = (stream->tnstream); // Initialize data elements of TREE stream // stream->tnstream->ctns = stream; // Initialize data elements of the COMMON TREE NODE stream // stream->super = NULL; stream->uniqueNavigationNodes = ANTLR3_FALSE; stream->markers = NULL; stream->nodeStack = antlr3StackNew(INITIAL_CALL_STACK_SIZE); // Create the node list map // if (hint == 0) { hint = DEFAULT_INITIAL_BUFFER_SIZE; } stream->nodes = antlr3VectorNew(hint); stream->p = -1; // Install the navigation nodes // antlr3SetCTAPI(&(stream->UP)); antlr3SetCTAPI(&(stream->DOWN)); antlr3SetCTAPI(&(stream->EOF_NODE)); antlr3SetCTAPI(&(stream->INVALID_NODE)); token = antlr3CommonTokenNew(ANTLR3_TOKEN_UP); token->strFactory = strFactory; token->textState = ANTLR3_TEXT_CHARP; token->tokText.chars = (pANTLR3_UCHAR)"UP"; stream->UP.token = token; token = antlr3CommonTokenNew(ANTLR3_TOKEN_DOWN); token->strFactory = strFactory; token->textState = ANTLR3_TEXT_CHARP; token->tokText.chars = (pANTLR3_UCHAR)"DOWN"; stream->DOWN.token = token; token = antlr3CommonTokenNew(ANTLR3_TOKEN_EOF); token->strFactory = strFactory; token->textState = ANTLR3_TEXT_CHARP; token->tokText.chars = (pANTLR3_UCHAR)"EOF"; stream->EOF_NODE.token = token; token = antlr3CommonTokenNew(ANTLR3_TOKEN_INVALID); token->strFactory = strFactory; token->textState = ANTLR3_TEXT_CHARP; token->tokText.chars = (pANTLR3_UCHAR)"INVALID"; stream->INVALID_NODE.token = token; return stream; } /// Free up any resources that belong to this common tree node stream. /// static void antlr3CommonTreeNodeStreamFree (pANTLR3_COMMON_TREE_NODE_STREAM ctns) { // If this is a rewrting stream, then certain resources // belong to the originating node stream and we do not // free them here. // if (ctns->isRewriter != ANTLR3_TRUE) { ctns->adaptor ->free (ctns->adaptor); if (ctns->nodeStack != NULL) { ctns->nodeStack->free(ctns->nodeStack); } ANTLR3_FREE(ctns->INVALID_NODE.token); ANTLR3_FREE(ctns->EOF_NODE.token); ANTLR3_FREE(ctns->DOWN.token); ANTLR3_FREE(ctns->UP.token); } if (ctns->nodes != NULL) { ctns->nodes ->free (ctns->nodes); } ctns->tnstream->istream ->free (ctns->tnstream->istream); ctns->tnstream ->free (ctns->tnstream); ANTLR3_FREE(ctns); } // ------------------------------------------------------------------------------ // Local helpers // /// Walk and fill the tree node buffer from the root tree /// static void fillBufferRoot(pANTLR3_COMMON_TREE_NODE_STREAM ctns) { // Call the generic buffer routine with the root as the // argument // fillBuffer(ctns, ctns->root); ctns->p = 0; // Indicate we are at buffer start } /// Walk tree with depth-first-search and fill nodes buffer. /// Don't add in DOWN, UP nodes if the supplied tree is a list (t is isNilNode) // such as the root tree is. /// static void fillBuffer(pANTLR3_COMMON_TREE_NODE_STREAM ctns, pANTLR3_BASE_TREE t) { ANTLR3_BOOLEAN nilNode; ANTLR3_UINT32 nCount; ANTLR3_UINT32 c; nilNode = ctns->adaptor->isNilNode(ctns->adaptor, t); // If the supplied node is not a nil (list) node then we // add in the node itself to the vector // if (nilNode == ANTLR3_FALSE) { ctns->nodes->add(ctns->nodes, t, NULL); } // Only add a DOWN node if the tree is not a nil tree and // the tree does have children. // nCount = t->getChildCount(t); if (nilNode == ANTLR3_FALSE && nCount>0) { ctns->addNavigationNode(ctns, ANTLR3_TOKEN_DOWN); } // We always add any children the tree contains, which is // a recursive call to this function, which will cause similar // recursion and implement a depth first addition // for (c = 0; c < nCount; c++) { fillBuffer(ctns, ctns->adaptor->getChild(ctns->adaptor, t, c)); } // If the tree had children and was not a nil (list) node, then we // we need to add an UP node here to match the DOWN node // if (nilNode == ANTLR3_FALSE && nCount > 0) { ctns->addNavigationNode(ctns, ANTLR3_TOKEN_UP); } } // ------------------------------------------------------------------------------ // Interface functions // /// Reset the input stream to the start of the input nodes. /// static void reset (pANTLR3_COMMON_TREE_NODE_STREAM ctns) { if (ctns->p != -1) { ctns->p = 0; } ctns->tnstream->istream->lastMarker = 0; // Free and reset the node stack only if this is not // a rewriter, which is going to reuse the originating // node streams node stack // if (ctns->isRewriter != ANTLR3_TRUE) { if (ctns->nodeStack != NULL) { ctns->nodeStack->free(ctns->nodeStack); ctns->nodeStack = antlr3StackNew(INITIAL_CALL_STACK_SIZE); } } } static pANTLR3_BASE_TREE LB(pANTLR3_TREE_NODE_STREAM tns, ANTLR3_INT32 k) { if ( k==0) { return &(tns->ctns->INVALID_NODE.baseTree); } if ( (tns->ctns->p - k) < 0) { return &(tns->ctns->INVALID_NODE.baseTree); } return tns->ctns->nodes->get(tns->ctns->nodes, tns->ctns->p - k); } /// Get tree node at current input pointer + i ahead where i=1 is next node. /// i<0 indicates nodes in the past. So -1 is previous node and -2 is /// two nodes ago. LT(0) is undefined. For i>=n, return null. /// Return null for LT(0) and any index that results in an absolute address /// that is negative. /// /// This is analogous to the _LT() method of the TokenStream, but this /// returns a tree node instead of a token. Makes code gen identical /// for both parser and tree grammars. :) /// static pANTLR3_BASE_TREE _LT (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_INT32 k) { if (tns->ctns->p == -1) { fillBufferRoot(tns->ctns); } if (k < 0) { return LB(tns, -k); } else if (k == 0) { return &(tns->ctns->INVALID_NODE.baseTree); } // k was a legitimate request, // if (( tns->ctns->p + k - 1) >= (ANTLR3_INT32)(tns->ctns->nodes->count)) { return &(tns->ctns->EOF_NODE.baseTree); } return tns->ctns->nodes->get(tns->ctns->nodes, tns->ctns->p + k - 1); } /// Where is this stream pulling nodes from? This is not the name, but /// the object that provides node objects. /// static pANTLR3_BASE_TREE getTreeSource (pANTLR3_TREE_NODE_STREAM tns) { return tns->ctns->root; } /// Consume the next node from the input stream /// static void consume (pANTLR3_INT_STREAM is) { pANTLR3_TREE_NODE_STREAM tns; pANTLR3_COMMON_TREE_NODE_STREAM ctns; tns = (pANTLR3_TREE_NODE_STREAM)(is->super); ctns = tns->ctns; if (ctns->p == -1) { fillBufferRoot(ctns); } ctns->p++; } static ANTLR3_UINT32 _LA (pANTLR3_INT_STREAM is, ANTLR3_INT32 i) { pANTLR3_TREE_NODE_STREAM tns; pANTLR3_BASE_TREE t; tns = (pANTLR3_TREE_NODE_STREAM)(is->super); // Ask LT for the 'token' at that position // t = tns->_LT(tns, i); if (t == NULL) { return ANTLR3_TOKEN_INVALID; } // Token node was there so return the type of it // return t->getType(t); } /// Mark the state of the input stream so that we can come back to it /// after a syntactic predicate and so on. /// static ANTLR3_MARKER mark (pANTLR3_INT_STREAM is) { pANTLR3_TREE_NODE_STREAM tns; pANTLR3_COMMON_TREE_NODE_STREAM ctns; tns = (pANTLR3_TREE_NODE_STREAM)(is->super); ctns = tns->ctns; if (tns->ctns->p == -1) { fillBufferRoot(tns->ctns); } // Return the current mark point // ctns->tnstream->istream->lastMarker = ctns->tnstream->istream->index(ctns->tnstream->istream); return ctns->tnstream->istream->lastMarker; } static void release (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker) { } /// Rewind the current state of the tree walk to the state it /// was in when mark() was called and it returned marker. Also, /// wipe out the lookahead which will force reloading a few nodes /// but it is better than making a copy of the lookahead buffer /// upon mark(). /// static void rewindMark (pANTLR3_INT_STREAM is, ANTLR3_MARKER marker) { is->seek(is, marker); } static void rewindLast (pANTLR3_INT_STREAM is) { is->seek(is, is->lastMarker); } /// consume() ahead until we hit index. Can't just jump ahead--must /// spit out the navigation nodes. /// static void seek (pANTLR3_INT_STREAM is, ANTLR3_MARKER index) { pANTLR3_TREE_NODE_STREAM tns; pANTLR3_COMMON_TREE_NODE_STREAM ctns; tns = (pANTLR3_TREE_NODE_STREAM)(is->super); ctns = tns->ctns; ctns->p = ANTLR3_UINT32_CAST(index); } static ANTLR3_MARKER tindex (pANTLR3_INT_STREAM is) { pANTLR3_TREE_NODE_STREAM tns; pANTLR3_COMMON_TREE_NODE_STREAM ctns; tns = (pANTLR3_TREE_NODE_STREAM)(is->super); ctns = tns->ctns; return (ANTLR3_MARKER)(ctns->p); } /// Expensive to compute the size of the whole tree while parsing. /// This method only returns how much input has been seen so far. So /// after parsing it returns true size. /// static ANTLR3_UINT32 size (pANTLR3_INT_STREAM is) { pANTLR3_TREE_NODE_STREAM tns; pANTLR3_COMMON_TREE_NODE_STREAM ctns; tns = (pANTLR3_TREE_NODE_STREAM)(is->super); ctns = tns->ctns; if (ctns->p == -1) { fillBufferRoot(ctns); } return ctns->nodes->size(ctns->nodes); } /// As we flatten the tree, we use UP, DOWN nodes to represent /// the tree structure. When debugging we need unique nodes /// so instantiate new ones when uniqueNavigationNodes is true. /// static void addNavigationNode (pANTLR3_COMMON_TREE_NODE_STREAM ctns, ANTLR3_UINT32 ttype) { pANTLR3_BASE_TREE node; node = NULL; if (ttype == ANTLR3_TOKEN_DOWN) { if (ctns->hasUniqueNavigationNodes(ctns) == ANTLR3_TRUE) { node = ctns->newDownNode(ctns); } else { node = &(ctns->DOWN.baseTree); } } else { if (ctns->hasUniqueNavigationNodes(ctns) == ANTLR3_TRUE) { node = ctns->newUpNode(ctns); } else { node = &(ctns->UP.baseTree); } } // Now add the node we decided upon. // ctns->nodes->add(ctns->nodes, node, NULL); } static pANTLR3_BASE_TREE_ADAPTOR getTreeAdaptor (pANTLR3_TREE_NODE_STREAM tns) { return tns->ctns->adaptor; } static ANTLR3_BOOLEAN hasUniqueNavigationNodes (pANTLR3_COMMON_TREE_NODE_STREAM ctns) { return ctns->uniqueNavigationNodes; } static void setUniqueNavigationNodes (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_BOOLEAN uniqueNavigationNodes) { tns->ctns->uniqueNavigationNodes = uniqueNavigationNodes; } /// Print out the entire tree including DOWN/UP nodes. Uses /// a recursive walk. Mostly useful for testing as it yields /// the token types not text. /// static pANTLR3_STRING toString (pANTLR3_TREE_NODE_STREAM tns) { return tns->toStringSS(tns, tns->ctns->root, NULL); } static pANTLR3_STRING toStringSS (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE start, pANTLR3_BASE_TREE stop) { pANTLR3_STRING buf; buf = tns->ctns->stringFactory->newRaw(tns->ctns->stringFactory); tns->toStringWork(tns, start, stop, buf); return buf; } static void toStringWork (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE p, pANTLR3_BASE_TREE stop, pANTLR3_STRING buf) { ANTLR3_UINT32 n; ANTLR3_UINT32 c; if (!p->isNilNode(p) ) { pANTLR3_STRING text; text = p->toString(p); if (text == NULL) { text = tns->ctns->stringFactory->newRaw(tns->ctns->stringFactory); text->addc (text, ' '); text->addi (text, p->getType(p)); } buf->appendS(buf, text); } if (p == stop) { return; /* Finished */ } n = p->getChildCount(p); if (n > 0 && ! p->isNilNode(p) ) { buf->addc (buf, ' '); buf->addi (buf, ANTLR3_TOKEN_DOWN); } for (c = 0; c<n ; c++) { pANTLR3_BASE_TREE child; child = p->getChild(p, c); tns->toStringWork(tns, child, stop, buf); } if (n > 0 && ! p->isNilNode(p) ) { buf->addc (buf, ' '); buf->addi (buf, ANTLR3_TOKEN_UP); } } static ANTLR3_UINT32 getLookaheadSize (pANTLR3_COMMON_TREE_NODE_STREAM ctns) { return ctns->tail < ctns->head ? (ctns->lookAheadLength - ctns->head + ctns->tail) : (ctns->tail - ctns->head); } static pANTLR3_BASE_TREE newDownNode (pANTLR3_COMMON_TREE_NODE_STREAM ctns) { pANTLR3_COMMON_TREE dNode; pANTLR3_COMMON_TOKEN token; token = antlr3CommonTokenNew(ANTLR3_TOKEN_DOWN); token->textState = ANTLR3_TEXT_CHARP; token->tokText.chars = (pANTLR3_UCHAR)"DOWN"; dNode = antlr3CommonTreeNewFromToken(token); return &(dNode->baseTree); } static pANTLR3_BASE_TREE newUpNode (pANTLR3_COMMON_TREE_NODE_STREAM ctns) { pANTLR3_COMMON_TREE uNode; pANTLR3_COMMON_TOKEN token; token = antlr3CommonTokenNew(ANTLR3_TOKEN_UP); token->textState = ANTLR3_TEXT_CHARP; token->tokText.chars = (pANTLR3_UCHAR)"UP"; uNode = antlr3CommonTreeNewFromToken(token); return &(uNode->baseTree); } /// Replace from start to stop child index of parent with t, which might /// be a list. Number of children may be different /// after this call. The stream is notified because it is walking the /// tree and might need to know you are monkey-ing with the underlying /// tree. Also, it might be able to modify the node stream to avoid /// re-streaming for future phases. /// /// If parent is null, don't do anything; must be at root of overall tree. /// Can't replace whatever points to the parent externally. Do nothing. /// static void replaceChildren (pANTLR3_TREE_NODE_STREAM tns, pANTLR3_BASE_TREE parent, ANTLR3_INT32 startChildIndex, ANTLR3_INT32 stopChildIndex, pANTLR3_BASE_TREE t) { if (parent != NULL) { pANTLR3_BASE_TREE_ADAPTOR adaptor; pANTLR3_COMMON_TREE_ADAPTOR cta; adaptor = tns->getTreeAdaptor(tns); cta = (pANTLR3_COMMON_TREE_ADAPTOR)(adaptor->super); adaptor->replaceChildren(adaptor, parent, startChildIndex, stopChildIndex, t); } } static pANTLR3_BASE_TREE get (pANTLR3_TREE_NODE_STREAM tns, ANTLR3_INT32 k) { if (tns->ctns->p == -1) { fillBufferRoot(tns->ctns); } return tns->ctns->nodes->get(tns->ctns->nodes, k); } static void push (pANTLR3_COMMON_TREE_NODE_STREAM ctns, ANTLR3_INT32 index) { ctns->nodeStack->push(ctns->nodeStack, ANTLR3_FUNC_PTR(ctns->p), NULL); // Save current index ctns->tnstream->istream->seek(ctns->tnstream->istream, index); } static ANTLR3_INT32 pop (pANTLR3_COMMON_TREE_NODE_STREAM ctns) { ANTLR3_INT32 retVal; retVal = ANTLR3_UINT32_CAST(ctns->nodeStack->pop(ctns->nodeStack)); ctns->tnstream->istream->seek(ctns->tnstream->istream, retVal); return retVal; }