2 * Copyright (C) 1999 the Free Software Foundation.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
32 extern char *filename;
36 static GList *class_nodes = NULL;
39 static GList *typestack = NULL;
41 static GList *funcargs = NULL;
42 static GList *checks = NULL;
43 static int has_this = FALSE;
45 static GList *gtktypes = NULL;
50 extern int ccode_line;
61 if(strcmp(yytext,"\n")==0) {
62 out=g_strconcat("Error: ",str," before newline",NULL);
63 } else if(yytext[0]=='\0') {
64 out=g_strconcat("Error: ",str," at end of input",NULL);
66 char *tmp = g_strdup(yytext);
67 while((p=strchr(tmp,'\n')))
70 out=g_strconcat("Error: ",str," before '",tmp,"'",NULL);
74 fprintf(stderr,"%s:%d: %s\n",filename,line_no,out);
81 push_variable(char *name, int scope)
84 Type *type = typestack->data;
85 typestack = g_list_remove(typestack,typestack->data);
87 var = new_variable(scope,type,name);
88 class_nodes = g_list_append(class_nodes, var);
92 push_function(int scope, char *oid, char *id, char *onerror,
93 GString *cbuf,int line_no, int ccode_line)
98 if(scope!=INIT_METHOD && scope!=CLASS_INIT_METHOD) {
99 type = typestack->data;
100 typestack = g_list_remove(typestack,typestack->data);
102 type = (Type *)new_type(0,g_strdup("void"));
105 node = new_method(scope,type,oid,gtktypes,id,funcargs,
106 onerror,cbuf,line_no,ccode_line);
110 class_nodes = g_list_append(class_nodes, node);
114 push_funcarg(char *name)
117 Type *type = typestack->data;
118 typestack = g_list_remove(typestack,typestack->data);
120 node = new_funcarg(type,name,checks);
123 funcargs = g_list_append(funcargs, node);
127 push_init_arg(char *name, int is_class)
134 tn = g_strconcat(((Class *)class)->otype,":Class",NULL);
136 tn = g_strdup(((Class *)class)->otype);
138 type = new_type(1,tn);
139 node = new_funcarg((Type *)type,name,NULL);
140 funcargs = g_list_prepend(funcargs, node);
144 push_this(char *this)
149 type = new_type(1,g_strdup(((Class *)class)->otype));
150 ch = g_list_append(ch,new_check(NULL_CHECK,NULL));
151 ch = g_list_append(ch,new_check(TYPE_CHECK,NULL));
152 node = new_funcarg((Type *)type,this,ch);
153 funcargs = g_list_prepend(funcargs, node);
166 %token VOID STRUCT UNION ENUM SIGNED UNSIGNED LONG SHORT INT FLOAT DOUBLE CHAR
170 %token <id> TOKEN NUMBER TYPETOKEN
171 %token <cbuf> CCODE HCODE
172 %token <line> PUBLIC PRIVATE ARGUMENT VIRTUAL SIGNAL OVERRIDE
176 prog: ccodes class ccodes { ; }
182 ccodes: ccodes CCODE {
183 Node *node = new_ccode(FALSE,$<cbuf>2,ccode_line);
184 nodes = g_list_append(nodes,node);
187 Node *node = new_ccode(TRUE,$<cbuf>2,ccode_line);
188 nodes = g_list_append(nodes,node);
191 Node *node = new_ccode(FALSE,$<cbuf>1,ccode_line);
192 nodes = g_list_append(nodes,node);
195 Node *node = new_ccode(TRUE,$<cbuf>1,ccode_line);
196 nodes = g_list_append(nodes,node);
200 class: classdec '{' classcode '}' {
201 ((Class *)class)->nodes = class_nodes;
203 nodes = g_list_append(nodes,class);
207 classdec: CLASS TYPETOKEN FROM TYPETOKEN {
208 class = new_class($<id>2,$<id>4,NULL);
212 classcode: classcode method { ; }
213 | classcode variable { ; }
214 | classcode argument { ; }
220 variable: PUBLIC type TOKEN ';' {
221 push_variable($<id>3,PUBLIC_SCOPE);
223 | PRIVATE type TOKEN ';' {
224 push_variable($<id>3,PRIVATE_SCOPE);
227 argument: ARGUMENT argflags TOKEN TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' {
228 if(strcmp($<id>5,"get")==0 &&
229 strcmp($<id>8,"set")==0) {
231 g_free($<id>5); g_free($<id>8);
232 node = new_argument($<id>3,$<list>2,$<id>4,
235 class_nodes = g_list_append(class_nodes,node);
236 } else if(strcmp($<id>5,"set")==0 &&
237 strcmp($<id>8,"get")==0) {
239 g_free($<id>5); g_free($<id>8);
240 node = new_argument($<id>3,$<list>2,$<id>4,
243 class_nodes = g_list_append(class_nodes,node);
245 g_free($<id>3); g_free($<id>4);
246 g_free($<id>5); g_free($<id>8);
247 g_list_foreach($<list>2,(GFunc)g_free,NULL);
248 g_string_free($<cbuf>10,TRUE);
249 g_string_free($<cbuf>7,TRUE);
250 yyerror(_("parse error"));
254 | ARGUMENT argflags TOKEN TOKEN TOKEN '{' CCODE ';' {
255 if(strcmp($<id>5,"get")==0) {
258 node = new_argument($<id>3,$<list>2,$<id>4,
259 $<cbuf>7,$<line>6,NULL,0);
260 class_nodes = g_list_append(class_nodes,node);
261 } else if(strcmp($<id>5,"set")==0) {
264 node = new_argument($<id>3,$<list>2,$<id>4,
265 NULL,0,$<cbuf>7,$<line>6);
266 class_nodes = g_list_append(class_nodes,node);
268 g_free($<id>5); g_free($<id>3);
270 g_list_foreach($<list>2,(GFunc)g_free,NULL);
271 g_string_free($<cbuf>7,TRUE);
272 yyerror(_("parse error"));
278 argflags: '(' flaglist ')' { $<list>$ = $<list>2; }
279 | { $<list>$ = NULL; }
282 flaglist: TOKEN '|' flaglist {
283 $<list>$ = g_list_append($<list>3,$<id>1);
286 $<list>$ = g_list_append(NULL,$<id>1);
292 Node *node = new_type(0,$<id>1);
293 typestack = g_list_prepend(typestack,node);
296 Node *node = new_type(stars,$<id>1);
298 typestack = g_list_prepend(typestack,node);
302 type1: UNSIGNED integer {
303 $<id>$ = g_strconcat("unsigned ",$<id>2,NULL);
306 $<id>$ = g_strconcat("signed ",$<id>2,NULL);
309 $<id>$ = g_strdup($<id>1);
312 $<id>$ = g_strdup("unsigned char");
315 $<id>$ = g_strdup("signed char");
318 $<id>$ = g_strdup("char");
321 $<id>$ = g_strdup("double");
324 $<id>$ = g_strdup("float");
330 $<id>$ = g_strconcat($<id>1,$<id>2,NULL);
337 $<id>$ = g_strdup("void");
348 $<id>$ = "short int";
369 stars: '*' stars { stars++; }
373 sigtype: TOKEN '(' tokenlist ')' {
374 gtktypes = g_list_prepend(gtktypes,$<id>1);
378 tokenlist: tokenlist ',' TOKEN {
379 gtktypes = g_list_append(gtktypes,$<id>3);
382 gtktypes = g_list_append(gtktypes,$<id>1);
386 /*here CCODE will include the ending '}' */
387 method: SIGNAL TOKEN sigtype type TOKEN '(' funcargs ')' onerror '{' CCODE {
388 int sigtype = SIGNAL_LAST_METHOD;
389 if(strcmp($<id>2,"first")==0)
390 sigtype = SIGNAL_FIRST_METHOD;
391 else if(strcmp($<id>2,"last")==0)
392 sigtype = SIGNAL_LAST_METHOD;
394 yyerror(_("signal must be 'first' or 'last'"));
401 yyerror(_("signal without 'this' as "
405 push_function(sigtype,NULL,
406 $<id>5, $<id>9, $<cbuf>11,$<line>1,$<line>10);
408 | SIGNAL TOKEN sigtype type TOKEN '(' funcargs ')' onerror ';' {
409 int sigtype = SIGNAL_LAST_METHOD;
410 if(strcmp($<id>2,"first")==0)
411 sigtype = SIGNAL_FIRST_METHOD;
412 else if(strcmp($<id>2,"last")==0)
413 sigtype = SIGNAL_LAST_METHOD;
415 yyerror(_("signal must be 'first' or 'last'"));
421 yyerror(_("signal without 'this' as "
425 push_function(sigtype, NULL,
426 $<id>5, $<id>9, NULL,$<line>1,0);
428 | SIGNAL sigtype type TOKEN '(' funcargs ')' onerror '{' CCODE {
430 yyerror(_("signal without 'this' as "
434 push_function(SIGNAL_LAST_METHOD, NULL,
435 $<id>4, $<id>8, $<cbuf>10,$<line>1,$<line>9);
437 | SIGNAL sigtype type TOKEN '(' funcargs ')' onerror ';' {
439 yyerror(_("signal without 'this' as "
443 push_function(SIGNAL_LAST_METHOD, NULL, $<id>4,
444 $<id>8, NULL,$<line>1,0);
446 | VIRTUAL type TOKEN '(' funcargs ')' onerror '{' CCODE {
447 push_function(VIRTUAL_METHOD, NULL, $<id>3,
448 $<id>7, $<cbuf>9,$<line>1,$<line>8);
450 | VIRTUAL type TOKEN '(' funcargs ')' onerror ';' {
451 push_function(VIRTUAL_METHOD, NULL, $<id>3,
452 $<id>7, NULL,$<line>1,0);
454 | OVERRIDE '(' TYPETOKEN ')' type TOKEN '(' funcargs ')' onerror '{' CCODE {
455 push_function(OVERRIDE_METHOD, $<id>3,
456 $<id>6, $<id>10, $<cbuf>12,$<line>1,$<line>11);
458 | PUBLIC type TOKEN '(' funcargs ')' onerror '{' CCODE {
459 push_function(PUBLIC_SCOPE, NULL, $<id>3,
460 $<id>7, $<cbuf>9,$<line>1,$<line>8);
462 | PRIVATE type TOKEN '(' funcargs ')' onerror '{' CCODE {
463 push_function(PRIVATE_SCOPE, NULL, $<id>3,
464 $<id>7, $<cbuf>9,$<line>1,$<line>8);
466 | TOKEN '(' TOKEN ')' ';' {
467 if(strcmp($<id>1,"init")==0) {
468 push_init_arg($<id>3,FALSE);
469 push_function(INIT_METHOD, NULL, $<id>1,
470 NULL, NULL,$<line>2,0);
471 } else if(strcmp($<id>1,"class_init")==0) {
472 push_init_arg($<id>3,TRUE);
473 push_function(CLASS_INIT_METHOD, NULL,
474 $<id>1, NULL, NULL,$<line>2,0);
478 yyerror(_("parse error"));
482 | TOKEN '(' TOKEN ')' '{' CCODE {
483 if(strcmp($<id>1,"init")==0) {
484 push_init_arg($<id>3,FALSE);
485 push_function(INIT_METHOD, NULL,
486 $<id>1, NULL, $<cbuf>6,$<line>2,
488 } else if(strcmp($<id>1,"class_init")==0) {
489 push_init_arg($<id>3,TRUE);
490 push_function(CLASS_INIT_METHOD, NULL,
491 $<id>1, NULL, $<cbuf>6,$<line>2,
496 g_string_free($<cbuf>3,TRUE);
497 yyerror(_("parse error"));
503 onerror: ONERROR numtok { $<id>$ = $<id>2; }
504 | ONERROR '{' CCODE {
505 $<id>$ = ($<cbuf>3)->str;
506 g_string_free($<cbuf>3,FALSE);
514 funcargs: VOID { has_this = FALSE; }
517 if(strcmp($<id>1,"this")==0)
521 yyerror(_("parse error"));
525 | TOKEN ',' arglist {
527 if(strcmp($<id>1,"this")==0)
531 yyerror(_("parse error"));
535 | arglist { has_this = FALSE; }
538 arglist: arglist ',' arg { ; }
543 push_funcarg($<id>2);
545 | type TOKEN '(' TOKEN checklist ')' {
546 if(strcmp($<id>4,"check")!=0) {
547 yyerror(_("parse error"));
551 push_funcarg($<id>2);
555 checklist: checklist check { ; }
560 if(strcmp($<id>1,"type")==0) {
561 Node *node = new_check(TYPE_CHECK,NULL);
562 checks = g_list_append(checks,node);
563 } else if(strcmp($<id>1,"null")==0) {
564 Node *node = new_check(NULL_CHECK,NULL);
565 checks = g_list_append(checks,node);
567 yyerror(_("parse error"));
573 Node *node = new_check(GT_CHECK,$<id>2);
574 checks = g_list_append(checks,node);
577 Node *node = new_check(LT_CHECK,$<id>2);
578 checks = g_list_append(checks,node);
581 Node *node = new_check(GE_CHECK,$<id>3);
582 checks = g_list_append(checks,node);
585 Node *node = new_check(LE_CHECK,$<id>3);
586 checks = g_list_append(checks,node);
589 Node *node = new_check(EQ_CHECK,$<id>3);
590 checks = g_list_append(checks,node);
593 Node *node = new_check(NE_CHECK,$<id>3);
594 checks = g_list_append(checks,node);
598 numtok: NUMBER { $<id>$ = $<id>1; }
600 $<id>$ = g_strconcat("-",$<id>2,NULL);
603 | TOKEN { $<id>$ = $<id>1; }