X-Git-Url: http://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/b17287deb56775a49030d738d8c8c0e9cd15f9fe..3b10bbd3a88d6e16146414d91d06bb2f36347bfc:/src/parse.y diff --git a/src/parse.y b/src/parse.y index 63f0a7a..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,7 +105,10 @@ 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); } @@ -198,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 { @@ -284,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; } @@ -297,11 +332,62 @@ 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 flags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { @@ -367,6 +453,69 @@ argument: ARGUMENT flags 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 ')' {