source: trunk/nomc/parser_c/classmethod_parser.c

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

Use 'public' instead of 'impl' as keyword for methods.

  • Property svn:executable set to *
File size: 11.8 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-2008
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#ifdef __OS2__
35# include <os2.h>
36#endif /* __OS2__ */
37
38#include <stdlib.h>
39
40#include <glib.h>
41#include <glib/gprintf.h>
42#include "parser.h"
43
44extern GScanner *gScanner;
45
46/* In override_parser.c */
47extern PINTERFACE findInterfaceForMethod(PINTERFACE pStartInterface, gchar* chrMethodName);
48
49
50static PMETHOD createMethodStruct()
51{
52 PMETHOD pMethod=g_malloc0(sizeof(METHOD));
53
54 pMethod->pParamArray=g_ptr_array_new();
55
56 return pMethod;
57}
58
59/*
60 Parse one or more method parameters. Note that the check for '(' and ')' is
61 done in the calling function.
62
63 MPARAMS:= DIRECTION TS G_TOKEN_IDENTIFIER
64 | MPARAMS ',' MPARAMS
65 */
66static void parseMethodParams(PMETHOD pMethod)
67{
68 GTokenValue value;
69 PMETHODPARAM pParam;
70 PSYMBOL pCurSymbol;
71
72 do{
73 pParam=g_malloc0(sizeof(METHODPARAM));
74
75 /* Direction */
76 if(!matchNextKind(KIND_DIRECTION)) /* Be aware that we don't compare types here */
77 {
78#if 0
79 getNextToken(); /* Make sure error references the correct token */
80 g_scanner_unexp_token(gScanner,
81 G_TOKEN_IDENTIFIER,
82 NULL,
83 NULL,
84 NULL,
85 "Error in method declaration, direction (in|out|inout) is not specified.",
86 TRUE); /* is_error */
87 cleanupAndExit(1);
88#endif
89 pParam->uiDirection=PARM_DIRECTION_IN;
90 }
91 else
92 {
93 value=gScanner->value;
94 pCurSymbol=value.v_symbol;
95 switch(pCurSymbol->uiSymbolToken)
96 {
97 case IDL_SYMBOL_IN:
98 pParam->uiDirection=PARM_DIRECTION_IN;
99 break;
100 case IDL_SYMBOL_OUT:
101 pParam->uiDirection=PARM_DIRECTION_OUT;
102 break;
103 case IDL_SYMBOL_INOUT:
104 pParam->uiDirection=PARM_DIRECTION_INOUT;
105 break;
106 default:
107 break;
108 }
109 }
110
111 parseTypeSpec(pParam);
112#if 0
113 /* Typespec */
114 if(matchNextKind(KIND_TYPESPEC)) /* Be aware that we don't compare types here */
115 parseTypeSpec(pParam);
116 else
117 {
118 getNextToken(); /* Make sure error references the correct token */
119 g_scanner_unexp_token(gScanner,
120 G_TOKEN_IDENTIFIER,
121 NULL,
122 NULL,
123 NULL,
124 "Error in method declaration, Unknown type specification.",
125 TRUE); /* is_error */
126 cleanupAndExit(1);
127 }
128#endif
129 //pParam->chrType=getTypeSpecStringFromCurToken();
130 //g_printf("%s %d", __FUNCTION__, __LINE__);
131 //printToken(curToken);
132 exitIfNotMatchNext(G_TOKEN_IDENTIFIER, "Error in method declaration. Wrong parameter name.");
133
134 value=gScanner->value;
135 pParam->chrName=g_strdup(value.v_identifier);
136
137 g_ptr_array_add(pMethod->pParamArray , (gpointer) pParam);
138 }while(matchNext(','));
139}
140
141
142
143
144static void doSingleMethodParam(void)
145{
146 GTokenValue value;
147 PSYMBOL pCurSymbol;
148
149 PMETHODPARAM pParam;
150 pParam=g_malloc0(sizeof(METHODPARAM));
151
152 /* Do direction */
153 /* Direction */
154 if(!matchNextKind(KIND_DIRECTION)) /* Be aware that we don't compare types here */
155 {
156 pParam->uiDirection=PARM_DIRECTION_IN;
157 }
158 else
159 {
160 value=gScanner->value;
161 pCurSymbol=value.v_symbol;
162 switch(pCurSymbol->uiSymbolToken)
163 {
164 case IDL_SYMBOL_IN:
165 pParam->uiDirection=PARM_DIRECTION_IN;
166 break;
167 case IDL_SYMBOL_OUT:
168 pParam->uiDirection=PARM_DIRECTION_OUT;
169 break;
170 case IDL_SYMBOL_INOUT:
171 pParam->uiDirection=PARM_DIRECTION_INOUT;
172 break;
173 default:
174 break;
175 }
176 }
177
178
179 /* Do typespec */
180
181 /* Do identifier */
182 exitIfNotMatchNext(G_TOKEN_IDENTIFIER, "Error in method implementation.");
183
184 /* The current token is the identifier */
185 value=gScanner->value;
186 pParam->chrName=g_strdup(value.v_identifier);
187
188
189}
190
191/*
192
193 MPARAMS := ˚)˚
194 | MPARAM
195 | MPARAM ',' MPARAMS
196 */
197static void doMethodParams(PMETHOD pMethod)
198{
199
200 while(g_scanner_peek_next_token(gScanner)!= G_TOKEN_EOF && g_scanner_peek_next_token(gScanner)!=')')
201 {
202 doSingleMethodParam();
203
204 if(!matchNext(','))
205 break;
206 }
207 exitIfNotMatchNext(')', "No closing of method parameter list.");
208}
209
210/*
211
212 MPARAM := TYPESPEC IDENT
213
214 */
215
216
217/*
218 Current token is the one just before the typespec.
219
220 METHOD := TYPESPEC IDENT '(' MPARAMS
221
222 */
223static void parseMethod(PMETHOD pMethod)
224{
225 GTokenValue value;
226 PINTERFACE pif;
227 PPARSEINFO pParseInfo=(PPARSEINFO)gScanner->user_data;
228
229 /********* Parse typespec *******************************************/
230
231
232 /********* Method identifier ****************************************/
233
234 exitIfNotMatchNext(G_TOKEN_IDENTIFIER, "Error in method implementation.");
235
236 /* The current token is the identifier */
237 value=gScanner->value;
238 pMethod->chrName=g_strdup(value.v_identifier);
239
240 /* Now check if the method was introduced by some parent. The interface struct contains
241 the parent name if any and the function will follow the chain of parents. */
242 if((pif=findInterfaceForMethod(pParseInfo->pCurInterface, pMethod->chrName))!=NULL)
243 {
244 gchar* chrMessage;
245 chrMessage=g_strdup_printf("A method '%s' is already present in interface '%s'.",
246 pMethod->chrName, pif->chrName);
247
248 g_scanner_unexp_token(gScanner,
249 G_TOKEN_IDENTIFIER,
250 NULL, NULL, NULL,
251 chrMessage,
252 TRUE); /* is_error */
253 cleanupAndExit(1);
254 }
255
256 /* Check if the method is defined at all */
257 if(NULL==findMethodInfoFromMethodNameWithCurrent(pParseInfo->pClassDefinition, pMethod->chrName))
258 {
259 gchar* chrMessage;
260 chrMessage=g_strdup_printf("Method '%s' is not defined for the current class or one of the parents.",
261 pMethod->chrName);
262
263 g_scanner_unexp_token(gScanner,
264 G_TOKEN_IDENTIFIER,
265 NULL, NULL, NULL,
266 chrMessage,
267 TRUE); /* is_error */
268 cleanupAndExit(1);
269
270 }
271
272 /****** Method parameters ***************************************************/
273 exitIfNotMatchNext('(', "Error in method implementation.");
274
275 /* Do parameters */
276
277}
278
279/*
280
281 CLASSMETHODS:= CLASSMETHOD
282 | CLASSMETHOD CLASSMETHODS
283
284 CLASSMETHOD := IMPL METHOD
285
286 */
287static void parseSingleClassMethod(void)
288{
289 GTokenValue value;
290 PSYMBOL pCurSymbol;
291 PPARSEINFO pParseInfo=(PPARSEINFO)gScanner->user_data;
292 PMETHOD pMethod=createMethodStruct();
293
294 g_ptr_array_add( pParseInfo->pCurInterface->pMethodArray, (gpointer) pMethod);
295
296 /* Method implementations must start with "impl" which is registered as a symbol. Here we check if
297 the token is a symbol. */
298 exitIfNotMatchNext(G_TOKEN_SYMBOL, "Method implementation must start with 'impl'.");
299
300 value=gScanner->value;
301 pCurSymbol=value.v_symbol;
302
303 /* Check if symbol is "impl". */
304 if(!pCurSymbol || pCurSymbol->uiSymbolToken!=NOMC_SYMBOL_PUBLIC)
305 {
306 g_scanner_unexp_token(gScanner,
307 G_TOKEN_SYMBOL,
308 NULL, NULL, NULL,
309 "'impl'.",
310 TRUE); /* is_error */
311 cleanupAndExit(1);
312 }
313
314 /* Parse method */
315 parseMethod(pMethod);
316}
317
318/*
319
320 CLASSMETHODS:= IMPL METHOD
321 | IMPL METHOD CLASSMETHODS
322*/
323 void parseClassMethods(void)
324{
325 do
326 {
327 PSYMBOL pCurSymbol;
328 GTokenValue value;
329
330 /* There must be at least one class method */
331 parseSingleClassMethod();
332
333 /* Any additional methods start with ˚impl˚ */
334 if(g_scanner_peek_next_token(gScanner)!=G_TOKEN_SYMBOL)
335 break;
336
337 value=gScanner->next_value;
338 pCurSymbol=value.v_symbol;
339
340 if(!pCurSymbol || pCurSymbol->uiSymbolToken!=NOMC_SYMBOL_PUBLIC)
341 break;
342 }while(g_scanner_peek_next_token(gScanner)!= G_TOKEN_EOF);
343}
344
345/*
346 Current token is the typespec.
347
348 TS:= TYPE_SPEC //typespec, see elsewhere
349 | TYPE_SPEC '*'
350
351 M:= TS G_TOKEN_IDENTIFIER '(' ')' BLOCK // method
352 | TS G_TOKEN_IDENTIFIER '(' MPARMS ')' BLOCK // method
353 */
354void parseClassMethod(void)
355{
356 GTokenValue value;
357 PMETHOD pMethod=createMethodStruct();
358 PINTERFACE pif;
359 PPARSEINFO pParseInfo=(PPARSEINFO)gScanner->user_data;
360
361 /* Do type spec */
362 parseTypeSpec(&pMethod->mpReturn);
363
364 /* Method name G_TOKEN_IDENTIFIER */
365 exitIfNotMatchNext(G_TOKEN_IDENTIFIER, "Error in method declaration.");
366
367 value=gScanner->value;
368 pMethod->chrName=g_strdup(value.v_identifier);
369
370 /* Now check if the method was introduced by some parent. The interface struct contains
371 the parent name if any and the function will follow the chain of parents. */
372 if((pif=findInterfaceForMethod(pParseInfo->pCurInterface, pMethod->chrName))!=NULL)
373 {
374 gchar* chrMessage;
375 chrMessage=g_strdup_printf("A method '%s' is already present in interface '%s'.",
376 pMethod->chrName, pif->chrName);
377
378 g_scanner_unexp_token(gScanner,
379 G_TOKEN_IDENTIFIER,
380 NULL, NULL, NULL,
381 chrMessage,
382 TRUE); /* is_error */
383 cleanupAndExit(1);
384 }
385
386 /* Check if the method is defined at all */
387 if(NULL==findMethodInfoFromMethodNameWithCurrent(pParseInfo->pClassDefinition, pMethod->chrName))
388 {
389 gchar* chrMessage;
390 chrMessage=g_strdup_printf("Method '%s' is not defined for the current class or one of the parents.",
391 pMethod->chrName);
392
393 g_scanner_unexp_token(gScanner,
394 G_TOKEN_IDENTIFIER,
395 NULL, NULL, NULL,
396 chrMessage,
397 TRUE); /* is_error */
398 cleanupAndExit(1);
399
400 }
401
402 /**** Do parameters if any ****/
403
404 exitIfNotMatchNext('(', "Error in method declaration");
405
406
407 /* No parameters */
408 if(matchNext(')'))
409 {
410
411 }
412 else
413 {
414 /* This parses all the parameters */
415 parseMethodParams(pMethod);
416 exitIfNotMatchNext(')', "Error in method declaration");
417 }
418
419 g_ptr_array_add( pParseInfo->pCurInterface->pMethodArray, (gpointer) pMethod);
420
421 emitMethodImplHeader(pParseInfo->pCurInterface, pMethod);
422
423 pParseInfo->fPrintToken=TRUE;
424 parseCodeBlock();
425 pParseInfo->fPrintToken=FALSE;
426}
427
Note: See TracBrowser for help on using the repository browser.