X-Git-Url: https://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/5b42e9400440d86723a27747b2191ab8cd59c2ee..3379dcdfd0872947d761053c61d773add94d38c2:/src/parse.y diff --git a/src/parse.y b/src/parse.y index e204c62..192e4c4 100644 --- a/src/parse.y +++ b/src/parse.y @@ -25,7 +25,7 @@ #include #include -#include "tree.h" +#include "treefuncs.h" #include "main.h" #include "util.h" @@ -50,6 +50,9 @@ static gboolean destructor_simple = TRUE; static char *initializer = NULL; static int initializer_line = 0; +static char *onerror = NULL; +static char *defreturn = NULL; + static GList *gtktypes = NULL; /* this can be a global as we will only do one function at a time @@ -113,9 +116,9 @@ push_variable(char *name, int scope, int line_no, char *postfix) } static void -push_function(int scope, int method, char *oid, char *id, char *onerror, - GString *cbuf, int line_no, int ccode_line, gboolean vararg, - GList *flags) +push_function(int scope, int method, char *oid, char *id, + GString *cbuf, int line_no, int ccode_line, + gboolean vararg, GList *flags) { Node *node; Type *type; @@ -150,7 +153,7 @@ push_function(int scope, int method, char *oid, char *id, char *onerror, c_cbuf = NULL; node = new_method(scope, method, type, oid, gtktypes, flags, - id, funcargs, onerror, c_cbuf, line_no, + id, funcargs, onerror, defreturn, c_cbuf, line_no, ccode_line, vararg); if(cbuf) @@ -161,9 +164,28 @@ push_function(int scope, int method, char *oid, char *id, char *onerror, gtktypes = NULL; funcargs = NULL; + onerror = NULL; + defreturn = NULL; + class_nodes = g_list_append(class_nodes, node); } +static void +free_all_global_state(void) +{ + g_free(onerror); + onerror = NULL; + g_free(defreturn); + defreturn = NULL; + + g_list_foreach(gtktypes, (GFunc)g_free, NULL); + g_list_free(gtktypes); + gtktypes = NULL; + + free_node_list(funcargs); + funcargs = NULL; +} + static void push_funcarg(char *name, char *postfix) { @@ -172,7 +194,7 @@ push_funcarg(char *name, char *postfix) type->postfix = postfix; - node = new_funcarg(type,name,checks); + node = new_funcarg(type, name, checks); checks = NULL; funcargs = g_list_append(funcargs, node); @@ -231,6 +253,25 @@ find_var_or_die(const char *id, int line) return NULL; } +static gboolean +set_return_value(char *type, char *val) +{ + if(strcmp(type, "onerror")==0) { + if(!onerror) { + onerror = val; + return TRUE; + } else + return FALSE; + } else if(strcmp(type, "defreturn")==0) { + if(!defreturn) { + defreturn = val; + return TRUE; + } else + return FALSE; + } + return FALSE; +} + %} %union { @@ -244,7 +285,6 @@ find_var_or_die(const char *id, int line) %token CLASS FROM %token CONST VOID STRUCT UNION ENUM THREEDOTS %token SIGNED UNSIGNED LONG SHORT INT FLOAT DOUBLE CHAR -%token ONERROR %token TOKEN NUMBER TYPETOKEN ARRAY_DIM %token CCODE HTCODE PHCODE HCODE ACODE ATCODE @@ -639,9 +679,9 @@ stars: '*' stars { stars++; } /* this never sets the_scope */ simplesigtype: TOKEN sigtype { - if(strcmp($1,"first")==0) + if(strcmp($1, "first")==0) $$ = SIGNAL_FIRST_METHOD; - else if(strcmp($1,"last")==0) + else if(strcmp($1, "last")==0) $$ = SIGNAL_LAST_METHOD; else { yyerror(_("signal must be 'first' or 'last'")); @@ -690,15 +730,15 @@ fullsigtype: scope TOKEN sigtype { ; sigtype: TOKEN '(' tokenlist ')' { - gtktypes = g_list_prepend(gtktypes,$1); + gtktypes = g_list_prepend(gtktypes, $1); } ; tokenlist: tokenlist ',' TOKEN { - gtktypes = g_list_append(gtktypes,$3); + gtktypes = g_list_append(gtktypes, $3); } | TOKEN { - gtktypes = g_list_append(gtktypes,$1); + gtktypes = g_list_append(gtktypes, $1); } ; @@ -707,77 +747,82 @@ codenocode: '{' CCODE { $$ = $2; } ; /*here CCODE will include the ending '}' */ -method: SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' onerror codenocode { +method: SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenocode { if(!has_self) { yyerror(_("signal without 'self' as " "first parameter")); + free_all_global_state(); YYERROR; } push_function(the_scope, $3,NULL, - $5, $9, $10,$1, + $5, $10,$1, ccode_line, vararg, $2); } - | scope SIGNAL flags simplesigtype type TOKEN '(' funcargs ')' onerror codenocode { + | scope SIGNAL flags simplesigtype type TOKEN '(' funcargs ')' returnvals codenocode { if(!has_self) { yyerror(_("signal without 'self' as " "first parameter")); + free_all_global_state(); YYERROR; } push_function(the_scope, $4, NULL, - $6, $10, $11, $2, + $6, $11, $2, ccode_line, vararg, $3); } - | VIRTUAL scope type TOKEN '(' funcargs ')' onerror codenocode { + | VIRTUAL scope type TOKEN '(' funcargs ')' returnvals codenocode { if(!has_self) { yyerror(_("virtual method without 'self' as " "first parameter")); + free_all_global_state(); YYERROR; } push_function(the_scope, VIRTUAL_METHOD, NULL, $4, - $8, $9, $1, + $9, $1, ccode_line, vararg, NULL); } - | scope VIRTUAL type TOKEN '(' funcargs ')' onerror codenocode { + | scope VIRTUAL type TOKEN '(' funcargs ')' returnvals codenocode { if(!has_self) { yyerror(_("virtual method without 'self' as " "first parameter")); + free_all_global_state(); YYERROR; } push_function(the_scope, VIRTUAL_METHOD, NULL, $4, - $8, $9, $2, + $9, $2, ccode_line, vararg, NULL); } - | VIRTUAL type TOKEN '(' funcargs ')' onerror codenocode { + | VIRTUAL type TOKEN '(' funcargs ')' returnvals codenocode { if(!has_self) { yyerror(_("virtual method without 'self' as " "first parameter")); + free_all_global_state(); YYERROR; } push_function(PUBLIC_SCOPE, VIRTUAL_METHOD, NULL, - $3, $7, $8, $1, + $3, $8, $1, ccode_line, vararg, NULL); } - | OVERRIDE '(' TYPETOKEN ')' type TOKEN '(' funcargs ')' onerror codenocode { + | OVERRIDE '(' TYPETOKEN ')' type TOKEN '(' funcargs ')' returnvals codenocode { push_function(NO_SCOPE, OVERRIDE_METHOD, $3, - $6, $10, $11, + $6, $11, $1, ccode_line, vararg, NULL); } - | scope type TOKEN '(' funcargs ')' onerror codenocode { + | scope type TOKEN '(' funcargs ')' returnvals codenocode { push_function(the_scope, REGULAR_METHOD, NULL, $3, - $7, $8, $1, ccode_line, + $8, $1, ccode_line, vararg, NULL); } | TOKEN '(' TOKEN ')' codenocode { - if(strcmp($1,"init")==0) { + if(strcmp($1, "init")==0) { push_init_arg($3,FALSE); push_function(NO_SCOPE, INIT_METHOD, NULL, - $1, NULL, $5, $2, + $1, $5, $2, ccode_line, FALSE, NULL); - } else if(strcmp($1,"class_init")==0) { + } else if(strcmp($1, "class_init")==0) { push_init_arg($3,TRUE); push_function(NO_SCOPE, CLASS_INIT_METHOD, NULL, - $1, NULL, $5, $2, + $1, $5, $2, ccode_line, FALSE, NULL); } else { g_free($1); @@ -788,13 +833,48 @@ method: SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' onerror codenocode } } ; - -onerror: ONERROR numtok { $$ = $2; } - | ONERROR '{' CCODE { + +returnvals: TOKEN retcode { + g_free(onerror); onerror = NULL; + g_free(defreturn); defreturn = NULL; + if(!set_return_value($1, $2)) { + g_free($1); + g_free($2); + yyerror(_("parse error")); + YYERROR; + } + g_free($1); + } + | TOKEN retcode TOKEN retcode { + g_free(onerror); onerror = NULL; + g_free(defreturn); defreturn = NULL; + if(!set_return_value($1, $2)) { + g_free($1); g_free($2); + g_free($3); g_free($4); + yyerror(_("parse error")); + YYERROR; + } + if(!set_return_value($3, $4)) { + onerror = defreturn = NULL; + g_free($1); g_free($2); + g_free($3); g_free($4); + yyerror(_("parse error")); + YYERROR; + } + g_free($1); + g_free($3); + } + | { + g_free(onerror); onerror = NULL; + g_free(defreturn); defreturn = NULL; + } + ; + +retcode: numtok { $$ = $1; } + | '{' CCODE { $$ = ($3)->str; - g_string_free($3,FALSE); + g_string_free($3, FALSE); } - | { $$ = NULL; } ; funcargs: VOID { vararg = FALSE; has_self = FALSE; }