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 */
38static void				mismatch	    (pANTLR3_BASE_RECOGNIZER recognizer, ANTLR3_UINT32 ttype, pANTLR3_BITSET_LIST follow);
39
40/* Tree parser API
41 */
42static void			setTreeNodeStream	    (pANTLR3_TREE_PARSER parser, pANTLR3_COMMON_TREE_NODE_STREAM input);
43static pANTLR3_COMMON_TREE_NODE_STREAM
44					getTreeNodeStream	    (pANTLR3_TREE_PARSER parser);
45static void			freeParser				(pANTLR3_TREE_PARSER parser);
46static void *		getCurrentInputSymbol	(pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_INT_STREAM istream);
47static void *		getMissingSymbol		(pANTLR3_BASE_RECOGNIZER recognizer, pANTLR3_INT_STREAM	istream, pANTLR3_EXCEPTION	e,
48												ANTLR3_UINT32 expectedTokenType, pANTLR3_BITSET_LIST follow);
49
50
51ANTLR3_API pANTLR3_TREE_PARSER
52antlr3TreeParserNewStream(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 */
110ANTLR3_API	void
111antlr3MTNExceptionNew(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
126static void
127freeParser	(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 */
152static void
153setTreeNodeStream	(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 */
162static pANTLR3_COMMON_TREE_NODE_STREAM
163getTreeNodeStream	(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 */
173static void
174mismatch	    (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//
188static void *
189getCurrentInputSymbol		(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//
203static void *
204getMissingSymbol			(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