source: trunk/nomc/parser_c/interface_parser.c

Last change on this file was 385, checked in by cinc, 17 years ago

Reworked class-, metod- and typespec parsers.

  • Property svn:executable set to *
File size: 14.7 KB
Line 
1/* ***** BEGIN LICENSE BLOCK *****
2* Version: CDDL 1.0/LGPL 2.1
3*
4* The contents of this file are subject to the COMMON DEVELOPMENT AND
5* DISTRIBUTION LICENSE (CDDL) Version 1.0 (the "License"); you may not use
6* this file except in compliance with the License. You may obtain a copy of
7* the License at http://www.sun.com/cddl/
8*
9* Software distributed under the License is distributed on an "AS IS" basis,
10* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11* for the specific language governing rights and limitations under the
12* License.
13*
14* The Original Code is "NOM" Netlabs Object Model
15*
16* The Initial Developer of the Original Code is
17* netlabs.org: Chris Wohlgemuth <cinc-ml@netlabs.org>.
18* Portions created by the Initial Developer are Copyright (C) 2007
19* the Initial Developer. All Rights Reserved.
20*
21* Contributor(s):
22*
23* Alternatively, the contents of this file may be used under the terms of
24* the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
25* case the provisions of the LGPL are applicable instead of those above. If
26* you wish to allow use of your version of this file only under the terms of
27* the LGPL, and not to allow others to use your version of this file under
28* the terms of the CDDL, indicate your decision by deleting the provisions
29* above and replace them with the notice and other provisions required by the
30* LGPL. If you do not delete the provisions above, a recipient may use your
31* version of this file under the terms of any one of the CDDL or the LGPL.
32*
33* ***** END LICENSE BLOCK ***** */
34
35/*
36 Main file containing the interface parser. Whenever a valid keyword is found
37 a specialized parser function in another source file is called from here.
38 */
39#ifdef __OS2__
40# include <os2.h>
41#endif /* __OS2__ */
42
43#include <stdlib.h>
44#include <string.h>
45
46#include <glib.h>
47#include <glib/gprintf.h>
48#include "parser.h"
49
50extern GScanner *gScanner;
51
52static void registerInterface(void)
53{
54 PSYMBOL pNewSymbol=g_malloc0(sizeof(SYMBOL));
55 PPARSEINFO pParseInfo=(PPARSEINFO)gScanner->user_data;
56
57 //g_message("In %s for %s", __FUNCTION__, pParseInfo->pCurInterface->chrName);
58
59 pParseInfo->pCurInterface->pSymbolIFace=pNewSymbol;
60
61 if(!strcmp(pParseInfo->chrRootSourceFile, pParseInfo->pCurInterface->chrSourceFileName))
62 pParseInfo->pCurInterface->fIsInRootFile=TRUE;
63
64 g_ptr_array_add(pParseInfo->pInterfaceArray, (gpointer) pParseInfo->pCurInterface);
65
66 /* Any found interface is registered as a new type so it can be
67 used in other classes. */
68 pNewSymbol->chrSymbolName=g_strdup(pParseInfo->pCurInterface->chrName); /* We create a copy here because
69 when cleaning up the symbol space
70 the string will be freed. */
71 pNewSymbol->uiKind=KIND_TYPESPEC;
72 pNewSymbol->uiSymbolToken=IDL_SYMBOL_REGINTERFACE;
73 g_tree_insert(pParseInfo->pSymbolTree, pNewSymbol, pNewSymbol->chrSymbolName);
74 g_scanner_scope_add_symbol(gScanner, ID_SCOPE, pNewSymbol->chrSymbolName,
75 pNewSymbol);
76 /* For legacy support and convenience we automatically register a pointer type
77 to the interface. */
78 pNewSymbol=g_malloc0(sizeof(SYMBOL));
79 pParseInfo->pCurInterface->pSymbolIFacePtr=pNewSymbol;
80 pNewSymbol->uiKind=KIND_TYPESPEC;
81 pNewSymbol->uiSymbolToken=IDL_SYMBOL_REGINTERFACE;
82 pNewSymbol->chrSymbolName=g_strconcat("P", pParseInfo->pCurInterface->chrName, NULL);
83 g_tree_insert(pParseInfo->pSymbolTree, pNewSymbol, pNewSymbol->chrSymbolName);
84 g_scanner_scope_add_symbol(gScanner, ID_SCOPE, pNewSymbol->chrSymbolName,
85 pNewSymbol);
86 //g_message("%s: %s", __FUNCTION__, pNewSymbol->chrSymbolName);
87}
88
89static void deRegisterInterface(PINTERFACE pif)
90{
91 PPARSEINFO pParseInfo=(PPARSEINFO)gScanner->user_data;
92 //g_message("In %s", __FUNCTION__);
93
94 /* Remove the interface from our list */
95 g_ptr_array_remove(pParseInfo->pInterfaceArray, (gpointer) pif);
96
97 /* Any found interface was registered as a new type so it can be
98 used in other classes. */
99 g_tree_remove(pParseInfo->pSymbolTree, pif->pSymbolIFace);
100
101 g_scanner_scope_remove_symbol(gScanner, ID_SCOPE, pif->pSymbolIFace->chrSymbolName);
102 /* For legacy support and convenience we automatically registered a pointer type
103 to the interface. */
104 g_tree_remove(pParseInfo->pSymbolTree, pif->pSymbolIFacePtr);
105 g_scanner_scope_remove_symbol(gScanner, ID_SCOPE, pif->pSymbolIFacePtr->chrSymbolName);
106 /* We don't clean up. Looking at the whole mess with string dupes and stuff in side the
107 structs I just decided to use a GC instead... */
108}
109
110static PINTERFACE createInterfaceStruct()
111{
112 PINTERFACE pInterface;
113
114 pInterface=(PINTERFACE)g_malloc0(sizeof(INTERFACE));
115 //pInterface->pInstanceVarArray=g_ptr_array_new();
116 pInterface->pMethodArray=g_ptr_array_new();
117 //pInterface->pOverrideArray=g_ptr_array_new();
118
119 return pInterface;
120}
121
122/*
123 Function to parse the body of an interface declaration.
124 Current token is '{'.
125
126 IB:= CV // NOMCLASSVERSION()
127 | IV // NOMINSTANCEVAR()
128 | M // Method
129 | OV // Overriden method
130 */
131void parseIBody(void)
132{
133 /* Current token is '{' */
134
135 do{
136 //g_printf("%d: ", __LINE__);
137 //printToken(gScanner->token);
138
139 parseInterfaceMethod();
140
141#if 0
142 /* Typespec check must be first */
143 if(matchNextKind(KIND_TYPESPEC)) /* Be aware that we don't compare types here */
144 {
145 //g_printf("%d: ", __LINE__);
146 //printToken(gScanner->token);
147
148 parseInterfaceMethod();
149 }
150 else if(matchNext('#'))
151 parseHash();
152 else if(matchNext(G_TOKEN_IDENTIFIER))
153 {
154 //g_printf("%d: ", __LINE__);
155 //printToken(gScanner->token);
156
157 /* This may be an override statement */
158 // parseOverrideMethodFromIdentifier();
159 }
160 else if(matchNext(G_TOKEN_SYMBOL))
161 {
162 PSYMBOL pCurSymbol;
163 GTokenValue value;
164
165 value=gScanner->value;
166 pCurSymbol=value.v_symbol;
167 switch(pCurSymbol->uiSymbolToken)
168 {
169 default:
170 {
171 g_scanner_unexp_token(gScanner,
172 G_TOKEN_SYMBOL,
173 NULL,
174 NULL,
175 NULL,
176 "Trying to parse interface body.",
177 TRUE); /* is_error */
178 exit(1);
179 }
180 }/* switch */
181 }
182 else
183 {
184 getNextToken();
185 g_scanner_unexp_token(gScanner,
186 G_TOKEN_IDENTIFIER,
187 NULL,
188 NULL,
189 NULL,
190 "Trying to parse interface body.",
191 TRUE); /* is_error */
192 exit(1);
193 }
194#endif
195 }while(g_scanner_peek_next_token(gScanner)!='}');
196 //g_printf("%d: ", __LINE__);
197 //printToken(gScanner->token);
198
199}
200
201
202/*
203 Parse the interface name.
204 Note that the current token is the 'interface' keyword.
205
206 I:= IDL_SYMBOL_INTERFACE G_TOKEN_IDENTIFIER
207 */
208static void parseIFace(GTokenType token)
209{
210 PPARSEINFO pParseInfo=(PPARSEINFO)gScanner->user_data;
211
212 if(matchNext(G_TOKEN_IDENTIFIER))
213 {
214 /* Save interface info */
215 GTokenValue value=gScanner->value;
216 pParseInfo->pCurInterface->chrName=g_strdup(value.v_identifier);
217 }
218 else
219 {
220 if(matchNext(G_TOKEN_SYMBOL))
221 {
222 /* If the interface name is a symbol, it means the interface was
223 already registered before. Maybe because of a forward statement.
224 We will check that in the function which called us. */
225
226 /* Check if it's one of our interface symbols */
227 PSYMBOL pCurSymbol;
228 GTokenValue value;
229
230 value=gScanner->value;
231 pCurSymbol=value.v_symbol;
232 if(IDL_SYMBOL_REGINTERFACE!=pCurSymbol->uiSymbolToken)
233 {
234 //g_message("%s %d", pCurSymbol->chrSymbolName, pCurSymbol->uiKind);
235 g_scanner_unexp_token(gScanner,
236 G_TOKEN_SYMBOL,
237 NULL,
238 NULL,
239 NULL,
240 "Keyword 'interface' is not followed by a valid identifier.",
241 TRUE); /* is_error */
242 exit(1);
243 }
244 /* Save interface info */
245 pParseInfo->pCurInterface->chrName=g_strdup(pCurSymbol->chrSymbolName);
246 }
247 else{
248 g_scanner_unexp_token(gScanner,
249 G_TOKEN_IDENTIFIER,
250 NULL,
251 NULL,
252 NULL,
253 "Keyword 'interface' must be followed by an identifier",
254 TRUE); /* is_error */
255 exit(1);
256 }
257 }
258}
259
260/*
261 Current token is '{'.
262
263 IB2:= '{' IB '}'
264 | '{' IB '}' ';'
265
266*/
267static void parseIFaceBody(void)
268{
269 //g_printf("%d: ", __LINE__);
270 //printToken(gScanner->token);
271
272 parseIBody();
273 if(!matchNext('}'))
274 {
275 g_scanner_unexp_token(gScanner,
276 '}',
277 NULL,
278 NULL,
279 NULL,
280 "No closing of 'interface' section.",
281 TRUE); /* is_error */
282 exit(1);
283 }
284 /* Remove a terminating ';' from the input if present. */
285 matchNext(';');
286}
287
288/*
289 Parse an interface which is subclassed. This includes checking if the parent
290 interface is already defined.
291
292 IS:= G_TOKEN_SYMBOL IB2
293
294 It's G_TOKEN_SYMBOL here because every found interface is registered
295 as a new symbol with GScanner.
296 */
297static void parseSubclassedIFace()
298{
299 PSYMBOL pCurSymbol;
300 GTokenValue value;
301 PPARSEINFO pParseInfo=(PPARSEINFO)gScanner->user_data;
302
303 /* Parent interface */
304 if(!matchNext(G_TOKEN_SYMBOL))
305 {
306 g_scanner_unexp_token(gScanner,
307 G_TOKEN_SYMBOL,
308 NULL,
309 NULL,
310 NULL,
311 "Parent interface name is missing or unknown.",
312 TRUE); /* is_error */
313 exit(1);
314 }
315 value=gScanner->value;
316 /* Make sure it's the correct symbol */
317 pCurSymbol=value.v_symbol;
318
319 if(IDL_SYMBOL_REGINTERFACE!=pCurSymbol->uiSymbolToken)
320 {
321 g_scanner_unexp_token(gScanner,
322 G_TOKEN_SYMBOL,
323 NULL,
324 NULL,
325 NULL,
326 "Parent interface name is unknown.",
327 TRUE); /* is_error */
328 exit(1);
329 }
330 pParseInfo->pCurInterface->chrParent=g_strdup(pCurSymbol->chrSymbolName);
331
332 /* Check if the parent interface is known. */
333 if(!findInterfaceFromName(pParseInfo->pCurInterface->chrParent))
334 {
335 g_scanner_unexp_token(gScanner,
336 G_TOKEN_IDENTIFIER,
337 NULL,
338 NULL,
339 NULL,
340 "Parent interface in definition is unknown.",
341 TRUE); /* is_error */
342 exit(1);
343 }
344
345 if(!matchNext('{'))
346 {
347 g_scanner_unexp_token(gScanner,
348 '{',
349 NULL,
350 NULL,
351 NULL,
352 "No opening brace in interface definition.",
353 TRUE); /* is_error */
354 exit(1);
355 }
356 parseIFaceBody();
357}
358
359/*
360 Parse an interface declaration. The current token is the 'interface' keyword.
361
362 interface:= I ';' // Forward declaration
363 | I IB2
364 | I ':' IS // Subclassed interface
365
366 This translates into:
367
368 interface:= I ';' // Forward declaration
369 | I '{' IB '}'
370 | I ':' G_TOKEN_SYMBOL '{' IB '}'
371
372 It's G_TOKEN_SYMBOL here because every found interface is registered
373 as a new symbol with GScanner.
374 */
375void parseInterface(GTokenType token)
376{
377 PPARSEINFO pParseInfo=(PPARSEINFO)gScanner->user_data;
378
379 pParseInfo->pCurInterface=createInterfaceStruct();
380
381 /* Get the interface name */
382 parseIFace(token);
383
384 if(matchNext(';')) /* forward declaration */
385 {
386 PINTERFACE pif;
387
388 /* Check if we already have a (maybe forward) declaration */
389 pif=findInterfaceFromName(pParseInfo->pCurInterface->chrName);
390 if(pif)
391 {
392 g_free(pParseInfo->pCurInterface);
393 }
394 else{
395 pParseInfo->pCurInterface->chrSourceFileName=g_strdup(pParseInfo->chrCurrentSourceFile);
396 pParseInfo->pCurInterface->fIsForwardDeclaration=TRUE;
397 /* It's save to register the interface right here even if the struct is almost empty.
398 If anything goes wrong later we will exit anyway. */
399 registerInterface();
400 }
401 }
402 else
403 {
404 PINTERFACE pif;
405 gchar *chrTemp=pParseInfo->pCurInterface->chrName;
406
407 /* Check if we already have a (maybe forward) declaration */
408 pif=findInterfaceFromName(pParseInfo->pCurInterface->chrName);
409 if(pif)
410 {
411 if(pif->fIsForwardDeclaration)
412 {
413 /* Remove the forward declaration and insert the real thing afterwards. */
414 deRegisterInterface(pif);
415 }
416 else
417 {
418 /* Oops, we already have an interface declaration */
419 g_scanner_unexp_token(gScanner,
420 G_TOKEN_SYMBOL,
421 NULL,
422 NULL,
423 NULL,
424 "An interface with this name was already declared.",
425 TRUE); /* is_error */
426 exit(1);
427 }
428 }
429 pParseInfo->pCurInterface->chrName=chrTemp;
430 pParseInfo->pCurInterface->chrSourceFileName=g_strdup(pParseInfo->chrCurrentSourceFile);
431 /* It's save to register the interface right here even if the struct is almost empty.
432 If anything goes wrong later we will exit anyway. */
433 registerInterface();
434 if(matchNext(':'))
435 {
436 parseSubclassedIFace();
437 }
438 else if(matchNext('{'))
439 {
440 parseIFaceBody();
441 }
442 else
443 {
444 g_message("Line %d: Error in interface declaration", g_scanner_cur_line(gScanner));
445 exit(0);
446 }
447 }
448}
449
Note: See TracBrowser for help on using the repository browser.