summaryrefslogtreecommitdiff
path: root/antlr/libantlr3c-3.4/src/antlr3treeparser.c
blob: b7e035aa2ed6695c21fc65846431ffeea1b4e13b (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
/** \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