blob: e35878fa8ad24f18dda42bd8177e1e2eb89c3849 [file] [log] [blame]
/** \file
* Contains the base functions that all tree adaptors start with.
* this implementation can then be overridden by any higher implementation.
*
*/
// [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 <antlr3basetreeadaptor.h>
#ifdef ANTLR3_WINDOWS
#pragma warning( disable : 4100 )
#endif
/* Interface functions
*/
static pANTLR3_BASE_TREE nilNode (pANTLR3_BASE_TREE_ADAPTOR adaptor);
static pANTLR3_BASE_TREE dbgNil (pANTLR3_BASE_TREE_ADAPTOR adaptor);
static pANTLR3_BASE_TREE dupTree (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t);
static pANTLR3_BASE_TREE dbgDupTree (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t);
static pANTLR3_BASE_TREE dupTreeTT (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, pANTLR3_BASE_TREE parent);
static void addChild (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, pANTLR3_BASE_TREE child);
static void dbgAddChild (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, pANTLR3_BASE_TREE child);
static pANTLR3_BASE_TREE becomeRoot (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE newRoot, pANTLR3_BASE_TREE oldRoot);
static pANTLR3_BASE_TREE dbgBecomeRoot (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE newRoot, pANTLR3_BASE_TREE oldRoot);
static pANTLR3_BASE_TREE rulePostProcessing (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE root);
static void addChildToken (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, pANTLR3_COMMON_TOKEN child);
static void dbgAddChildToken (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, pANTLR3_COMMON_TOKEN child);
static pANTLR3_BASE_TREE becomeRootToken (pANTLR3_BASE_TREE_ADAPTOR adaptor, void * newRoot, pANTLR3_BASE_TREE oldRoot);
static pANTLR3_BASE_TREE dbgBecomeRootToken (pANTLR3_BASE_TREE_ADAPTOR adaptor, void * newRoot, pANTLR3_BASE_TREE oldRoot);
static pANTLR3_BASE_TREE createTypeToken (pANTLR3_BASE_TREE_ADAPTOR adaptor, ANTLR3_UINT32 tokenType, pANTLR3_COMMON_TOKEN fromToken);
static pANTLR3_BASE_TREE dbgCreateTypeToken (pANTLR3_BASE_TREE_ADAPTOR adaptor, ANTLR3_UINT32 tokenType, pANTLR3_COMMON_TOKEN fromToken);
static pANTLR3_BASE_TREE createTypeTokenText (pANTLR3_BASE_TREE_ADAPTOR adaptor, ANTLR3_UINT32 tokenType, pANTLR3_COMMON_TOKEN fromToken, pANTLR3_UINT8 text);
static pANTLR3_BASE_TREE dbgCreateTypeTokenText (pANTLR3_BASE_TREE_ADAPTOR adaptor, ANTLR3_UINT32 tokenType, pANTLR3_COMMON_TOKEN fromToken, pANTLR3_UINT8 text);
static pANTLR3_BASE_TREE createTypeText (pANTLR3_BASE_TREE_ADAPTOR adaptor, ANTLR3_UINT32 tokenType, pANTLR3_UINT8 text);
static pANTLR3_BASE_TREE dbgCreateTypeText (pANTLR3_BASE_TREE_ADAPTOR adaptor, ANTLR3_UINT32 tokenType, pANTLR3_UINT8 text);
static ANTLR3_UINT32 getType (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t);
static void setType (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, ANTLR3_UINT32 type);
static pANTLR3_STRING getText (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t);
static void setText (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_STRING t);
static void setText8 (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_UINT8 t);
static pANTLR3_BASE_TREE getChild (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, ANTLR3_UINT32 i);
static ANTLR3_UINT32 getChildCount (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t);
static ANTLR3_UINT32 getUniqueID (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t);
static ANTLR3_BOOLEAN isNilNode (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t);
static pANTLR3_STRING makeDot (pANTLR3_BASE_TREE_ADAPTOR adaptor, void * theTree);
/** Given a pointer to a base tree adaptor structure (which is usually embedded in the
* super class the implements the tree adaptor used in the parse), initialize its
* function pointers and so on.
*/
ANTLR3_API void
antlr3BaseTreeAdaptorInit(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_DEBUG_EVENT_LISTENER debugger)
{
// Initialize the interface
//
if (debugger == NULL)
{
adaptor->nilNode = (void * (*)(pANTLR3_BASE_TREE_ADAPTOR))
nilNode;
adaptor->addChild = (void (*)(pANTLR3_BASE_TREE_ADAPTOR, void *, void *))
addChild;
adaptor->becomeRoot = (void * (*)(pANTLR3_BASE_TREE_ADAPTOR, void *, void *))
becomeRoot;
adaptor->addChildToken = (void (*)(pANTLR3_BASE_TREE_ADAPTOR, void *, pANTLR3_COMMON_TOKEN))
addChildToken;
adaptor->becomeRootToken = (void * (*)(pANTLR3_BASE_TREE_ADAPTOR, void *, void *))
becomeRootToken;
adaptor->createTypeToken = (void * (*)(pANTLR3_BASE_TREE_ADAPTOR, ANTLR3_UINT32, pANTLR3_COMMON_TOKEN))
createTypeToken;
adaptor->createTypeTokenText = (void * (*)(pANTLR3_BASE_TREE_ADAPTOR, ANTLR3_UINT32, pANTLR3_COMMON_TOKEN, pANTLR3_UINT8))
createTypeTokenText;
adaptor->createTypeText = (void * (*)(pANTLR3_BASE_TREE_ADAPTOR, ANTLR3_UINT32, pANTLR3_UINT8))
createTypeText;
adaptor->dupTree = (void * (*)(pANTLR3_BASE_TREE_ADAPTOR, void *))
dupTree;
}
else
{
adaptor->nilNode = (void * (*)(pANTLR3_BASE_TREE_ADAPTOR))
dbgNil;
adaptor->addChild = (void (*)(pANTLR3_BASE_TREE_ADAPTOR, void *, void *))
dbgAddChild;
adaptor->becomeRoot = (void * (*)(pANTLR3_BASE_TREE_ADAPTOR, void *, void *))
dbgBecomeRoot;
adaptor->addChildToken = (void (*)(pANTLR3_BASE_TREE_ADAPTOR, void *, pANTLR3_COMMON_TOKEN))
dbgAddChildToken;
adaptor->becomeRootToken = (void * (*)(pANTLR3_BASE_TREE_ADAPTOR, void *, void *))
dbgBecomeRootToken;
adaptor->createTypeToken = (void * (*)(pANTLR3_BASE_TREE_ADAPTOR, ANTLR3_UINT32, pANTLR3_COMMON_TOKEN))
dbgCreateTypeToken;
adaptor->createTypeTokenText = (void * (*)(pANTLR3_BASE_TREE_ADAPTOR, ANTLR3_UINT32, pANTLR3_COMMON_TOKEN, pANTLR3_UINT8))
dbgCreateTypeTokenText;
adaptor->createTypeText = (void * (*)(pANTLR3_BASE_TREE_ADAPTOR, ANTLR3_UINT32, pANTLR3_UINT8))
dbgCreateTypeText;
adaptor->dupTree = (void * (*)(pANTLR3_BASE_TREE_ADAPTOR, void *))
dbgDupTree;
debugger->adaptor = adaptor;
}
adaptor->dupTreeTT = (void * (*)(pANTLR3_BASE_TREE_ADAPTOR, void *, void *))
dupTreeTT;
adaptor->rulePostProcessing = (void * (*)(pANTLR3_BASE_TREE_ADAPTOR, void *))
rulePostProcessing;
adaptor->getType = (ANTLR3_UINT32 (*)(pANTLR3_BASE_TREE_ADAPTOR, void *))
getType;
adaptor->setType = (void (*)(pANTLR3_BASE_TREE_ADAPTOR, void *, ANTLR3_UINT32))
setType;
adaptor->getText = (pANTLR3_STRING (*) (pANTLR3_BASE_TREE_ADAPTOR, void *))
getText;
adaptor->setText8 = (void (*)(pANTLR3_BASE_TREE_ADAPTOR, pANTLR3_UINT8))
setText8;
adaptor->setText = (void (*)(pANTLR3_BASE_TREE_ADAPTOR, pANTLR3_STRING))
setText;
adaptor->getChild = (void * (*)(pANTLR3_BASE_TREE_ADAPTOR, void *, ANTLR3_UINT32))
getChild;
adaptor->getChildCount = (ANTLR3_UINT32 (*)(pANTLR3_BASE_TREE_ADAPTOR, void *))
getChildCount;
adaptor->getUniqueID = (ANTLR3_UINT32 (*)(pANTLR3_BASE_TREE_ADAPTOR, void *))
getUniqueID;
adaptor->isNilNode = (ANTLR3_BOOLEAN (*)(pANTLR3_BASE_TREE_ADAPTOR, void *))
isNilNode;
adaptor->makeDot = (pANTLR3_STRING (*)(pANTLR3_BASE_TREE_ADAPTOR, void *))
makeDot;
/* Remaining functions filled in by the caller.
*/
return;
}
static void
defineDotNodes(pANTLR3_BASE_TREE_ADAPTOR adaptor, void * t, pANTLR3_STRING dotSpec )
{
// How many nodes are we talking about?
//
int nCount;
int i;
pANTLR3_BASE_TREE child;
char buff[64];
pANTLR3_STRING text;
int j;
// Count the nodes
//
nCount = adaptor->getChildCount(adaptor, t);
if (nCount == 0)
{
// This will already have been included as a child of another node
// so there is nothing to add.
//
return;
}
// For each child of the current tree, define a node using the
// memory address of the node to name it
//
for (i = 0; i<nCount; i++)
{
// Pick up a pointer for the child
//
child = adaptor->getChild(adaptor, t, i);
// Name the node
//
sprintf(buff, "\tn%p[label=\"", child);
dotSpec->append8(dotSpec, buff);
text = adaptor->getText(adaptor, child);
for (j = 0; j < (ANTLR3_INT32)(text->len); j++)
{
switch(text->charAt(text, j))
{
case '"':
dotSpec->append8(dotSpec, "\\\"");
break;
case '\n':
dotSpec->append8(dotSpec, "\\n");
break;
case '\r':
dotSpec->append8(dotSpec, "\\r");
break;
default:
dotSpec->addc(dotSpec, text->charAt(text, j));
break;
}
}
dotSpec->append8(dotSpec, "\"]\n");
// And now define the children of this child (if any)
//
defineDotNodes(adaptor, child, dotSpec);
}
// Done
//
return;
}
static void
defineDotEdges(pANTLR3_BASE_TREE_ADAPTOR adaptor, void * t, pANTLR3_STRING dotSpec)
{
// How many nodes are we talking about?
//
int nCount;
int i;
if (t == NULL)
{
// No tree, so do nothing
//
return;
}
// Count the nodes
//
nCount = adaptor->getChildCount(adaptor, t);
if (nCount == 0)
{
// This will already have been included as a child of another node
// so there is nothing to add.
//
return;
}
// For each child, define an edge from this parent, then process
// and children of this child in the same way
//
for (i=0; i<nCount; i++)
{
pANTLR3_BASE_TREE child;
char buff[128];
pANTLR3_STRING text;
int j;
// Next child
//
child = adaptor->getChild(adaptor, t, i);
// Create the edge relation
//
sprintf(buff, "\t\tn%p -> n%p\t\t// ", t, child);
dotSpec->append8(dotSpec, buff);
// Document the relationship
//
text = adaptor->getText(adaptor, t);
for (j = 0; j < (ANTLR3_INT32)(text->len); j++)
{
switch(text->charAt(text, j))
{
case '"':
dotSpec->append8(dotSpec, "\\\"");
break;
case '\n':
dotSpec->append8(dotSpec, "\\n");
break;
case '\r':
dotSpec->append8(dotSpec, "\\r");
break;
default:
dotSpec->addc(dotSpec, text->charAt(text, j));
break;
}
}
dotSpec->append8(dotSpec, " -> ");
text = adaptor->getText(adaptor, child);
for (j = 0; j < (ANTLR3_INT32)(text->len); j++)
{
switch(text->charAt(text, j))
{
case '"':
dotSpec->append8(dotSpec, "\\\"");
break;
case '\n':
dotSpec->append8(dotSpec, "\\n");
break;
case '\r':
dotSpec->append8(dotSpec, "\\r");
break;
default:
dotSpec->addc(dotSpec, text->charAt(text, j));
break;
}
}
dotSpec->append8(dotSpec, "\n");
// Define edges for this child
//
defineDotEdges(adaptor, child, dotSpec);
}
// Done
//
return;
}
/// Produce a DOT specification for graphviz
//
static pANTLR3_STRING
makeDot (pANTLR3_BASE_TREE_ADAPTOR adaptor, void * theTree)
{
// The string we are building up
//
pANTLR3_STRING dotSpec;
char buff[64];
pANTLR3_STRING text;
int j;
dotSpec = adaptor->strFactory->newStr8
(
adaptor->strFactory,
// Default look and feel
//
(pANTLR3_UINT8)
"digraph {\n\n"
"\tordering=out;\n"
"\tranksep=.4;\n"
"\tbgcolor=\"lightgrey\"; node [shape=box, fixedsize=false, fontsize=12, fontname=\"Helvetica-bold\", fontcolor=\"blue\"\n"
"\twidth=.25, height=.25, color=\"black\", fillcolor=\"white\", style=\"filled, solid, bold\"];\n\n"
"\tedge [arrowsize=.5, color=\"black\", style=\"bold\"]\n\n"
);
if (theTree == NULL)
{
// No tree, so create a blank spec
//
dotSpec->append8(dotSpec, "n0[label=\"EMPTY TREE\"]\n");
return dotSpec;
}
sprintf(buff, "\tn%p[label=\"", theTree);
dotSpec->append8(dotSpec, buff);
text = adaptor->getText(adaptor, theTree);
for (j = 0; j < (ANTLR3_INT32)(text->len); j++)
{
switch(text->charAt(text, j))
{
case '"':
dotSpec->append8(dotSpec, "\\\"");
break;
case '\n':
dotSpec->append8(dotSpec, "\\n");
break;
case '\r':
dotSpec->append8(dotSpec, "\\r");
break;
default:
dotSpec->addc(dotSpec, text->charAt(text, j));
break;
}
}
dotSpec->append8(dotSpec, "\"]\n");
// First produce the node defintions
//
defineDotNodes(adaptor, theTree, dotSpec);
dotSpec->append8(dotSpec, "\n");
defineDotEdges(adaptor, theTree, dotSpec);
// Terminate the spec
//
dotSpec->append8(dotSpec, "\n}");
// Result
//
return dotSpec;
}
/** Create and return a nil tree node (no token payload)
*/
static pANTLR3_BASE_TREE
nilNode (pANTLR3_BASE_TREE_ADAPTOR adaptor)
{
return adaptor->create(adaptor, NULL);
}
static pANTLR3_BASE_TREE
dbgNil (pANTLR3_BASE_TREE_ADAPTOR adaptor)
{
pANTLR3_BASE_TREE t;
t = adaptor->create (adaptor, NULL);
adaptor->debugger->createNode (adaptor->debugger, t);
return t;
}
/** Return a duplicate of the entire tree (implementation provided by the
* BASE_TREE interface.)
*/
static pANTLR3_BASE_TREE
dupTree (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t)
{
return adaptor->dupTreeTT(adaptor, t, NULL);
}
pANTLR3_BASE_TREE
dupTreeTT (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, pANTLR3_BASE_TREE parent)
{
pANTLR3_BASE_TREE newTree;
pANTLR3_BASE_TREE child;
pANTLR3_BASE_TREE newSubTree;
ANTLR3_UINT32 n;
ANTLR3_UINT32 i;
if (t == NULL)
{
return NULL;
}
newTree = t->dupNode(t);
// Ensure new subtree root has parent/child index set
//
adaptor->setChildIndex (adaptor, newTree, t->getChildIndex(t));
adaptor->setParent (adaptor, newTree, parent);
n = adaptor->getChildCount (adaptor, t);
for (i=0; i < n; i++)
{
child = adaptor->getChild (adaptor, t, i);
newSubTree = adaptor->dupTreeTT (adaptor, child, t);
adaptor->addChild (adaptor, newTree, newSubTree);
}
return newTree;
}
/// Sends the required debugging events for duplicating a tree
/// to the debugger.
///
static void
simulateTreeConstruction(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE tree)
{
ANTLR3_UINT32 n;
ANTLR3_UINT32 i;
pANTLR3_BASE_TREE child;
// Send the create node event
//
adaptor->debugger->createNode(adaptor->debugger, tree);
n = adaptor->getChildCount(adaptor, tree);
for (i = 0; i < n; i++)
{
child = adaptor->getChild(adaptor, tree, i);
simulateTreeConstruction(adaptor, child);
adaptor->debugger->addChild(adaptor->debugger, tree, child);
}
}
pANTLR3_BASE_TREE
dbgDupTree (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE tree)
{
pANTLR3_BASE_TREE t;
// Call the normal dup tree mechanism first
//
t = adaptor->dupTreeTT(adaptor, tree, NULL);
// In order to tell the debugger what we have just done, we now
// simulate the tree building mechanism. THis will fire
// lots of debugging events to the client and look like we
// duped the tree..
//
simulateTreeConstruction(adaptor, t);
return t;
}
/** Add a child to the tree t. If child is a flat tree (a list), make all
* in list children of t. Warning: if t has no children, but child does
* and child isNilNode then it is ok to move children to t via
* t.children = child.children; i.e., without copying the array. This
* is for construction and I'm not sure it's completely general for
* a tree's addChild method to work this way. Make sure you differentiate
* between your tree's addChild and this parser tree construction addChild
* if it's not ok to move children to t with a simple assignment.
*/
static void
addChild (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, pANTLR3_BASE_TREE child)
{
if (t != NULL && child != NULL)
{
t->addChild(t, child);
}
}
static void
dbgAddChild (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, pANTLR3_BASE_TREE child)
{
if (t != NULL && child != NULL)
{
t->addChild(t, child);
adaptor->debugger->addChild(adaptor->debugger, t, child);
}
}
/** Use the adaptor implementation to add a child node with the supplied token
*/
static void
addChildToken (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, pANTLR3_COMMON_TOKEN child)
{
if (t != NULL && child != NULL)
{
adaptor->addChild(adaptor, t, adaptor->create(adaptor, child));
}
}
static void
dbgAddChildToken (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, pANTLR3_COMMON_TOKEN child)
{
pANTLR3_BASE_TREE tc;
if (t != NULL && child != NULL)
{
tc = adaptor->create(adaptor, child);
adaptor->addChild(adaptor, t, tc);
adaptor->debugger->addChild(adaptor->debugger, t, tc);
}
}
/** If oldRoot is a nil root, just copy or move the children to newRoot.
* If not a nil root, make oldRoot a child of newRoot.
*
* \code
* old=^(nil a b c), new=r yields ^(r a b c)
* old=^(a b c), new=r yields ^(r ^(a b c))
* \endcode
*
* If newRoot is a nil-rooted single child tree, use the single
* child as the new root node.
*
* \code
* old=^(nil a b c), new=^(nil r) yields ^(r a b c)
* old=^(a b c), new=^(nil r) yields ^(r ^(a b c))
* \endcode
*
* If oldRoot was null, it's ok, just return newRoot (even if isNilNode).
*
* \code
* old=null, new=r yields r
* old=null, new=^(nil r) yields ^(nil r)
* \endcode
*
* Return newRoot. Throw an exception if newRoot is not a
* simple node or nil root with a single child node--it must be a root
* node. If newRoot is <code>^(nil x)</endcode> return x as newRoot.
*
* Be advised that it's ok for newRoot to point at oldRoot's
* children; i.e., you don't have to copy the list. We are
* constructing these nodes so we should have this control for
* efficiency.
*/
static pANTLR3_BASE_TREE
becomeRoot (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE newRootTree, pANTLR3_BASE_TREE oldRootTree)
{
pANTLR3_BASE_TREE saveRoot;
/* Protect against tree rewrites if we are in some sort of error
* state, but have tried to recover. In C we can end up with a null pointer
* for a tree that was not produced.
*/
if (newRootTree == NULL)
{
return oldRootTree;
}
/* root is just the new tree as is if there is no
* current root tree.
*/
if (oldRootTree == NULL)
{
return newRootTree;
}
/* Produce ^(nil real-node)
*/
if (newRootTree->isNilNode(newRootTree))
{
if (newRootTree->getChildCount(newRootTree) > 1)
{
/* TODO: Handle tree exceptions
*/
ANTLR3_FPRINTF(stderr, "More than one node as root! TODO: Create tree exception handling\n");
return newRootTree;
}
/* The new root is the first child, keep track of the original newRoot
* because if it was a Nil Node, then we can reuse it now.
*/
saveRoot = newRootTree;
newRootTree = newRootTree->getChild(newRootTree, 0);
// Reclaim the old nilNode()
//
saveRoot->reuse(saveRoot);
}
/* Add old root into new root. addChild takes care of the case where oldRoot
* is a flat list (nill rooted tree). All children of oldroot are added to
* new root.
*/
newRootTree->addChild(newRootTree, oldRootTree);
// If the oldroot tree was a nil node, then we know at this point
// it has become orphaned by the rewrite logic, so we tell it to do
// whatever it needs to do to be reused.
//
if (oldRootTree->isNilNode(oldRootTree))
{
// We have taken an old Root Tree and appended all its children to the new
// root. In addition though it was a nil node, which means the generated code
// will not reuse it again, so we will reclaim it here. First we want to zero out
// any pointers it was carrying around. We are just the baseTree handler so we
// don't know necessarilly know how to do this for the real node, we just ask the tree itself
// to do it.
//
oldRootTree->reuse(oldRootTree);
}
/* Always returns new root structure
*/
return newRootTree;
}
static pANTLR3_BASE_TREE
dbgBecomeRoot (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE newRootTree, pANTLR3_BASE_TREE oldRootTree)
{
pANTLR3_BASE_TREE t;
t = becomeRoot(adaptor, newRootTree, oldRootTree);
adaptor->debugger->becomeRoot(adaptor->debugger, newRootTree, oldRootTree);
return t;
}
/** Transform ^(nil x) to x
*/
static pANTLR3_BASE_TREE
rulePostProcessing (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE root)
{
pANTLR3_BASE_TREE saveRoot;
// Keep track of the root we are given. If it is a nilNode, then we
// can reuse it rather than orphaning it!
//
saveRoot = root;
if (root != NULL && root->isNilNode(root))
{
if (root->getChildCount(root) == 0)
{
root = NULL;
}
else if (root->getChildCount(root) == 1)
{
root = root->getChild(root, 0);
root->setParent(root, NULL);
root->setChildIndex(root, -1);
// The root we were given was a nil node, wiht one child, which means it has
// been abandoned and would be lost in the node factory. However
// nodes can be flagged as resuable to prevent this terrible waste
//
saveRoot->reuse(saveRoot);
}
}
return root;
}
/** Use the adaptor interface to set a new tree node with the supplied token
* to the root of the tree.
*/
static pANTLR3_BASE_TREE
becomeRootToken (pANTLR3_BASE_TREE_ADAPTOR adaptor, void * newRoot, pANTLR3_BASE_TREE oldRoot)
{
return adaptor->becomeRoot(adaptor, adaptor->create(adaptor, newRoot), oldRoot);
}
static pANTLR3_BASE_TREE
dbgBecomeRootToken (pANTLR3_BASE_TREE_ADAPTOR adaptor, void * newRoot, pANTLR3_BASE_TREE oldRoot)
{
pANTLR3_BASE_TREE t;
t = adaptor->becomeRoot(adaptor, adaptor->create(adaptor, newRoot), oldRoot);
adaptor->debugger->becomeRoot(adaptor->debugger,t, oldRoot);
return t;
}
/** Use the super class supplied create() method to create a new node
* from the supplied token.
*/
static pANTLR3_BASE_TREE
createTypeToken (pANTLR3_BASE_TREE_ADAPTOR adaptor, ANTLR3_UINT32 tokenType, pANTLR3_COMMON_TOKEN fromToken)
{
/* Create the new token
*/
fromToken = adaptor->createTokenFromToken(adaptor, fromToken);
/* Set the type of the new token to that supplied
*/
fromToken->setType(fromToken, tokenType);
/* Return a new node based upon this token
*/
return adaptor->create(adaptor, fromToken);
}
static pANTLR3_BASE_TREE
dbgCreateTypeToken (pANTLR3_BASE_TREE_ADAPTOR adaptor, ANTLR3_UINT32 tokenType, pANTLR3_COMMON_TOKEN fromToken)
{
pANTLR3_BASE_TREE t;
t = createTypeToken(adaptor, tokenType, fromToken);
adaptor->debugger->createNode(adaptor->debugger, t);
return t;
}
static pANTLR3_BASE_TREE
createTypeTokenText (pANTLR3_BASE_TREE_ADAPTOR adaptor, ANTLR3_UINT32 tokenType, pANTLR3_COMMON_TOKEN fromToken, pANTLR3_UINT8 text)
{
/* Create the new token
*/
fromToken = adaptor->createTokenFromToken(adaptor, fromToken);
/* Set the type of the new token to that supplied
*/
fromToken->setType(fromToken, tokenType);
/* Set the text of the token accordingly
*/
fromToken->setText8(fromToken, text);
/* Return a new node based upon this token
*/
return adaptor->create(adaptor, fromToken);
}
static pANTLR3_BASE_TREE
dbgCreateTypeTokenText (pANTLR3_BASE_TREE_ADAPTOR adaptor, ANTLR3_UINT32 tokenType, pANTLR3_COMMON_TOKEN fromToken, pANTLR3_UINT8 text)
{
pANTLR3_BASE_TREE t;
t = createTypeTokenText(adaptor, tokenType, fromToken, text);
adaptor->debugger->createNode(adaptor->debugger, t);
return t;
}
static pANTLR3_BASE_TREE
createTypeText (pANTLR3_BASE_TREE_ADAPTOR adaptor, ANTLR3_UINT32 tokenType, pANTLR3_UINT8 text)
{
pANTLR3_COMMON_TOKEN fromToken;
/* Create the new token
*/
fromToken = adaptor->createToken(adaptor, tokenType, text);
/* Return a new node based upon this token
*/
return adaptor->create(adaptor, fromToken);
}
static pANTLR3_BASE_TREE
dbgCreateTypeText (pANTLR3_BASE_TREE_ADAPTOR adaptor, ANTLR3_UINT32 tokenType, pANTLR3_UINT8 text)
{
pANTLR3_BASE_TREE t;
t = createTypeText(adaptor, tokenType, text);
adaptor->debugger->createNode(adaptor->debugger, t);
return t;
}
/** Dummy implementation - will be supplied by super class
*/
static ANTLR3_UINT32
getType (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t)
{
return 0;
}
/** Dummy implementation - will be supplied by super class
*/
static void
setType (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, ANTLR3_UINT32 type)
{
ANTLR3_FPRINTF(stderr, "Internal error - implementor of superclass containing ANTLR3_TREE_ADAPTOR did not implement setType()\n");
}
/** Dummy implementation - will be supplied by super class
*/
static pANTLR3_STRING
getText (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t)
{
ANTLR3_FPRINTF(stderr, "Internal error - implementor of superclass containing ANTLR3_TREE_ADAPTOR did not implement getText()\n");
return NULL;
}
/** Dummy implementation - will be supplied by super class
*/
static void
setText (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_STRING t)
{
ANTLR3_FPRINTF(stderr, "Internal error - implementor of superclass containing ANTLR3_TREE_ADAPTOR did not implement setText()\n");
}
/** Dummy implementation - will be supplied by super class
*/
static void
setText8 (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_UINT8 t)
{
ANTLR3_FPRINTF(stderr, "Internal error - implementor of superclass containing ANTLR3_TREE_ADAPTOR did not implement setText()\n");
}
static pANTLR3_BASE_TREE
getChild (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE tree, ANTLR3_UINT32 i)
{
ANTLR3_FPRINTF(stderr, "Internal error - implementor of superclass containing ANTLR3_TREE_ADAPTOR did not implement getChild()\n");
return NULL;
}
static ANTLR3_UINT32
getChildCount (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE tree)
{
ANTLR3_FPRINTF(stderr, "Internal error - implementor of superclass containing ANTLR3_TREE_ADAPTOR did not implement getChildCount()\n");
return 0;
}
/** Returns a uniqueID for the node. Because this is the C implementation
* we can just use its address suitably converted/cast to an integer.
*/
static ANTLR3_UINT32
getUniqueID (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE node)
{
return ANTLR3_UINT32_CAST(node);
}
static ANTLR3_BOOLEAN
isNilNode (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t)
{
return t->isNilNode(t);
}