blob: abce6f0f9144f424c78500856ccfb235649209de [file] [log] [blame]
/** \file
* This is the standard tree adaptor used by the C runtime unless the grammar
* source file says to use anything different. It embeds a BASE_TREE to which
* it adds its own implementation of anything that the base tree is not
* good for, plus a number of methods that any other adaptor type
* needs to implement too.
* \ingroup pANTLR3_COMMON_TREE_ADAPTOR
*/
// [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 <antlr3commontreeadaptor.h>
#ifdef ANTLR3_WINDOWS
#pragma warning( disable : 4100 )
#endif
/* BASE_TREE_ADAPTOR overrides... */
static pANTLR3_BASE_TREE dupNode (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE treeNode);
static pANTLR3_BASE_TREE create (pANTLR3_BASE_TREE_ADAPTOR adpator, pANTLR3_COMMON_TOKEN payload);
static pANTLR3_BASE_TREE dbgCreate (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_COMMON_TOKEN payload);
static pANTLR3_COMMON_TOKEN createToken (pANTLR3_BASE_TREE_ADAPTOR adaptor, ANTLR3_UINT32 tokenType, pANTLR3_UINT8 text);
static pANTLR3_COMMON_TOKEN createTokenFromToken (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_COMMON_TOKEN fromToken);
static pANTLR3_COMMON_TOKEN getToken (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t);
static pANTLR3_STRING getText (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t);
static ANTLR3_UINT32 getType (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE 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 void replaceChildren (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE parent, ANTLR3_INT32 startChildIndex, ANTLR3_INT32 stopChildIndex, pANTLR3_BASE_TREE t);
static void setDebugEventListener (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_DEBUG_EVENT_LISTENER debugger);
static void setChildIndex (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, ANTLR3_INT32 i);
static ANTLR3_INT32 getChildIndex (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t);
static void setParent (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE child, pANTLR3_BASE_TREE parent);
static pANTLR3_BASE_TREE getParent (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE child);
static void setChild (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, ANTLR3_UINT32 i, pANTLR3_BASE_TREE child);
static void deleteChild (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, ANTLR3_UINT32 i);
static pANTLR3_BASE_TREE errorNode (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_TOKEN_STREAM ctnstream, pANTLR3_COMMON_TOKEN startToken, pANTLR3_COMMON_TOKEN stopToken, pANTLR3_EXCEPTION e);
/* Methods specific to each tree adaptor
*/
static void setTokenBoundaries (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, pANTLR3_COMMON_TOKEN startToken, pANTLR3_COMMON_TOKEN stopToken);
static void dbgSetTokenBoundaries (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, pANTLR3_COMMON_TOKEN startToken, pANTLR3_COMMON_TOKEN stopToken);
static ANTLR3_MARKER getTokenStartIndex (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t);
static ANTLR3_MARKER getTokenStopIndex (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t);
static void ctaFree (pANTLR3_BASE_TREE_ADAPTOR adaptor);
/** Create a new tree adaptor. Note that despite the fact that this is
* creating a new COMMON_TREE adaptor, we return the address of the
* BASE_TREE interface, as should any other adaptor that wishes to be
* used as the tree element of a tree parse/build. It needs to be given the
* address of a valid string factory as we do not know what the originating
* input stream encoding type was. This way we can rely on just using
* the original input stream's string factory or one of the correct type
* which the user supplies us.
*/
ANTLR3_API pANTLR3_BASE_TREE_ADAPTOR
ANTLR3_TREE_ADAPTORNew(pANTLR3_STRING_FACTORY strFactory)
{
pANTLR3_COMMON_TREE_ADAPTOR cta;
// First job is to create the memory we need for the tree adaptor interface.
//
cta = (pANTLR3_COMMON_TREE_ADAPTOR) ANTLR3_MALLOC((size_t)(sizeof(ANTLR3_COMMON_TREE_ADAPTOR)));
if (cta == NULL)
{
return NULL;
}
// Memory is initialized, so initialize the base tree adaptor
//
antlr3BaseTreeAdaptorInit(&(cta->baseAdaptor), NULL);
// Install our interface overrides. Strangeness is to allow generated code to treat them
// as returning void *
//
cta->baseAdaptor.dupNode = (void * (*) (pANTLR3_BASE_TREE_ADAPTOR, void *))
dupNode;
cta->baseAdaptor.create = (void * (*) (pANTLR3_BASE_TREE_ADAPTOR, pANTLR3_COMMON_TOKEN))
create;
cta->baseAdaptor.createToken =
createToken;
cta->baseAdaptor.createTokenFromToken =
createTokenFromToken;
cta->baseAdaptor.setTokenBoundaries = (void (*) (pANTLR3_BASE_TREE_ADAPTOR, void *, pANTLR3_COMMON_TOKEN, pANTLR3_COMMON_TOKEN))
setTokenBoundaries;
cta->baseAdaptor.getTokenStartIndex = (ANTLR3_MARKER (*) (pANTLR3_BASE_TREE_ADAPTOR, void *))
getTokenStartIndex;
cta->baseAdaptor.getTokenStopIndex = (ANTLR3_MARKER (*) (pANTLR3_BASE_TREE_ADAPTOR, void *))
getTokenStopIndex;
cta->baseAdaptor.getText = (pANTLR3_STRING (*) (pANTLR3_BASE_TREE_ADAPTOR, void *))
getText;
cta->baseAdaptor.getType = (ANTLR3_UINT32 (*) (pANTLR3_BASE_TREE_ADAPTOR, void *))
getType;
cta->baseAdaptor.getChild = (void * (*) (pANTLR3_BASE_TREE_ADAPTOR, void *, ANTLR3_UINT32))
getChild;
cta->baseAdaptor.setChild = (void (*) (pANTLR3_BASE_TREE_ADAPTOR, void *, ANTLR3_UINT32, void *))
setChild;
cta->baseAdaptor.setParent = (void (*) (pANTLR3_BASE_TREE_ADAPTOR, void *, void *))
setParent;
cta->baseAdaptor.getParent = (void * (*) (pANTLR3_BASE_TREE_ADAPTOR, void *))
getParent;
cta->baseAdaptor.setChildIndex = (void (*) (pANTLR3_BASE_TREE_ADAPTOR, void *, ANTLR3_UINT32))
setChildIndex;
cta->baseAdaptor.deleteChild = (void (*) (pANTLR3_BASE_TREE_ADAPTOR, void *, ANTLR3_UINT32))
deleteChild;
cta->baseAdaptor.getChildCount = (ANTLR3_UINT32 (*) (pANTLR3_BASE_TREE_ADAPTOR, void *))
getChildCount;
cta->baseAdaptor.getChildIndex = (ANTLR3_INT32 (*) (pANTLR3_BASE_TREE_ADAPTOR, void *))
getChildIndex;
cta->baseAdaptor.free = (void (*) (pANTLR3_BASE_TREE_ADAPTOR))
ctaFree;
cta->baseAdaptor.setDebugEventListener =
setDebugEventListener;
cta->baseAdaptor.replaceChildren = (void (*) (pANTLR3_BASE_TREE_ADAPTOR, void *, ANTLR3_INT32, ANTLR3_INT32, void *))
replaceChildren;
cta->baseAdaptor.errorNode = (void * (*) (pANTLR3_BASE_TREE_ADAPTOR, pANTLR3_TOKEN_STREAM, pANTLR3_COMMON_TOKEN, pANTLR3_COMMON_TOKEN, pANTLR3_EXCEPTION))
errorNode;
// Install the super class pointer
//
cta->baseAdaptor.super = cta;
// Install a tree factory for creating new tree nodes
//
cta->arboretum = antlr3ArboretumNew(strFactory);
// Install a token factory for imaginary tokens, these imaginary
// tokens do not require access to the input stream so we can
// dummy the creation of it, but they will need a string factory.
//
cta->baseAdaptor.tokenFactory = antlr3TokenFactoryNew(NULL);
cta->baseAdaptor.tokenFactory->unTruc.strFactory = strFactory;
// Allow the base tree adaptor to share the tree factory's string factory.
//
cta->baseAdaptor.strFactory = strFactory;
// Return the address of the base adaptor interface.
//
return &(cta->baseAdaptor);
}
/// Debugging version of the tree adaptor (not normally called as generated code
/// calls setDebugEventListener instead which changes a normal token stream to
/// a debugging stream and means that a user's instantiation code does not need
/// to be changed just to debug with AW.
///
ANTLR3_API pANTLR3_BASE_TREE_ADAPTOR
ANTLR3_TREE_ADAPTORDebugNew(pANTLR3_STRING_FACTORY strFactory, pANTLR3_DEBUG_EVENT_LISTENER debugger)
{
pANTLR3_BASE_TREE_ADAPTOR ta;
// Create a normal one first
//
ta = ANTLR3_TREE_ADAPTORNew(strFactory);
if (ta != NULL)
{
// Reinitialize as a debug version
//
antlr3BaseTreeAdaptorInit(ta, debugger);
ta->create = (void * (*) (pANTLR3_BASE_TREE_ADAPTOR, pANTLR3_COMMON_TOKEN))
dbgCreate;
ta->setTokenBoundaries = (void (*) (pANTLR3_BASE_TREE_ADAPTOR, void *, pANTLR3_COMMON_TOKEN, pANTLR3_COMMON_TOKEN))
dbgSetTokenBoundaries;
}
return ta;
}
/// Causes an existing common tree adaptor to become a debug version
///
static void
setDebugEventListener (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_DEBUG_EVENT_LISTENER debugger)
{
// Reinitialize as a debug version
//
antlr3BaseTreeAdaptorInit(adaptor, debugger);
adaptor->create = (void * (*) (pANTLR3_BASE_TREE_ADAPTOR, pANTLR3_COMMON_TOKEN))
dbgCreate;
adaptor->setTokenBoundaries = (void (*) (pANTLR3_BASE_TREE_ADAPTOR, void *, pANTLR3_COMMON_TOKEN, pANTLR3_COMMON_TOKEN))
dbgSetTokenBoundaries;
}
static void
ctaFree(pANTLR3_BASE_TREE_ADAPTOR adaptor)
{
pANTLR3_COMMON_TREE_ADAPTOR cta;
cta = (pANTLR3_COMMON_TREE_ADAPTOR)(adaptor->super);
/* Free the tree factory we created
*/
cta->arboretum->close(((pANTLR3_COMMON_TREE_ADAPTOR)(adaptor->super))->arboretum);
/* Free the token factory we created
*/
adaptor->tokenFactory->close(adaptor->tokenFactory);
/* Free the super pointer, as it is this that was allocated
* and is the common tree structure.
*/
ANTLR3_FREE(adaptor->super);
}
/* BASE_TREE_ADAPTOR overrides */
static pANTLR3_BASE_TREE
errorNode (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_TOKEN_STREAM ctnstream, pANTLR3_COMMON_TOKEN startToken, pANTLR3_COMMON_TOKEN stopToken, pANTLR3_EXCEPTION e)
{
// Use the supplied common tree node stream to get another tree from the factory
// TODO: Look at creating the erronode as in Java, but this is complicated by the
// need to track and free the memory allocated to it, so for now, we just
// want something in the tree that isn't a NULL pointer.
//
return adaptor->createTypeText(adaptor, ANTLR3_TOKEN_INVALID, (pANTLR3_UINT8)"Tree Error Node");
}
/** Duplicate the supplied node.
*/
static pANTLR3_BASE_TREE
dupNode (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE treeNode)
{
return treeNode == NULL ? NULL : treeNode->dupNode(treeNode);
}
static pANTLR3_BASE_TREE
create (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_COMMON_TOKEN payload)
{
pANTLR3_BASE_TREE ct;
/* Create a new common tree as this is what this adaptor deals with
*/
ct = ((pANTLR3_COMMON_TREE_ADAPTOR)(adaptor->super))->arboretum->newFromToken(((pANTLR3_COMMON_TREE_ADAPTOR)(adaptor->super))->arboretum, payload);
/* But all adaptors return the pointer to the base interface.
*/
return ct;
}
static pANTLR3_BASE_TREE
dbgCreate (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_COMMON_TOKEN payload)
{
pANTLR3_BASE_TREE ct;
ct = create(adaptor, payload);
adaptor->debugger->createNode(adaptor->debugger, ct);
return ct;
}
/** Tell me how to create a token for use with imaginary token nodes.
* For example, there is probably no input symbol associated with imaginary
* token DECL, but you need to create it as a payload or whatever for
* the DECL node as in ^(DECL type ID).
*
* If you care what the token payload objects' type is, you should
* override this method and any other createToken variant.
*/
static pANTLR3_COMMON_TOKEN
createToken (pANTLR3_BASE_TREE_ADAPTOR adaptor, ANTLR3_UINT32 tokenType, pANTLR3_UINT8 text)
{
pANTLR3_COMMON_TOKEN newToken;
newToken = adaptor->tokenFactory->newToken(adaptor->tokenFactory);
if (newToken != NULL)
{
newToken->textState = ANTLR3_TEXT_CHARP;
newToken->tokText.chars = (pANTLR3_UCHAR)text;
newToken->setType(newToken, tokenType);
newToken->input = adaptor->tokenFactory->input;
newToken->strFactory = adaptor->strFactory;
}
return newToken;
}
/** Tell me how to create a token for use with imaginary token nodes.
* For example, there is probably no input symbol associated with imaginary
* token DECL, but you need to create it as a payload or whatever for
* the DECL node as in ^(DECL type ID).
*
* This is a variant of createToken where the new token is derived from
* an actual real input token. Typically this is for converting '{'
* tokens to BLOCK etc... You'll see
*
* r : lc='{' ID+ '}' -> ^(BLOCK[$lc] ID+) ;
*
* If you care what the token payload objects' type is, you should
* override this method and any other createToken variant.
*
* NB: this being C it is not so easy to extend the types of creaeteToken.
* We will have to see if anyone needs to do this and add any variants to
* this interface.
*/
static pANTLR3_COMMON_TOKEN
createTokenFromToken (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_COMMON_TOKEN fromToken)
{
pANTLR3_COMMON_TOKEN newToken;
newToken = adaptor->tokenFactory->newToken(adaptor->tokenFactory);
if (newToken != NULL)
{
// Create the text using our own string factory to avoid complicating
// commontoken.
//
pANTLR3_STRING text;
newToken->toString = fromToken->toString;
if (fromToken->textState == ANTLR3_TEXT_CHARP)
{
newToken->textState = ANTLR3_TEXT_CHARP;
newToken->tokText.chars = fromToken->tokText.chars;
}
else
{
text = fromToken->getText(fromToken);
newToken->textState = ANTLR3_TEXT_STRING;
newToken->tokText.text = adaptor->strFactory->newPtr(adaptor->strFactory, text->chars, text->len);
}
newToken->setLine (newToken, fromToken->getLine(fromToken));
newToken->setTokenIndex (newToken, fromToken->getTokenIndex(fromToken));
newToken->setCharPositionInLine (newToken, fromToken->getCharPositionInLine(fromToken));
newToken->setChannel (newToken, fromToken->getChannel(fromToken));
newToken->setType (newToken, fromToken->getType(fromToken));
}
return newToken;
}
/* Specific methods for a TreeAdaptor */
/** Track start/stop token for subtree root created for a rule.
* Only works with CommonTree nodes. For rules that match nothing,
* seems like this will yield start=i and stop=i-1 in a nil node.
* Might be useful info so I'll not force to be i..i.
*/
static void
setTokenBoundaries (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, pANTLR3_COMMON_TOKEN startToken, pANTLR3_COMMON_TOKEN stopToken)
{
ANTLR3_MARKER start;
ANTLR3_MARKER stop;
pANTLR3_COMMON_TREE ct;
if (t == NULL)
{
return;
}
if ( startToken != NULL)
{
start = startToken->getTokenIndex(startToken);
}
else
{
start = 0;
}
if ( stopToken != NULL)
{
stop = stopToken->getTokenIndex(stopToken);
}
else
{
stop = 0;
}
ct = (pANTLR3_COMMON_TREE)(t->super);
ct->startIndex = start;
ct->stopIndex = stop;
}
static void
dbgSetTokenBoundaries (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, pANTLR3_COMMON_TOKEN startToken, pANTLR3_COMMON_TOKEN stopToken)
{
setTokenBoundaries(adaptor, t, startToken, stopToken);
if (t != NULL && startToken != NULL && stopToken != NULL)
{
adaptor->debugger->setTokenBoundaries(adaptor->debugger, t, startToken->getTokenIndex(startToken), stopToken->getTokenIndex(stopToken));
}
}
static ANTLR3_MARKER
getTokenStartIndex (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t)
{
return ((pANTLR3_COMMON_TREE)(t->super))->startIndex;
}
static ANTLR3_MARKER
getTokenStopIndex (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t)
{
return ((pANTLR3_COMMON_TREE)(t->super))->stopIndex;
}
static pANTLR3_STRING
getText (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t)
{
return t->getText(t);
}
static ANTLR3_UINT32
getType (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t)
{
return t->getType(t);
}
static void
replaceChildren
(pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE parent, ANTLR3_INT32 startChildIndex, ANTLR3_INT32 stopChildIndex, pANTLR3_BASE_TREE t)
{
if (parent != NULL)
{
parent->replaceChildren(parent, startChildIndex, stopChildIndex, t);
}
}
static pANTLR3_BASE_TREE
getChild (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, ANTLR3_UINT32 i)
{
return t->getChild(t, i);
}
static void
setChild (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, ANTLR3_UINT32 i, pANTLR3_BASE_TREE child)
{
t->setChild(t, i, child);
}
static void
deleteChild (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, ANTLR3_UINT32 i)
{
t->deleteChild(t, i);
}
static ANTLR3_UINT32
getChildCount (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t)
{
return t->getChildCount(t);
}
static void
setChildIndex (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t, ANTLR3_INT32 i)
{
t->setChildIndex(t, i);
}
static ANTLR3_INT32
getChildIndex (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE t)
{
return t->getChildIndex(t);
}
static void
setParent (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE child, pANTLR3_BASE_TREE parent)
{
child->setParent(child, parent);
}
static pANTLR3_BASE_TREE
getParent (pANTLR3_BASE_TREE_ADAPTOR adaptor, pANTLR3_BASE_TREE child)
{
return child->getParent(child);
}