X-Git-Url: http://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/6e77e91bbb048a0ee1a072715c0ce808c169ab38..b17287deb56775a49030d738d8c8c0e9cd15f9fe:/src/parse.y diff --git a/src/parse.y b/src/parse.y index 7648232..63f0a7a 100644 --- a/src/parse.y +++ b/src/parse.y @@ -27,11 +27,10 @@ #include "tree.h" #include "main.h" +#include "util.h" #define _(x) (x) -extern char *filename; - GList *nodes = NULL; static GList *class_nodes = NULL; @@ -46,6 +45,10 @@ static int vararg = FALSE; static GList *gtktypes = NULL; +/* this can be a global as we will only do one function at a time + anyway */ +static int the_scope = NO_SCOPE; + void free(void *ptr); int yylex(void); @@ -79,33 +82,72 @@ yyerror(char *str) exit(1); } -static void -push_variable(char *name, int scope, int line_no) +static Type * +pop_type(void) { - Node *var; Type *type = typestack->data; typestack = g_list_remove(typestack,typestack->data); + return type; +} + +static void +push_variable(char *name, int scope, int line_no, char *postfix) +{ + Node *var; + Type *type = pop_type(); + + type->postfix = postfix; var = new_variable(scope,type,name,line_no); class_nodes = g_list_append(class_nodes, var); } static void -push_function(int scope, char *oid, char *id, char *onerror, - GString *cbuf,int line_no, int ccode_line, int vararg) +push_function(int scope, int method, char *oid, char *id, char *onerror, + GString *cbuf, int line_no, int ccode_line, gboolean vararg, + GList *flags) { Node *node; Type *type; + char *c_cbuf; - if(scope!=INIT_METHOD && scope!=CLASS_INIT_METHOD) { - type = typestack->data; - typestack = g_list_remove(typestack,typestack->data); + if(method!=INIT_METHOD && method!=CLASS_INIT_METHOD) { + type = pop_type(); } else { - type = (Type *)new_type(0,g_strdup("void")); + type = (Type *)new_type(0,g_strdup("void"),NULL); } - node = new_method(scope,type,oid,gtktypes,id,funcargs, - onerror,cbuf,line_no,ccode_line,vararg); + /* a complicated and ugly test to figure out if we have + the wrong number of types for a signal */ + if((method == SIGNAL_FIRST_METHOD || + method == SIGNAL_LAST_METHOD) && + g_list_length(gtktypes) != g_list_length(funcargs) && + !(g_list_length(funcargs) == 1 && + g_list_length(gtktypes) == 2 && + strcmp(gtktypes->next->data,"NONE")==0)) { + print_error(TRUE, _("The number of GTK arguments and " + "function arguments for a signal " + "don't seem to match"),line_no); + } + if(cbuf) { + char *p; + c_cbuf = p = cbuf->str; + while(p && *p && (*p==' ' || *p=='\t' || *p=='\n' || *p=='\r')) + p++; + if(!p || !*p) + c_cbuf = NULL; + } else + c_cbuf = NULL; + + node = new_method(scope, method, type, oid, gtktypes, flags, + id, funcargs, onerror, c_cbuf, line_no, + ccode_line, vararg); + + if(cbuf) + g_string_free(cbuf, + /*only free segment if we haven't passed it + above */ + c_cbuf?FALSE:TRUE); gtktypes = NULL; funcargs = NULL; @@ -113,11 +155,12 @@ push_function(int scope, char *oid, char *id, char *onerror, } static void -push_funcarg(char *name) +push_funcarg(char *name, char *postfix) { Node *node; - Type *type = typestack->data; - typestack = g_list_remove(typestack,typestack->data); + Type *type = pop_type(); + + type->postfix = postfix; node = new_funcarg(type,name,checks); checks = NULL; @@ -137,7 +180,7 @@ push_init_arg(char *name, int is_class) else tn = g_strdup(((Class *)class)->otype); - type = new_type(1,tn); + type = new_type(1,tn,NULL); node = new_funcarg((Type *)type,name,NULL); funcargs = g_list_prepend(funcargs, node); } @@ -148,7 +191,7 @@ push_self(char *id) Node *node; Node *type; GList *ch = NULL; - type = new_type(1,g_strdup(((Class *)class)->otype)); + type = new_type(1,g_strdup(((Class *)class)->otype),NULL); ch = g_list_append(ch,new_check(NULL_CHECK,NULL)); ch = g_list_append(ch,new_check(TYPE_CHECK,NULL)); node = new_funcarg((Type *)type,id,ch); @@ -170,9 +213,9 @@ push_self(char *id) %token SIGNED UNSIGNED LONG SHORT INT FLOAT DOUBLE CHAR %token ONERROR -%token TOKEN NUMBER TYPETOKEN -%token CCODE HCODE -%token PUBLIC PRIVATE ARGUMENT VIRTUAL SIGNAL OVERRIDE +%token TOKEN NUMBER TYPETOKEN ARRAY_DIM +%token CCODE HTCODE PHCODE HCODE ACODE ATCODE +%token PUBLIC PRIVATE PROTECTED ARGUMENT VIRTUAL SIGNAL OVERRIDE %% @@ -182,29 +225,58 @@ prog: ccodes class ccodes { ; } | class { ; } ; -ccodes: ccodes CCODE { - Node *node = new_ccode(FALSE,$2,ccode_line); +ccode: CCODE { + Node *node = new_ccode(C_CCODE,($1)->str, + ccode_line); + nodes = g_list_append(nodes,node); + g_string_free($1,FALSE); + } + | HCODE { + Node *node = new_ccode(H_CCODE,($1)->str, + ccode_line); nodes = g_list_append(nodes,node); + g_string_free($1,FALSE); } - | ccodes HCODE { - Node *node = new_ccode(TRUE,$2,ccode_line); + | HTCODE { + Node *node = new_ccode(HT_CCODE,($1)->str, + ccode_line); nodes = g_list_append(nodes,node); + g_string_free($1,FALSE); } - | CCODE { - Node *node = new_ccode(FALSE,$1,ccode_line); + | PHCODE { + Node *node = new_ccode(PH_CCODE,($1)->str, + ccode_line); nodes = g_list_append(nodes,node); + g_string_free($1,FALSE); } - | HCODE { - Node *node = new_ccode(TRUE,$1,ccode_line); + | ACODE { + Node *node = new_ccode(A_CCODE,($1)->str, + ccode_line); nodes = g_list_append(nodes,node); + g_string_free($1,FALSE); + } + | ATCODE { + Node *node = new_ccode(AT_CCODE,($1)->str, + ccode_line); + nodes = g_list_append(nodes,node); + g_string_free($1,FALSE); } ; +ccodes: ccodes ccode { ; } + | ccode { ; } + ; + class: classdec '{' classcode '}' { ((Class *)class)->nodes = class_nodes; class_nodes = NULL; nodes = g_list_append(nodes,class); } + | classdec '{' '}' { + ((Class *)class)->nodes = NULL; + class_nodes = NULL; + nodes = g_list_append(nodes,class); + } ; classdec: CLASS TYPETOKEN FROM TYPETOKEN { @@ -220,31 +292,42 @@ classcode: classcode method { ; } | argument { ; } ; -variable: PUBLIC type TOKEN ';' { - push_variable($3,PUBLIC_SCOPE,$1); +scope: PUBLIC { the_scope = PUBLIC_SCOPE; } + | PRIVATE { the_scope = PRIVATE_SCOPE; } + | PROTECTED { the_scope = PROTECTED_SCOPE; } + ; + +variable: scope type TOKEN ';' { + push_variable($3,the_scope,$1,NULL); } - | PRIVATE type TOKEN ';' { - push_variable($3,PRIVATE_SCOPE,$1); + | scope type TOKEN ARRAY_DIM ';' { + push_variable($3,the_scope,$1,$4); } ; -argument: ARGUMENT argflags TOKEN TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { +argument: ARGUMENT flags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { if(strcmp($5,"get")==0 && strcmp($8,"set")==0) { Node *node; + Type *type = pop_type(); g_free($5); g_free($8); - node = new_argument($3,$2,$4, - $7,$6, - $10,$9, + node = new_argument($3,type,$2,$4, + ($7)->str,$6, + ($10)->str,$9, $1); + g_string_free($7,FALSE); + g_string_free($10,FALSE); class_nodes = g_list_append(class_nodes,node); } else if(strcmp($5,"set")==0 && strcmp($8,"get")==0) { Node *node; + Type *type = pop_type(); g_free($5); g_free($8); - node = new_argument($3,$2,$4, - $10,$9, - $7,$6, + node = new_argument($3,type,$2,$4, + ($10)->str,$9, + ($7)->str,$6, $1); + g_string_free($10,FALSE); + g_string_free($7,FALSE); class_nodes = g_list_append(class_nodes,node); } else { g_free($3); g_free($4); @@ -256,20 +339,24 @@ argument: ARGUMENT argflags TOKEN TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { YYERROR; } } - | ARGUMENT argflags TOKEN TOKEN TOKEN '{' CCODE ';' { + | ARGUMENT flags argtype TOKEN TOKEN '{' CCODE ';' { if(strcmp($5,"get")==0) { Node *node; + Type *type = pop_type(); g_free($5); - node = new_argument($3,$2,$4, - $7,$6,NULL,0, - $1); + node = new_argument($3,type,$2,$4, + ($7)->str,$6, + NULL,0, $1); + g_string_free($7,FALSE); class_nodes = g_list_append(class_nodes,node); } else if(strcmp($5,"set")==0) { Node *node; + Type *type = pop_type(); g_free($5); - node = new_argument($3,$2,$4, - NULL,0,$7,$6, - $1); + node = new_argument($3,type,$2,$4, + NULL,0,($7)->str, + $6, $1); + g_string_free($7,FALSE); class_nodes = g_list_append(class_nodes,node); } else { g_free($5); g_free($3); @@ -281,8 +368,23 @@ argument: ARGUMENT argflags TOKEN TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { } } ; + +argtype: TOKEN '(' TOKEN type ')' { + if(strcmp($3,"type")!=0) { + g_free($1); + g_free($3); + yyerror(_("parse error")); + YYERROR; + } + $$ = $1; + } + | TOKEN { + $$ = $1; + typestack = g_list_prepend(typestack,NULL); + } + ; -argflags: '(' flaglist ')' { $$ = $2; } +flags: '(' flaglist ')' { $$ = $2; } | { $$ = NULL; } ; @@ -305,11 +407,11 @@ type: type1 { ; } ; type1: type2 { - Node *node = new_type(0,$1); + Node *node = new_type(0,$1,NULL); typestack = g_list_prepend(typestack,node); } | type2 stars { - Node *node = new_type(stars,$1); + Node *node = new_type(stars,$1,NULL); stars = 0; typestack = g_list_prepend(typestack,node); } @@ -386,23 +488,12 @@ stars: '*' stars { stars++; } | '*' { stars++; } ; -fullsigtype: PRIVATE TOKEN sigtype { - if(strcmp($2,"first")==0) - $$ = PRIVATE_SIGNAL_FIRST_METHOD; - else if(strcmp($2,"last")==0) - $$ = PRIVATE_SIGNAL_LAST_METHOD; - else { - yyerror(_("signal must be 'first' or 'last'")); - g_free($2); - YYERROR; - } - g_free($2); - } - | TOKEN PRIVATE sigtype { +/* this never sets the_scope */ +simplesigtype: TOKEN sigtype { if(strcmp($1,"first")==0) - $$ = PRIVATE_SIGNAL_FIRST_METHOD; + $$ = SIGNAL_FIRST_METHOD; else if(strcmp($1,"last")==0) - $$ = PRIVATE_SIGNAL_LAST_METHOD; + $$ = SIGNAL_LAST_METHOD; else { yyerror(_("signal must be 'first' or 'last'")); g_free($1); @@ -410,10 +501,25 @@ fullsigtype: PRIVATE TOKEN sigtype { } g_free($1); } - | PRIVATE sigtype { - $$ = PRIVATE_SIGNAL_LAST_METHOD; + | sigtype { + $$ = SIGNAL_LAST_METHOD; + } + ; + +/* this always sets the_scope */ +fullsigtype: scope TOKEN sigtype { + if(strcmp($2,"first")==0) + $$ = SIGNAL_FIRST_METHOD; + else if(strcmp($2,"last")==0) + $$ = SIGNAL_LAST_METHOD; + else { + yyerror(_("signal must be 'first' or 'last'")); + g_free($2); + YYERROR; + } + g_free($2); } - | TOKEN sigtype { + | TOKEN scope sigtype { if(strcmp($1,"first")==0) $$ = SIGNAL_FIRST_METHOD; else if(strcmp($1,"last")==0) @@ -425,9 +531,13 @@ fullsigtype: PRIVATE TOKEN sigtype { } g_free($1); } - | sigtype { + | scope sigtype { $$ = SIGNAL_LAST_METHOD; } + | simplesigtype { + /* the_scope was default thus public */ + the_scope = PUBLIC_SCOPE; + } ; sigtype: TOKEN '(' tokenlist ')' { @@ -443,30 +553,50 @@ tokenlist: tokenlist ',' TOKEN { } ; -codenocode: '{' CCODE { $$=$2; } +codenocode: '{' CCODE { $$ = $2; } | ';' { $$ = NULL; } ; /*here CCODE will include the ending '}' */ -method: SIGNAL fullsigtype type TOKEN '(' funcargs ')' onerror codenocode { +method: SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' onerror codenocode { if(!has_self) { yyerror(_("signal without 'self' as " "first parameter")); YYERROR; } - push_function($2,NULL, - $4, $8, $9,$1, - ccode_line,vararg); + push_function(the_scope, $3,NULL, + $5, $9, $10,$1, + ccode_line, vararg, $2); + } + | scope SIGNAL flags simplesigtype type TOKEN '(' funcargs ')' onerror codenocode { + if(!has_self) { + yyerror(_("signal without 'self' as " + "first parameter")); + YYERROR; + } + push_function(the_scope, $4, NULL, + $6, $10, $11, $2, + ccode_line, vararg, $3); + } + | VIRTUAL scope type TOKEN '(' funcargs ')' onerror codenocode { + if(!has_self) { + yyerror(_("virtual method without 'self' as " + "first parameter")); + YYERROR; + } + push_function(the_scope, VIRTUAL_METHOD, NULL, $4, + $8, $9, $1, + ccode_line, vararg, NULL); } - | VIRTUAL PRIVATE type TOKEN '(' funcargs ')' onerror codenocode { + | scope VIRTUAL type TOKEN '(' funcargs ')' onerror codenocode { if(!has_self) { yyerror(_("virtual method without 'self' as " "first parameter")); YYERROR; } - push_function(PRIVATE_VIRTUAL_METHOD, NULL, $4, - $8, $9,$1, - ccode_line,vararg); + push_function(the_scope, VIRTUAL_METHOD, NULL, $4, + $8, $9, $2, + ccode_line, vararg, NULL); } | VIRTUAL type TOKEN '(' funcargs ')' onerror codenocode { if(!has_self) { @@ -474,37 +604,32 @@ method: SIGNAL fullsigtype type TOKEN '(' funcargs ')' onerror codenocode { "first parameter")); YYERROR; } - push_function(VIRTUAL_METHOD, NULL, $3, - $7, $8,$1, - ccode_line,vararg); + push_function(PUBLIC_SCOPE, VIRTUAL_METHOD, NULL, + $3, $7, $8, $1, + ccode_line, vararg, NULL); } - | OVERRIDE '(' TYPETOKEN ')' type TOKEN '(' funcargs ')' onerror '{' CCODE { - push_function(OVERRIDE_METHOD, $3, - $6, $10, $12, - $1,$11, - vararg); + | OVERRIDE '(' TYPETOKEN ')' type TOKEN '(' funcargs ')' onerror codenocode { + push_function(NO_SCOPE, OVERRIDE_METHOD, $3, + $6, $10, $11, + $1, ccode_line, + vararg, NULL); } - | PUBLIC type TOKEN '(' funcargs ')' onerror '{' CCODE { - push_function(PUBLIC_SCOPE, NULL, $3, - $7, $9,$1,$8, - vararg); - } - | PRIVATE type TOKEN '(' funcargs ')' onerror '{' CCODE { - push_function(PRIVATE_SCOPE, NULL, $3, - $7, $9,$1,$8, - vararg); + | scope type TOKEN '(' funcargs ')' onerror codenocode { + push_function(the_scope, REGULAR_METHOD, NULL, $3, + $7, $8, $1, ccode_line, + vararg, NULL); } | TOKEN '(' TOKEN ')' codenocode { if(strcmp($1,"init")==0) { push_init_arg($3,FALSE); - push_function(INIT_METHOD, NULL, - $1, NULL, $5,$2, - ccode_line,FALSE); + push_function(NO_SCOPE, INIT_METHOD, NULL, + $1, NULL, $5, $2, + ccode_line, FALSE, NULL); } else if(strcmp($1,"class_init")==0) { push_init_arg($3,TRUE); - push_function(CLASS_INIT_METHOD, NULL, - $1, NULL, $5,$2, - ccode_line,FALSE); + push_function(NO_SCOPE, CLASS_INIT_METHOD, NULL, + $1, NULL, $5, $2, + ccode_line, FALSE, NULL); } else { g_free($1); g_free($3); @@ -520,7 +645,6 @@ onerror: ONERROR numtok { $$ = $2; } $$ = ($3)->str; g_string_free($3,FALSE); } - | '=' '1' { ; } | { $$ = NULL; } ; @@ -528,12 +652,7 @@ funcargs: VOID { vararg = FALSE; has_self = FALSE; } | TOKEN { vararg = FALSE; has_self = TRUE; - if(strcmp($1,"this")==0) { - push_self($1); - print_error(TRUE,_("Use of 'this' is " - "depreciated, use 'self' " - "instead"),line_no); - } else if(strcmp($1,"self")==0) + if(strcmp($1,"self")==0) push_self($1); else { g_free($1); @@ -543,12 +662,7 @@ funcargs: VOID { vararg = FALSE; has_self = FALSE; } } | TOKEN ',' arglist { has_self = TRUE; - if(strcmp($1,"this")==0) { - push_self($1); - print_error(TRUE,_("Use of 'this' is " - "depreciated, use 'self' " - "instead"),line_no); - } else if(strcmp($1,"self")==0) + if(strcmp($1,"self")==0) push_self($1); else { g_free($1); @@ -568,7 +682,10 @@ arglist1: arglist1 ',' arg { ; } ; arg: type TOKEN { - push_funcarg($2); + push_funcarg($2,NULL); + } + | type TOKEN ARRAY_DIM { + push_funcarg($2,$3); } | type TOKEN '(' TOKEN checklist ')' { if(strcmp($4,"check")!=0) { @@ -576,7 +693,15 @@ arg: type TOKEN { YYERROR; } g_free($4); - push_funcarg($2); + push_funcarg($2,NULL); + } + | type TOKEN ARRAY_DIM '(' TOKEN checklist ')' { + if(strcmp($5,"check")!=0) { + yyerror(_("parse error")); + YYERROR; + } + g_free($5); + push_funcarg($2,$3); } ;