1 /** \file 2 * Implementation of the tree parser and overrides for the base recognizer 3 */ 4 5 // [The "BSD licence"] 6 // Copyright (c) 2005-2009 Jim Idle, Temporal Wave LLC 7 // http://www.temporal-wave.com 8 // http://www.linkedin.com/in/jimidle 9 // 10 // All rights reserved. 11 // 12 // Redistribution and use in source and binary forms, with or without 13 // modification, are permitted provided that the following conditions 14 // are met: 15 // 1. Redistributions of source code must retain the above copyright 16 // notice, this list of conditions and the following disclaimer. 17 // 2. Redistributions in binary form must reproduce the above copyright 18 // notice, this list of conditions and the following disclaimer in the 19 // documentation and/or other materials provided with the distribution. 20 // 3. The name of the author may not be used to endorse or promote products 21 // derived from this software without specific prior written permission. 22 // 23 // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 // IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 34 #include <antlr3treeparser.h> 35 36 /* BASE Recognizer overrides 37 */ 38 static void mismatch (pANTLR3_BASE_RECOGNIZER recognizer, ANTLR3_UINT32 ttype, pANTLR3_BITSET_LIST follow); 39 40 /* Tree parser API 41 */ 42 static void setTreeNodeStream (pANTLR3_TREE_PARSER parser, pANTLR3_COMMON_TREE_NODE_STREAM input); 43 static pANTLR3_COMMON_TREE_NODE_STREAM 44 getTreeNodeStream (pANTLR3_TREE_PARSER parser); 45 static void freeParser (pANTLR3_TREE_PARSER parser); 46 static void * getCurrentInputSymbol (pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_INT_STREAM istream); 47 static void * getMissingSymbol (pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_INT_STREAM istream, pANTLR3_EXCEPTION e, 48 ANTLR3_UINT32 expectedTokenType, pANTLR3_BITSET_LIST follow); 49 50 51 ANTLR3_API pANTLR3_TREE_PARSER 52 antlr3TreeParserNewStream(ANTLR3_UINT32 sizeHint, pANTLR3_COMMON_TREE_NODE_STREAM ctnstream, pANTLR3_RECOGNIZER_SHARED_STATE state) 53 { 54 pANTLR3_TREE_PARSER parser; 55 56 /** Allocate tree parser memory 57 */ 58 parser =(pANTLR3_TREE_PARSER) ANTLR3_MALLOC(sizeof(ANTLR3_TREE_PARSER)); 59 60 if (parser == NULL) 61 { 62 return NULL; 63 } 64 65 /* Create and install a base recognizer which does most of the work for us 66 */ 67 parser->rec = antlr3BaseRecognizerNew(ANTLR3_TYPE_PARSER, sizeHint, state); 68 69 if (parser->rec == NULL) 70 { 71 parser->free(parser); 72 return NULL; 73 } 74 75 /* Ensure we can track back to the tree parser super structure 76 * from the base recognizer structure 77 */ 78 parser->rec->super = parser; 79 parser->rec->type = ANTLR3_TYPE_TREE_PARSER; 80 81 /* Install our base recognizer overrides 82 */ 83 parser->rec->mismatch = mismatch; 84 parser->rec->exConstruct = antlr3MTNExceptionNew; 85 parser->rec->getCurrentInputSymbol = getCurrentInputSymbol; 86 parser->rec->getMissingSymbol = getMissingSymbol; 87 88 /* Install tree parser API 89 */ 90 parser->getTreeNodeStream = getTreeNodeStream; 91 parser->setTreeNodeStream = setTreeNodeStream; 92 parser->free = freeParser; 93 94 /* Install the tree node stream 95 */ 96 parser->setTreeNodeStream(parser, ctnstream); 97 98 return parser; 99 } 100 101 /** 102 * \brief 103 * Creates a new Mismatched Tree Nde Exception and inserts in the recognizer 104 * exception stack. 105 * 106 * \param recognizer 107 * Context pointer for this recognizer 108 * 109 */ 110 ANTLR3_API void 111 antlr3MTNExceptionNew(pANTLR3_BASE_RECOGNIZER recognizer) 112 { 113 /* Create a basic recognition exception structure 114 */ 115 antlr3RecognitionExceptionNew(recognizer); 116 117 /* Now update it to indicate this is a Mismatched token exception 118 */ 119 recognizer->state->exception->name = ANTLR3_MISMATCHED_TREE_NODE_NAME; 120 recognizer->state->exception->type = ANTLR3_MISMATCHED_TREE_NODE_EXCEPTION; 121 122 return; 123 } 124 125 126 static void 127 freeParser (pANTLR3_TREE_PARSER parser) 128 { 129 if (parser->rec != NULL) 130 { 131 // This may have ben a delegate or delegator parser, in which case the 132 // state may already have been freed (and set to NULL therefore) 133 // so we ignore the state if we don't have it. 134 // 135 if (parser->rec->state != NULL) 136 { 137 if (parser->rec->state->following != NULL) 138 { 139 parser->rec->state->following->free(parser->rec->state->following); 140 parser->rec->state->following = NULL; 141 } 142 } 143 parser->rec->free(parser->rec); 144 parser->rec = NULL; 145 } 146 147 ANTLR3_FREE(parser); 148 } 149 150 /** Set the input stream and reset the parser 151 */ 152 static void 153 setTreeNodeStream (pANTLR3_TREE_PARSER parser, pANTLR3_COMMON_TREE_NODE_STREAM input) 154 { 155 parser->ctnstream = input; 156 parser->rec->reset (parser->rec); 157 parser->ctnstream->reset (parser->ctnstream); 158 } 159 160 /** Return a pointer to the input stream 161 */ 162 static pANTLR3_COMMON_TREE_NODE_STREAM 163 getTreeNodeStream (pANTLR3_TREE_PARSER parser) 164 { 165 return parser->ctnstream; 166 } 167 168 169 /** Override for standard base recognizer mismatch function 170 * as we have DOWN/UP nodes in the stream that have no line info, 171 * plus we want to alter the exception type. 172 */ 173 static void 174 mismatch (pANTLR3_BASE_RECOGNIZER recognizer, ANTLR3_UINT32 ttype, pANTLR3_BITSET_LIST follow) 175 { 176 recognizer->exConstruct(recognizer); 177 recognizer->recoverFromMismatchedToken(recognizer, ttype, follow); 178 } 179 180 #ifdef ANTLR3_WINDOWS 181 #pragma warning (push) 182 #pragma warning (disable : 4100) 183 #endif 184 185 // Default implementation is for parser and assumes a token stream as supplied by the runtime. 186 // You MAY need override this function if the standard TOKEN_STREAM is not what you are using. 187 // 188 static void * 189 getCurrentInputSymbol (pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_INT_STREAM istream) 190 { 191 pANTLR3_TREE_NODE_STREAM tns; 192 pANTLR3_COMMON_TREE_NODE_STREAM ctns; 193 194 tns = (pANTLR3_TREE_NODE_STREAM)(istream->super); 195 ctns = tns->ctns; 196 return tns->_LT(tns, 1); 197 } 198 199 200 // Default implementation is for parser and assumes a token stream as supplied by the runtime. 201 // You MAY need override this function if the standard BASE_TREE is not what you are using. 202 // 203 static void * 204 getMissingSymbol (pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_INT_STREAM istream, pANTLR3_EXCEPTION e, 205 ANTLR3_UINT32 expectedTokenType, pANTLR3_BITSET_LIST follow) 206 { 207 pANTLR3_TREE_NODE_STREAM tns; 208 pANTLR3_COMMON_TREE_NODE_STREAM ctns; 209 pANTLR3_BASE_TREE node; 210 pANTLR3_BASE_TREE current; 211 pANTLR3_COMMON_TOKEN token; 212 pANTLR3_STRING text; 213 ANTLR3_INT32 i; 214 215 // Dereference the standard pointers 216 // 217 tns = (pANTLR3_TREE_NODE_STREAM)(istream->super); 218 ctns = tns->ctns; 219 220 // Create a new empty node, by stealing the current one, or the previous one if the current one is EOF 221 // 222 current = tns->_LT(tns, 1); 223 i = -1; 224 225 if (current == &ctns->EOF_NODE.baseTree) 226 { 227 current = tns->_LT(tns, -1); 228 i--; 229 } 230 while (((pANTLR3_COMMON_TREE)(current->super))->factory == NULL) 231 { 232 current = tns->_LT(tns, i--); 233 } 234 235 node = current->dupNode(current); 236 237 // Find the newly dupicated token 238 // 239 token = node->getToken(node); 240 241 // Create the token text that shows it has been inserted 242 // 243 token->setText8 (token, (pANTLR3_UINT8)"<missing "); 244 text = token->getText (token); 245 text->append8 (text, (const char *)recognizer->state->tokenNames[expectedTokenType]); 246 text->append8 (text, (const char *)">"); 247 248 // Finally return the pointer to our new node 249 // 250 return node; 251 } 252 #ifdef ANTLR3_WINDOWS 253 #pragma warning (pop) 254 #endif 255 256