X-Git-Url: http://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/e10d6e307623d0952f6e1f5d9fee8720ddab4808..3b10bbd3a88d6e16146414d91d06bb2f36347bfc:/src/parse.y diff --git a/src/parse.y b/src/parse.y index a6892e9..d0b56fe 100644 --- a/src/parse.y +++ b/src/parse.y @@ -43,6 +43,13 @@ static GList *checks = NULL; static int has_self = FALSE; static int vararg = FALSE; +/* destructor and initializer for variables */ +static char *destructor = NULL; +static int destructor_line = 0; +static gboolean destructor_simple = TRUE; +static char *initializer = NULL; +static int initializer_line = 0; + static GList *gtktypes = NULL; /* this can be a global as we will only do one function at a time @@ -98,13 +105,17 @@ push_variable(char *name, int scope, int line_no, char *postfix) type->postfix = postfix; - var = new_variable(scope,type,name,line_no); + var = new_variable(scope, type, name, line_no, + destructor, destructor_line, + destructor_simple, + initializer, initializer_line); class_nodes = g_list_append(class_nodes, var); } static void push_function(int scope, int method, char *oid, char *id, char *onerror, - GString *cbuf,int line_no, int ccode_line, int vararg) + GString *cbuf, int line_no, int ccode_line, gboolean vararg, + GList *flags) { Node *node; Type *type; @@ -138,8 +149,9 @@ push_function(int scope, int method, char *oid, char *id, char *onerror, } else c_cbuf = NULL; - node = new_method(scope,method,type,oid,gtktypes,id,funcargs, - onerror,c_cbuf,line_no,ccode_line,vararg); + 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, @@ -196,6 +208,29 @@ push_self(char *id) funcargs = g_list_prepend(funcargs, node); } +static Variable * +find_var_or_die(const char *id, int line) +{ + GList *li; + char *s; + + for(li = class_nodes; li != NULL; li = li->next) { + Variable *var; + Node *node = li->data; + if(node->type != VARIABLE_NODE) + continue; + var = li->data; + if(strcmp(var->id, id)==0) + return var; + } + + s = g_strdup_printf(_("Variable %s not defined here"), id); + print_error(FALSE, s, line); + + g_assert_not_reached(); + return NULL; +} + %} %union { @@ -212,7 +247,7 @@ push_self(char *id) %token ONERROR %token TOKEN NUMBER TYPETOKEN ARRAY_DIM -%token CCODE HTCODE PHCODE HCODE +%token CCODE HTCODE PHCODE HCODE ACODE ATCODE %token PUBLIC PRIVATE PROTECTED ARGUMENT VIRTUAL SIGNAL OVERRIDE %% @@ -247,6 +282,18 @@ ccode: CCODE { nodes = g_list_append(nodes,node); g_string_free($1,FALSE); } + | 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 { ; } @@ -270,12 +317,14 @@ classdec: CLASS TYPETOKEN FROM TYPETOKEN { } ; -classcode: classcode method { ; } - | classcode variable { ; } - | classcode argument { ; } - | method { ; } +classcode: classcode thing { ; } + | thing { ; } + ; + +thing: method { ; } | variable { ; } | argument { ; } + | ';' { ; } ; scope: PUBLIC { the_scope = PUBLIC_SCOPE; } @@ -283,14 +332,65 @@ scope: PUBLIC { the_scope = PUBLIC_SCOPE; } | PROTECTED { the_scope = PROTECTED_SCOPE; } ; -variable: scope type TOKEN ';' { - push_variable($3,the_scope,$1,NULL); +destructor: TOKEN TOKEN { + if(strcmp($1, "destroywith")==0) { + g_free($1); + destructor = $2; + destructor_line = ccode_line; + destructor_simple = TRUE; + } else { + g_free($1); + g_free($2); + yyerror(_("parse error")); + YYERROR; + } + } + | TOKEN '{' CCODE { + if(strcmp($1, "destroy")==0) { + g_free($1); + destructor = ($3)->str; + g_string_free($3, FALSE); + destructor_line = ccode_line; + destructor_simple = FALSE; + } else { + g_free($1); + g_string_free($3, TRUE); + yyerror(_("parse error")); + YYERROR; + } + } + ; + +initializer: '=' numtok { + initializer = $2; + initializer_line = ccode_line; + } + | '=' '{' CCODE { + initializer = ($3)->str; + initializer_line = ccode_line; + g_string_free($3, FALSE); + } + ; + + +varoptions: destructor initializer { ; } + | initializer destructor { ; } + | initializer { destructor = NULL; } + | destructor { initializer = NULL; } + | { + destructor = NULL; + initializer = NULL; + } + ; + +variable: scope type TOKEN varoptions ';' { + push_variable($3, the_scope,$1, NULL); } - | scope type TOKEN ARRAY_DIM ';' { - push_variable($3,the_scope,$1,$4); + | scope type TOKEN ARRAY_DIM varoptions ';' { + push_variable($3, the_scope, $1, $4); } ; -argument: ARGUMENT argflags argtype 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; @@ -325,7 +425,7 @@ argument: ARGUMENT argflags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { YYERROR; } } - | ARGUMENT argflags argtype TOKEN TOKEN '{' CCODE ';' { + | ARGUMENT flags argtype TOKEN TOKEN '{' CCODE ';' { if(strcmp($5,"get")==0) { Node *node; Type *type = pop_type(); @@ -353,6 +453,69 @@ argument: ARGUMENT argflags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { YYERROR; } } + | ARGUMENT flags argtype TOKEN TOKEN { + Node *node; + char *get, *set; + Variable *var; + Type *type; + char *root; + + if(strcmp($5,"link")!=0 && + strcmp($5,"stringlink")!=0 && + strcmp($5,"objectlink")!=0) { + g_free($5); g_free($3); + g_free($4); + g_list_foreach($2,(GFunc)g_free,NULL); + yyerror(_("parse error")); + YYERROR; + } + + type = pop_type(); + + var = find_var_or_die($4, $1); + if(var->scope == PRIVATE_SCOPE) + root = "self->_priv"; + else + root = "self"; + + if(strcmp($5,"link")==0) { + set = g_strdup_printf("%s->%s = ARG;", + root, $4); + } else if(strcmp($5,"stringlink")==0) { + set = g_strdup_printf("g_free(%s->%s); " + "%s->%s = g_strdup(ARG);", + root, $4, + root, $4); + } else if(strcmp($5,"objectlink")==0) { + set = g_strdup_printf( + "if(%s->%s) " + "gtk_object_unref(GTK_OBJECT(%s->%s)); " + "%s->%s = ARG; " + "if(%s->%s) " + "gtk_object_ref(GTK_OBJECT(%s->%s)); ", + root, $4, + root, $4, + root, $4, + root, $4, + root, $4); + } else { + g_assert_not_reached(); + } + + /* get is the same for everything */ + get = g_strdup_printf("ARG = %s->%s;", root, $4); + + g_free($5); + + + if(!type) + type = copy_type(var->vtype); + + node = new_argument($3, type, $2, + $4, get, $1, + set, $1, $1); + class_nodes = g_list_append(class_nodes,node); + } ; argtype: TOKEN '(' TOKEN type ')' { @@ -370,7 +533,7 @@ argtype: TOKEN '(' TOKEN type ')' { } ; -argflags: '(' flaglist ')' { $$ = $2; } +flags: '(' flaglist ')' { $$ = $2; } | { $$ = NULL; } ; @@ -544,25 +707,25 @@ codenocode: '{' CCODE { $$ = $2; } ; /*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(the_scope, $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 simplesigtype type TOKEN '(' funcargs ')' onerror codenocode { + | scope SIGNAL flags simplesigtype type TOKEN '(' funcargs ')' onerror codenocode { if(!has_self) { yyerror(_("signal without 'self' as " "first parameter")); YYERROR; } - push_function(the_scope, $3,NULL, - $5, $9, $10,$2, - ccode_line,vararg); + push_function(the_scope, $4, NULL, + $6, $10, $11, $2, + ccode_line, vararg, $3); } | VIRTUAL scope type TOKEN '(' funcargs ')' onerror codenocode { if(!has_self) { @@ -571,8 +734,8 @@ method: SIGNAL fullsigtype type TOKEN '(' funcargs ')' onerror codenocode { YYERROR; } push_function(the_scope, VIRTUAL_METHOD, NULL, $4, - $8, $9,$1, - ccode_line,vararg); + $8, $9, $1, + ccode_line, vararg, NULL); } | scope VIRTUAL type TOKEN '(' funcargs ')' onerror codenocode { if(!has_self) { @@ -581,8 +744,8 @@ method: SIGNAL fullsigtype type TOKEN '(' funcargs ')' onerror codenocode { YYERROR; } push_function(the_scope, VIRTUAL_METHOD, NULL, $4, - $8, $9,$2, - ccode_line,vararg); + $8, $9, $2, + ccode_line, vararg, NULL); } | VIRTUAL type TOKEN '(' funcargs ')' onerror codenocode { if(!has_self) { @@ -591,31 +754,31 @@ method: SIGNAL fullsigtype type TOKEN '(' funcargs ')' onerror codenocode { YYERROR; } push_function(PUBLIC_SCOPE, VIRTUAL_METHOD, NULL, - $3, $7, $8,$1, - ccode_line,vararg); + $3, $7, $8, $1, + ccode_line, vararg, NULL); } | OVERRIDE '(' TYPETOKEN ')' type TOKEN '(' funcargs ')' onerror codenocode { push_function(NO_SCOPE, OVERRIDE_METHOD, $3, $6, $10, $11, - $1,ccode_line, - vararg); + $1, ccode_line, + vararg, NULL); } | scope type TOKEN '(' funcargs ')' onerror codenocode { push_function(the_scope, REGULAR_METHOD, NULL, $3, - $7, $8,$1,ccode_line, - vararg); + $7, $8, $1, ccode_line, + vararg, NULL); } | TOKEN '(' TOKEN ')' codenocode { if(strcmp($1,"init")==0) { push_init_arg($3,FALSE); push_function(NO_SCOPE, INIT_METHOD, NULL, - $1, NULL, $5,$2, - ccode_line,FALSE); + $1, NULL, $5, $2, + ccode_line, FALSE, NULL); } else if(strcmp($1,"class_init")==0) { push_init_arg($3,TRUE); push_function(NO_SCOPE, CLASS_INIT_METHOD, NULL, - $1, NULL, $5,$2, - ccode_line,FALSE); + $1, NULL, $5, $2, + ccode_line, FALSE, NULL); } else { g_free($1); g_free($3);