/** \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 /* 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 = (pANTLR3_BASE_TREE)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)"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