X-Git-Url: http://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/dd11885aadcfaafae2d6268c381b0aac94cbc149..c9914e54f16c3315d47040f4cca2d3788228c504:/src/parse.y diff --git a/src/parse.y b/src/parse.y index 0161aea..f29f9de 100644 --- a/src/parse.y +++ b/src/parse.y @@ -23,6 +23,7 @@ #include "config.h" #include #include +#include #include #include "treefuncs.h" @@ -35,9 +36,9 @@ GList *nodes = NULL; static GList *class_nodes = NULL; Node *class = NULL; +char *chunk_size = NULL; static GList *typestack = NULL; -static int stars = 0; static GList *funcargs = NULL; static GList *checks = NULL; static int has_self = FALSE; @@ -123,11 +124,13 @@ push_function(int scope, int method, char *oid, char *id, Node *node; Type *type; char *c_cbuf; + + g_assert(scope != CLASS_SCOPE); - if(method!=INIT_METHOD && method!=CLASS_INIT_METHOD) { - type = pop_type(); + if(method == INIT_METHOD || method == CLASS_INIT_METHOD) { + type = (Type *)new_type(g_strdup("void"), NULL, NULL); } else { - type = (Type *)new_type(0,g_strdup("void"),NULL); + type = pop_type(); } /* a complicated and ugly test to figure out if we have @@ -165,7 +168,7 @@ push_function(int scope, int method, char *oid, char *id, node = new_method(scope, method, type, oid, gtktypes, flags, id, funcargs, onerror, defreturn, c_cbuf, line_no, - ccode_line, vararg); + ccode_line, vararg, method_unique_id++); if(cbuf) g_string_free(cbuf, @@ -189,6 +192,9 @@ free_all_global_state(void) g_free(defreturn); defreturn = NULL; + g_free(chunk_size); + chunk_size = NULL; + g_list_foreach(gtktypes, (GFunc)g_free, NULL); g_list_free(gtktypes); gtktypes = NULL; @@ -223,18 +229,19 @@ push_init_arg(char *name, int is_class) else tn = g_strdup(((Class *)class)->otype); - type = new_type(1,tn,NULL); + type = new_type(tn, g_strdup("*"), NULL); node = new_funcarg((Type *)type,name,NULL); funcargs = g_list_prepend(funcargs, node); } static void -push_self(char *id) +push_self(char *id, gboolean constant) { Node *node; Node *type; GList *ch = NULL; - type = new_type(1,g_strdup(((Class *)class)->otype),NULL); + type = new_type(g_strdup(((Class *)class)->otype), + g_strdup(constant ? "const *" : "*"), 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); @@ -299,7 +306,7 @@ set_return_value(char *type, char *val) %token TOKEN NUMBER TYPETOKEN ARRAY_DIM %token CCODE HTCODE PHCODE HCODE ACODE ATCODE -%token PUBLIC PRIVATE PROTECTED ARGUMENT VIRTUAL SIGNAL OVERRIDE +%token PUBLIC PRIVATE PROTECTED CLASSWIDE ARGUMENT VIRTUAL SIGNAL OVERRIDE %% @@ -363,11 +370,31 @@ class: classdec '{' classcode '}' { } ; -classdec: CLASS TYPETOKEN FROM TYPETOKEN { - class = new_class($2,$4,NULL); +classdec: CLASS TYPETOKEN FROM TYPETOKEN chunk { + class = new_class($2,$4,chunk_size,NULL); } ; - + +chunk: + | '(' TOKEN TOKEN ')' { + if(strcmp($2,"chunks") == 0) { + chunk_size = g_strdup($4); + } else { + yyerror(_("parse error")); + YYERROR; + } + } + | '(' TOKEN NUMBER ')' { + if(strcmp($2,"chunks") == 0) { + if(atoi($4) != 0) + chunk_size = g_strdup($4); + } else { + yyerror(_("parse error")); + YYERROR; + } + } + ; + classcode: classcode thing { ; } | thing { ; } ; @@ -381,6 +408,7 @@ thing: method { ; } scope: PUBLIC { the_scope = PUBLIC_SCOPE; } | PRIVATE { the_scope = PRIVATE_SCOPE; } | PROTECTED { the_scope = PROTECTED_SCOPE; } + | CLASSWIDE { the_scope = CLASS_SCOPE; } ; destructor: TOKEN TOKEN { @@ -470,6 +498,7 @@ argument: ARGUMENT flags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { g_free($3); g_free($4); g_free($5); g_free($8); g_list_foreach($2,(GFunc)g_free,NULL); + g_list_free($2); g_string_free($10,TRUE); g_string_free($7,TRUE); yyerror(_("parse error")); @@ -477,29 +506,30 @@ argument: ARGUMENT flags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { } } | ARGUMENT flags argtype TOKEN TOKEN '{' CCODE ';' { - if(strcmp($5,"get")==0) { + if(strcmp($5, "get") == 0) { Node *node; Type *type = pop_type(); g_free($5); - 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 = 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,type,$2,$4, - NULL,0,($7)->str, + 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); + g_string_free($7, FALSE); + class_nodes = g_list_append(class_nodes, node); } else { g_free($5); g_free($3); g_free($4); - g_list_foreach($2,(GFunc)g_free,NULL); - g_string_free($7,TRUE); + g_list_foreach($2, (GFunc)g_free, NULL); + g_list_free($2); + g_string_free($7, TRUE); yyerror(_("parse error")); YYERROR; } @@ -511,12 +541,13 @@ argument: ARGUMENT flags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { Type *type; char *root; - if(strcmp($5,"link")!=0 && - strcmp($5,"stringlink")!=0 && - strcmp($5,"objectlink")!=0) { + 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); + g_list_free($2); yyerror(_("parse error")); YYERROR; } @@ -526,24 +557,30 @@ argument: ARGUMENT flags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { var = find_var_or_die($4, $1); if(var->scope == PRIVATE_SCOPE) root = "self->_priv"; - else + else if(var->scope == CLASS_SCOPE) { + root = "SELF_GET_CLASS(self)"; + if(no_self_alias) + print_error(FALSE, + _("Self aliases needed when autolinking to a classwide member"), + $1); + } else root = "self"; - if(strcmp($5,"link")==0) { + if(strcmp($5, "link")==0) { set = g_strdup_printf("%s->%s = ARG;", root, $4); - } else if(strcmp($5,"stringlink")==0) { + } 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) { + } 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)); ", + "gtk_object_ref(GTK_OBJECT(%s->%s));", root, $4, root, $4, root, $4, @@ -553,8 +590,11 @@ argument: ARGUMENT flags argtype TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { g_assert_not_reached(); } - /* get is the same for everything */ - get = g_strdup_printf("ARG = %s->%s;", root, $4); + if(strcmp($5, "stringlink")==0) { + get = g_strdup_printf("ARG = g_strdup(%s->%s);", root, $4); + } else + /* For everything else, get is just straight assignment */ + get = g_strdup_printf("ARG = %s->%s;", root, $4); g_free($5); @@ -597,95 +637,102 @@ flaglist: TOKEN '|' flaglist { ; -type: type1 { ; } - | CONST type1 { - Type *type = typestack->data; - char *oldname = type->name; - type->name = g_strconcat("const ",oldname,NULL); - g_free(oldname); - } - ; - -type1: type2 { - Node *node = new_type(0,$1,NULL); +type: specifier_list pointer { + Node *node = new_type($1, $2, NULL); typestack = g_list_prepend(typestack,node); - } - | type2 stars { - Node *node = new_type(stars,$1,NULL); - stars = 0; + } + | specifier_list { + Node *node = new_type($1, NULL, NULL); typestack = g_list_prepend(typestack,node); - } + } ; -type2: UNSIGNED integer { - $$ = g_strconcat("unsigned ",$2,NULL); - } - | SIGNED integer { - $$ = g_strconcat("signed ",$2,NULL); - } - | integer { - $$ = g_strdup($1); - } - | UNSIGNED CHAR { - $$ = g_strdup("unsigned char"); - } - | SIGNED CHAR { - $$ = g_strdup("signed char"); - } - | CHAR { - $$ = g_strdup("char"); - } - | DOUBLE { - $$ = g_strdup("double"); - } - | FLOAT { - $$ = g_strdup("float"); - } - | TOKEN { +/* The special cases are neccessary to avoid conflicts */ +specifier_list: spec_list { $$ = $1; - } - | tspecifier TOKEN { - $$ = g_strconcat($1,$2,NULL); - g_free($2); - } - | TYPETOKEN { + } + | TOKEN { $$ = $1; - } - | VOID { - $$ = g_strdup("void"); - } + } + | CONST TOKEN { + $$ = g_strconcat("const ", $2, NULL); + g_free($2); + } + | TOKEN CONST { + $$ = g_strconcat($1, " const", NULL); + g_free($1); + } + | strunionenum TOKEN { + $$ = g_strconcat($1, " ", $2, NULL); + g_free($2); + } + | CONST strunionenum TOKEN { + $$ = g_strconcat("const ", $2, " ", + $3, NULL); + g_free($3); + } + | strunionenum TOKEN CONST { + $$ = g_strconcat($1, " ", + $2, " const", NULL); + g_free($2); + } ; -integer: LONG INT { - $$ = "long int"; - } - | LONG { - $$ = "long"; - } - | SHORT INT { - $$ = "short int"; - } - | SHORT { - $$ = "short"; - } - | INT { - $$ = "int"; - } +/* The special const cases take care of conflicts ! */ +spec_list: specifier spec_list { + $$ = g_strconcat($1, " ", $2, NULL); + g_free($2); + } + | TYPETOKEN spec_list { + $$ = g_strconcat($1, " ", $2, NULL); + g_free($1); + g_free($2); + } + | CONST spec_list { + $$ = g_strconcat("const ", $2, NULL); + g_free($2); + } + | TYPETOKEN { + $$ = $1; + } + | TYPETOKEN CONST { + $$ = g_strconcat($1, " const", NULL); + g_free($1); + } + | specifier { + $$ = g_strdup($1); + } + | specifier CONST { + $$ = g_strconcat($1, " const", NULL); + } ; - -tspecifier: ENUM { - $$ = "enum "; - } - | UNION { - $$ = "union "; - } - | STRUCT { - $$ = "struct "; - } + +specifier: VOID { $$ = "void"; } + | CHAR { $$ = "char"; } + | SHORT { $$ = "short"; } + | INT { $$ = "int"; } + | LONG { $$ = "long"; } + | FLOAT { $$ = "float"; } + | DOUBLE { $$ = "double"; } + | SIGNED { $$ = "signed"; } + | UNSIGNED { $$ = "unsigned"; } + ; + +strunionenum: STRUCT { $$ = "struct"; } + | UNION { $$ = "union"; } + | ENUM { $$ = "enum"; } ; - -stars: '*' stars { stars++; } - | '*' { stars++; } + +pointer: '*' { $$ = g_strdup("*"); } + | '*' CONST { $$ = g_strdup("* const"); } + | '*' pointer { + $$ = g_strconcat("*", $2, NULL); + g_free($2); + } + | '*' CONST pointer { + $$ = g_strconcat("* const", $3, NULL); + g_free($3); + } ; /* this never sets the_scope */ @@ -765,6 +812,11 @@ method: SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenoc free_all_global_state(); YYERROR; } + if(the_scope == CLASS_SCOPE) { + yyerror(_("a method cannot be of class scope")); + free_all_global_state(); + YYERROR; + } push_function(the_scope, $3,NULL, $5, $10,$1, ccode_line, vararg, $2); @@ -776,6 +828,11 @@ method: SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenoc free_all_global_state(); YYERROR; } + if(the_scope == CLASS_SCOPE) { + yyerror(_("a method cannot be of class scope")); + free_all_global_state(); + YYERROR; + } push_function(the_scope, $4, NULL, $6, $11, $2, ccode_line, vararg, $3); @@ -787,6 +844,11 @@ method: SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenoc free_all_global_state(); YYERROR; } + if(the_scope == CLASS_SCOPE) { + yyerror(_("a method cannot be of class scope")); + free_all_global_state(); + YYERROR; + } push_function(the_scope, VIRTUAL_METHOD, NULL, $4, $9, $1, ccode_line, vararg, NULL); @@ -798,6 +860,11 @@ method: SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenoc free_all_global_state(); YYERROR; } + if(the_scope == CLASS_SCOPE) { + yyerror(_("a method cannot be of class scope")); + free_all_global_state(); + YYERROR; + } push_function(the_scope, VIRTUAL_METHOD, NULL, $4, $9, $2, ccode_line, vararg, NULL); @@ -820,6 +887,11 @@ method: SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenoc vararg, NULL); } | scope type TOKEN '(' funcargs ')' returnvals codenocode { + if(the_scope == CLASS_SCOPE) { + yyerror(_("a method cannot be of class scope")); + free_all_global_state(); + YYERROR; + } push_function(the_scope, REGULAR_METHOD, NULL, $3, $8, $1, ccode_line, vararg, NULL); @@ -838,8 +910,10 @@ method: SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenoc } else { g_free($1); g_free($3); - g_string_free($3,TRUE); - yyerror(_("parse error")); + g_string_free($5,TRUE); + yyerror(_("parse error " + "(untyped blocks must be init or " + "class_init)")); YYERROR; } } @@ -893,23 +967,65 @@ funcargs: VOID { vararg = FALSE; has_self = FALSE; } vararg = FALSE; has_self = TRUE; if(strcmp($1,"self")==0) - push_self($1); + push_self($1, FALSE); else { g_free($1); yyerror(_("parse error")); YYERROR; } } + | TOKEN CONST { + vararg = FALSE; + has_self = TRUE; + if(strcmp($1,"self")==0) + push_self($1, TRUE); + else { + g_free($1); + yyerror(_("parse error")); + YYERROR; + } + } + | CONST TOKEN { + vararg = FALSE; + has_self = TRUE; + if(strcmp($2,"self")==0) + push_self($2, TRUE); + else { + g_free($2); + yyerror(_("parse error")); + YYERROR; + } + } | TOKEN ',' arglist { has_self = TRUE; if(strcmp($1,"self")==0) - push_self($1); + push_self($1, FALSE); else { g_free($1); yyerror(_("parse error")); YYERROR; } } + | TOKEN CONST ',' arglist { + has_self = TRUE; + if(strcmp($1,"self")==0) + push_self($1, TRUE); + else { + g_free($1); + yyerror(_("parse error")); + YYERROR; + } + } + | CONST TOKEN ',' arglist { + has_self = TRUE; + if(strcmp($2,"self")==0) + push_self($2, TRUE); + else { + g_free($2); + yyerror(_("parse error")); + YYERROR; + } + } | arglist { has_self = FALSE; } ;