255 lines
7.8 KiB
C
255 lines
7.8 KiB
C
/** \file
|
|
* Implementation of the tree parser and overrides for the base recognizer
|
|
*/
|
|
|
|
// [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 <antlr3treeparser.h>
|
|
|
|
/* BASE Recognizer overrides
|
|
*/
|
|
static void mismatch (pANTLR3_BASE_RECOGNIZER recognizer, ANTLR3_UINT32 ttype, pANTLR3_BITSET_LIST follow);
|
|
|
|
/* Tree parser API
|
|
*/
|
|
static void setTreeNodeStream (pANTLR3_TREE_PARSER parser, pANTLR3_COMMON_TREE_NODE_STREAM input);
|
|
static pANTLR3_COMMON_TREE_NODE_STREAM
|
|
getTreeNodeStream (pANTLR3_TREE_PARSER parser);
|
|
static void freeParser (pANTLR3_TREE_PARSER parser);
|
|
static void * getCurrentInputSymbol (pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_INT_STREAM istream);
|
|
static void * getMissingSymbol (pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_INT_STREAM istream, pANTLR3_EXCEPTION e,
|
|
ANTLR3_UINT32 expectedTokenType, pANTLR3_BITSET_LIST follow);
|
|
|
|
|
|
ANTLR3_API pANTLR3_TREE_PARSER
|
|
antlr3TreeParserNewStream(ANTLR3_UINT32 sizeHint, pANTLR3_COMMON_TREE_NODE_STREAM ctnstream, pANTLR3_RECOGNIZER_SHARED_STATE state)
|
|
{
|
|
pANTLR3_TREE_PARSER parser;
|
|
|
|
/** Allocate tree parser memory
|
|
*/
|
|
parser =(pANTLR3_TREE_PARSER) ANTLR3_MALLOC(sizeof(ANTLR3_TREE_PARSER));
|
|
|
|
if (parser == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
/* Create and install a base recognizer which does most of the work for us
|
|
*/
|
|
parser->rec = antlr3BaseRecognizerNew(ANTLR3_TYPE_PARSER, sizeHint, state);
|
|
|
|
if (parser->rec == NULL)
|
|
{
|
|
parser->free(parser);
|
|
return NULL;
|
|
}
|
|
|
|
/* Ensure we can track back to the tree parser super structure
|
|
* from the base recognizer structure
|
|
*/
|
|
parser->rec->super = parser;
|
|
parser->rec->type = ANTLR3_TYPE_TREE_PARSER;
|
|
|
|
/* Install our base recognizer overrides
|
|
*/
|
|
parser->rec->mismatch = mismatch;
|
|
parser->rec->exConstruct = antlr3MTNExceptionNew;
|
|
parser->rec->getCurrentInputSymbol = getCurrentInputSymbol;
|
|
parser->rec->getMissingSymbol = getMissingSymbol;
|
|
|
|
/* Install tree parser API
|
|
*/
|
|
parser->getTreeNodeStream = getTreeNodeStream;
|
|
parser->setTreeNodeStream = setTreeNodeStream;
|
|
parser->free = freeParser;
|
|
|
|
/* Install the tree node stream
|
|
*/
|
|
parser->setTreeNodeStream(parser, ctnstream);
|
|
|
|
return parser;
|
|
}
|
|
|
|
/**
|
|
* \brief
|
|
* Creates a new Mismatched Tree Nde Exception and inserts in the recognizer
|
|
* exception stack.
|
|
*
|
|
* \param recognizer
|
|
* Context pointer for this recognizer
|
|
*
|
|
*/
|
|
ANTLR3_API void
|
|
antlr3MTNExceptionNew(pANTLR3_BASE_RECOGNIZER recognizer)
|
|
{
|
|
/* Create a basic recognition exception structure
|
|
*/
|
|
antlr3RecognitionExceptionNew(recognizer);
|
|
|
|
/* Now update it to indicate this is a Mismatched token exception
|
|
*/
|
|
recognizer->state->exception->name = ANTLR3_MISMATCHED_TREE_NODE_NAME;
|
|
recognizer->state->exception->type = ANTLR3_MISMATCHED_TREE_NODE_EXCEPTION;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
static void
|
|
freeParser (pANTLR3_TREE_PARSER parser)
|
|
{
|
|
if (parser->rec != NULL)
|
|
{
|
|
// This may have ben a delegate or delegator parser, in which case the
|
|
// state may already have been freed (and set to NULL therefore)
|
|
// so we ignore the state if we don't have it.
|
|
//
|
|
if (parser->rec->state != NULL)
|
|
{
|
|
if (parser->rec->state->following != NULL)
|
|
{
|
|
parser->rec->state->following->free(parser->rec->state->following);
|
|
parser->rec->state->following = NULL;
|
|
}
|
|
}
|
|
parser->rec->free(parser->rec);
|
|
parser->rec = NULL;
|
|
}
|
|
|
|
ANTLR3_FREE(parser);
|
|
}
|
|
|
|
/** Set the input stream and reset the parser
|
|
*/
|
|
static void
|
|
setTreeNodeStream (pANTLR3_TREE_PARSER parser, pANTLR3_COMMON_TREE_NODE_STREAM input)
|
|
{
|
|
parser->ctnstream = input;
|
|
parser->rec->reset (parser->rec);
|
|
parser->ctnstream->reset (parser->ctnstream);
|
|
}
|
|
|
|
/** Return a pointer to the input stream
|
|
*/
|
|
static pANTLR3_COMMON_TREE_NODE_STREAM
|
|
getTreeNodeStream (pANTLR3_TREE_PARSER parser)
|
|
{
|
|
return parser->ctnstream;
|
|
}
|
|
|
|
|
|
/** Override for standard base recognizer mismatch function
|
|
* as we have DOWN/UP nodes in the stream that have no line info,
|
|
* plus we want to alter the exception type.
|
|
*/
|
|
static void
|
|
mismatch (pANTLR3_BASE_RECOGNIZER recognizer, ANTLR3_UINT32 ttype, pANTLR3_BITSET_LIST follow)
|
|
{
|
|
recognizer->exConstruct(recognizer);
|
|
recognizer->recoverFromMismatchedToken(recognizer, ttype, follow);
|
|
}
|
|
|
|
#ifdef ANTLR3_WINDOWS
|
|
#pragma warning (push)
|
|
#pragma warning (disable : 4100)
|
|
#endif
|
|
|
|
// Default implementation is for parser and assumes a token stream as supplied by the runtime.
|
|
// You MAY need override this function if the standard TOKEN_STREAM is not what you are using.
|
|
//
|
|
static void *
|
|
getCurrentInputSymbol (pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_INT_STREAM istream)
|
|
{
|
|
pANTLR3_TREE_NODE_STREAM tns;
|
|
pANTLR3_COMMON_TREE_NODE_STREAM ctns;
|
|
|
|
tns = (pANTLR3_TREE_NODE_STREAM)(istream->super);
|
|
ctns = tns->ctns;
|
|
return tns->_LT(tns, 1);
|
|
}
|
|
|
|
|
|
// Default implementation is for parser and assumes a token stream as supplied by the runtime.
|
|
// You MAY need override this function if the standard BASE_TREE is not what you are using.
|
|
//
|
|
static void *
|
|
getMissingSymbol (pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_INT_STREAM istream, pANTLR3_EXCEPTION e,
|
|
ANTLR3_UINT32 expectedTokenType, pANTLR3_BITSET_LIST follow)
|
|
{
|
|
pANTLR3_TREE_NODE_STREAM tns;
|
|
pANTLR3_COMMON_TREE_NODE_STREAM ctns;
|
|
pANTLR3_BASE_TREE node;
|
|
pANTLR3_BASE_TREE current;
|
|
pANTLR3_COMMON_TOKEN token;
|
|
pANTLR3_STRING text;
|
|
ANTLR3_INT32 i;
|
|
|
|
// Dereference the standard pointers
|
|
//
|
|
tns = (pANTLR3_TREE_NODE_STREAM)(istream->super);
|
|
ctns = tns->ctns;
|
|
|
|
// Create a new empty node, by stealing the current one, or the previous one if the current one is EOF
|
|
//
|
|
current = tns->_LT(tns, 1);
|
|
i = -1;
|
|
|
|
if (current == &ctns->EOF_NODE.baseTree)
|
|
{
|
|
current = tns->_LT(tns, -1);
|
|
i--;
|
|
}
|
|
while (((pANTLR3_COMMON_TREE)(current->super))->factory == NULL)
|
|
{
|
|
current = tns->_LT(tns, i--);
|
|
}
|
|
|
|
node = current->dupNode(current);
|
|
|
|
// Find the newly dupicated token
|
|
//
|
|
token = node->getToken(node);
|
|
|
|
// Create the token text that shows it has been inserted
|
|
//
|
|
token->setText8 (token, (pANTLR3_UINT8)"<missing ");
|
|
text = token->getText (token);
|
|
text->append8 (text, (const char *)recognizer->state->tokenNames[expectedTokenType]);
|
|
text->append8 (text, (const char *)">");
|
|
|
|
// Finally return the pointer to our new node
|
|
//
|
|
return node;
|
|
}
|
|
#ifdef ANTLR3_WINDOWS
|
|
#pragma warning (pop)
|
|
#endif
|
|
|