X-Git-Url: http://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/774037b15064dcc6e4995c0bba3b24abb1bde35f..3b10bbd3a88d6e16146414d91d06bb2f36347bfc:/src/parse.y diff --git a/src/parse.y b/src/parse.y index c2c4253..d0b56fe 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; @@ -44,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 @@ -99,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; @@ -139,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, @@ -197,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 { @@ -213,7 +247,7 @@ push_self(char *id) %token ONERROR %token TOKEN NUMBER TYPETOKEN ARRAY_DIM -%token CCODE HCODE +%token CCODE HTCODE PHCODE HCODE ACODE ATCODE %token PUBLIC PRIVATE PROTECTED ARGUMENT VIRTUAL SIGNAL OVERRIDE %% @@ -224,28 +258,46 @@ prog: ccodes class ccodes { ; } | class { ; } ; -ccodes: ccodes CCODE { - Node *node = new_ccode(FALSE,($2)->str, +ccode: CCODE { + Node *node = new_ccode(C_CCODE,($1)->str, ccode_line); nodes = g_list_append(nodes,node); - g_string_free($2,FALSE); + g_string_free($1,FALSE); } - | ccodes HCODE { - Node *node = new_ccode(TRUE,($2)->str,ccode_line); + | HCODE { + Node *node = new_ccode(H_CCODE,($1)->str, + ccode_line); nodes = g_list_append(nodes,node); - g_string_free($2,FALSE); + g_string_free($1,FALSE); } - | CCODE { - Node *node = new_ccode(FALSE,($1)->str, + | HTCODE { + Node *node = new_ccode(HT_CCODE,($1)->str, ccode_line); nodes = g_list_append(nodes,node); g_string_free($1,FALSE); } - | HCODE { - Node *node = new_ccode(TRUE,($1)->str,ccode_line); + | PHCODE { + Node *node = new_ccode(PH_CCODE,($1)->str, + ccode_line); 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 { ; } + | ccode { ; } ; class: classdec '{' classcode '}' { @@ -265,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; } @@ -278,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; @@ -320,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(); @@ -348,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 ')' { @@ -365,7 +533,7 @@ argtype: TOKEN '(' TOKEN type ')' { } ; -argflags: '(' flaglist ')' { $$ = $2; } +flags: '(' flaglist ')' { $$ = $2; } | { $$ = NULL; } ; @@ -539,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) { @@ -566,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) { @@ -576,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) { @@ -586,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);