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
antlr3TreeParserNewStream(ANTLR3_UINT32 sizeHint,pANTLR3_COMMON_TREE_NODE_STREAM ctnstream,pANTLR3_RECOGNIZER_SHARED_STATE state)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
antlr3MTNExceptionNew(pANTLR3_BASE_RECOGNIZER recognizer)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
freeParser(pANTLR3_TREE_PARSER parser)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
setTreeNodeStream(pANTLR3_TREE_PARSER parser,pANTLR3_COMMON_TREE_NODE_STREAM input)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
getTreeNodeStream(pANTLR3_TREE_PARSER parser)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
mismatch(pANTLR3_BASE_RECOGNIZER recognizer,ANTLR3_UINT32 ttype,pANTLR3_BITSET_LIST follow)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 *
getCurrentInputSymbol(pANTLR3_BASE_RECOGNIZER recognizer,pANTLR3_INT_STREAM istream)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 *
getMissingSymbol(pANTLR3_BASE_RECOGNIZER recognizer,pANTLR3_INT_STREAM istream,pANTLR3_EXCEPTION e,ANTLR3_UINT32 expectedTokenType,pANTLR3_BITSET_LIST follow)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