source: trunk/idl-compiler/parser_c/interface_parser.c

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

Portability patches for Windows, Linux, Darwin by Bird.

File size: 15.0 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;
51extern PPARSEINFO pParseInfo;
52
53static void registerInterface(void)
54{
55 PSYMBOL pNewSymbol=g_malloc0(sizeof(SYMBOL));
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 //g_message("In %s", __FUNCTION__);
92
93 /* Remove the interface from our list */
94 g_ptr_array_remove(pParseInfo->pInterfaceArray, (gpointer) pif);
95
96 /* Any found interface was registered as a new type so it can be
97 used in other classes. */
98 g_tree_remove(pParseInfo->pSymbolTree, pif->pSymbolIFace);
99
100 g_scanner_scope_remove_symbol(gScanner, ID_SCOPE, pif->pSymbolIFace->chrSymbolName);
101 /* For legacy support and convenience we automatically registered a pointer type
102 to the interface. */
103 g_tree_remove(pParseInfo->pSymbolTree, pif->pSymbolIFacePtr);
104 g_scanner_scope_remove_symbol(gScanner, ID_SCOPE, pif->pSymbolIFacePtr->chrSymbolName);
105 /* We don't clean up. Looking at the whole mess with string dupes and stuff in side the
106 structs I just decided to use a GC instead... */
107}
108
109static PINTERFACE createInterfaceStruct()
110{
111 PINTERFACE pInterface;
112
113 pInterface=(PINTERFACE)g_malloc0(sizeof(INTERFACE));
114 pInterface->pInstanceVarArray=g_ptr_array_new();
115 pInterface->pMethodArray=g_ptr_array_new();
116 pInterface->pOverrideArray=g_ptr_array_new();
117
118 return pInterface;
119}
120
121/*
122 Function to parse the body of an interface declaration.
123 Current token is '{'.
124
125 IB:= CV // NOMCLASSVERSION()
126 | IV // NOMINSTANCEVAR()
127 | M // Method
128 | OV // Overriden method
129 */
130void parseIBody(void)
131{
132 /* Current token is '{' */
133
134 do{
135 // g_printf("%d: ", __LINE__);
136 // printToken(curToken);
137
138 /* Typespec check must be first */
139 if(matchNextKind(KIND_TYPESPEC)) /* Be aware that we don't compare types here */
140 {
141 parseMethod();
142 }
143 else if(matchNext('#'))
144 parseHash();
145 else if(matchNext(G_TOKEN_IDENTIFIER))
146 {
147 /* This may be an override statement */
148 parseOverrideMethodFromIdentifier();
149 }
150 else if(matchNext(G_TOKEN_SYMBOL))
151 {
152 PSYMBOL pCurSymbol;
153 GTokenValue value;
154
155 value=gScanner->value;
156 pCurSymbol=value.v_symbol;
157 switch(pCurSymbol->uiSymbolToken)
158 {
159 case IDL_SYMBOL_OVERRIDE: /* This one is deprecated */
160 parseOverrideMethod();
161 break;
162 case IDL_SYMBOL_CLSVERSION:
163 parseClassVersion();
164 break;
165 case IDL_SYMBOL_INSTANCEVAR:
166 parseInstanceVar();
167 break;
168 case IDL_SYMBOL_METACLASS:
169 parseMetaClass();
170 break;
171 case IDL_SYMBOL_FILESTEM:
172 parseFileStem();
173 break;
174 default:
175 {
176 g_scanner_unexp_token(gScanner,
177 G_TOKEN_SYMBOL,
178 NULL,
179 NULL,
180 NULL,
181 "Trying to parse interface body.",
182 TRUE); /* is_error */
183 exit(1);
184 }
185 }/* switch */
186 }
187 else
188 {
189 getNextToken();
190 g_scanner_unexp_token(gScanner,
191 G_TOKEN_IDENTIFIER,
192 NULL,
193 NULL,
194 NULL,
195 "Trying to parse interface body.",
196 TRUE); /* is_error */
197 exit(1);
198 }
199 }while(g_scanner_peek_next_token(gScanner)!='}');
200}
201
202
203/*
204 Parse the interface name.
205 Note that the current token is the 'interface' keyword.
206
207 I:= IDL_SYMBOL_INTERFACE G_TOKEN_IDENTIFIER
208 */
209static void parseIFace(GTokenType token)
210{
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 parseIBody();
270 if(!matchNext('}'))
271 {
272 g_scanner_unexp_token(gScanner,
273 '}',
274 NULL,
275 NULL,
276 NULL,
277 "No closing of 'interface' section.",
278 TRUE); /* is_error */
279 exit(1);
280 }
281 /* Remove a terminating ';' from the input if present. */
282 matchNext(';');
283}
284
285/*
286 Parse an interface which is subclassed. This includes checking if the parent
287 interface is already defined.
288
289 IS:= G_TOKEN_SYMBOL IB2
290
291 It's G_TOKEN_SYMBOL here because every found interface is registered
292 as a new symbol with GScanner.
293 */
294static void parseSubclassedIFace()
295{
296 PSYMBOL pCurSymbol;
297 GTokenValue value;
298
299 /* Parent interface */
300 if(!matchNext(G_TOKEN_SYMBOL))
301 {
302 g_scanner_unexp_token(gScanner,
303 G_TOKEN_SYMBOL,
304 NULL,
305 NULL,
306 NULL,
307 "Parent interface name is missing or unknown.",
308 TRUE); /* is_error */
309 exit(1);
310 }
311 value=gScanner->value;
312 /* Make sure it's the correct symbol */
313 pCurSymbol=value.v_symbol;
314
315 if(IDL_SYMBOL_REGINTERFACE!=pCurSymbol->uiSymbolToken)
316 {
317 g_scanner_unexp_token(gScanner,
318 G_TOKEN_SYMBOL,
319 NULL,
320 NULL,
321 NULL,
322 "Parent interface name is unknown.",
323 TRUE); /* is_error */
324 exit(1);
325 }
326 pParseInfo->pCurInterface->chrParent=g_strdup(pCurSymbol->chrSymbolName);
327
328 /* Check if the parent interface is known. */
329 if(!findInterfaceFromName(pParseInfo->pCurInterface->chrParent))
330 {
331 g_scanner_unexp_token(gScanner,
332 G_TOKEN_IDENTIFIER,
333 NULL,
334 NULL,
335 NULL,
336 "Parent interface in definition is unknown.",
337 TRUE); /* is_error */
338 exit(1);
339 }
340
341 if(!matchNext('{'))
342 {
343 g_scanner_unexp_token(gScanner,
344 '{',
345 NULL,
346 NULL,
347 NULL,
348 "No opening brace in interface definition.",
349 TRUE); /* is_error */
350 exit(1);
351 }
352 parseIFaceBody();
353}
354
355/*
356 Parse an interface declaration. The current token is the 'interface' keyword.
357
358 interface:= I ';' // Forward declaration
359 | I IB2
360 | I ':' IS // Subclassed interface
361
362 This translates into:
363
364 interface:= I ';' // Forward declaration
365 | I '{' IB '}'
366 | I ':' G_TOKEN_SYMBOL '{' IB '}'
367
368 It's G_TOKEN_SYMBOL here because every found interface is registered
369 as a new symbol with GScanner.
370 */
371void parseInterface(GTokenType token)
372{
373 pParseInfo->pCurInterface=createInterfaceStruct();
374
375 /* Get the interface name */
376 parseIFace(token);
377
378 if(matchNext(';')) /* forward declaration */
379 {
380 PINTERFACE pif;
381
382 /* Check if we already have a (maybe forward) declaration */
383 pif=findInterfaceFromName(pParseInfo->pCurInterface->chrName);
384 if(pif)
385 {
386 g_free(pParseInfo->pCurInterface);
387 }
388 else{
389 pParseInfo->pCurInterface->chrSourceFileName=g_strdup(pParseInfo->chrCurrentSourceFile);
390 pParseInfo->pCurInterface->fIsForwardDeclaration=TRUE;
391 /* It's save to register the interface right here even if the struct is almost empty.
392 If anything goes wrong later we will exit anyway. */
393 registerInterface();
394 }
395 }
396 else
397 {
398 PINTERFACE pif;
399 gchar *chrTemp=pParseInfo->pCurInterface->chrName;
400
401 /* Check if we already have a (maybe forward) declaration */
402 pif=findInterfaceFromName(pParseInfo->pCurInterface->chrName);
403 if(pif)
404 {
405 if(pif->fIsForwardDeclaration)
406 {
407 /* Remove the forward declaration and insert the real thing afterwards. */
408 deRegisterInterface(pif);
409 }
410 else
411 {
412 /* Oops, we already have an interface declaration */
413 g_scanner_unexp_token(gScanner,
414 G_TOKEN_SYMBOL,
415 NULL,
416 NULL,
417 NULL,
418 "An interface with this name was already declared.",
419 TRUE); /* is_error */
420 exit(1);
421 }
422 }
423 pParseInfo->pCurInterface->chrName=chrTemp;
424 pParseInfo->pCurInterface->chrSourceFileName=g_strdup(pParseInfo->chrCurrentSourceFile);
425 /* It's save to register the interface right here even if the struct is almost empty.
426 If anything goes wrong later we will exit anyway. */
427 registerInterface();
428 if(matchNext(':'))
429 {
430 parseSubclassedIFace();
431 }
432 else if(matchNext('{'))
433 {
434 parseIFaceBody();
435 }
436 else
437 {
438 g_message("Line %d: Error in interface declaration", g_scanner_cur_line(gScanner));
439 exit(0);
440 }
441 }
442}
443
Note: See TracBrowser for help on using the repository browser.