X-Git-Url: https://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/4c9cb9b99991c36920bd17e366e2128d1b22eb6e..6d0fe9d5f8c513045bf064ea256c822beac19037:/src/parse.y diff --git a/src/parse.y b/src/parse.y index b718cdc..4cdb6a0 100644 --- a/src/parse.y +++ b/src/parse.y @@ -26,6 +26,7 @@ #include #include "tree.h" +#include "main.h" #define _(x) (x) @@ -40,7 +41,8 @@ static GList *typestack = NULL; static int stars = 0; static GList *funcargs = NULL; static GList *checks = NULL; -static int has_this = FALSE; +static int has_self = FALSE; +static int vararg = FALSE; static GList *gtktypes = NULL; @@ -78,19 +80,21 @@ yyerror(char *str) } static void -push_variable(char *name, int scope) +push_variable(char *name, int scope, int line_no, char *postfix) { Node *var; Type *type = typestack->data; typestack = g_list_remove(typestack,typestack->data); + + type->postfix = postfix; - var = new_variable(scope,type,name); + var = new_variable(scope,type,name,line_no); class_nodes = g_list_append(class_nodes, var); } static void push_function(int scope, char *oid, char *id, char *onerror, - GString *cbuf,int line_no, int ccode_line) + GString *cbuf,int line_no, int ccode_line, int vararg) { Node *node; Type *type; @@ -99,11 +103,25 @@ push_function(int scope, char *oid, char *id, char *onerror, type = typestack->data; typestack = g_list_remove(typestack,typestack->data); } else { - type = (Type *)new_type(0,g_strdup("void")); + type = (Type *)new_type(0,g_strdup("void"),NULL); } + /* a complicated and ugly test to figure out if we have + the wrong number of types for a signal */ + if((scope == SIGNAL_FIRST_METHOD || + scope == SIGNAL_LAST_METHOD || + scope == PRIVATE_SIGNAL_FIRST_METHOD || + scope == PRIVATE_SIGNAL_LAST_METHOD) && + g_list_length(gtktypes) != g_list_length(funcargs) && + !(g_list_length(funcargs) == 1 && + g_list_length(gtktypes) == 2 && + strcmp(gtktypes->next->data,"NONE")==0)) { + print_error(TRUE, _("The number of GTK arguments and " + "function arguments for a signal " + "don't seem to match"),line_no); + } node = new_method(scope,type,oid,gtktypes,id,funcargs, - onerror,cbuf,line_no,ccode_line); + onerror,cbuf,line_no,ccode_line,vararg); gtktypes = NULL; funcargs = NULL; @@ -111,11 +129,13 @@ push_function(int scope, char *oid, char *id, char *onerror, } static void -push_funcarg(char *name) +push_funcarg(char *name, char *postfix) { Node *node; Type *type = typestack->data; typestack = g_list_remove(typestack,typestack->data); + + type->postfix = postfix; node = new_funcarg(type,name,checks); checks = NULL; @@ -135,21 +155,21 @@ push_init_arg(char *name, int is_class) else tn = g_strdup(((Class *)class)->otype); - type = new_type(1,tn); + type = new_type(1,tn,NULL); node = new_funcarg((Type *)type,name,NULL); funcargs = g_list_prepend(funcargs, node); } static void -push_this(char *this) +push_self(char *id) { Node *node; Node *type; GList *ch = NULL; - type = new_type(1,g_strdup(((Class *)class)->otype)); + type = new_type(1,g_strdup(((Class *)class)->otype),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,this,ch); + node = new_funcarg((Type *)type,id,ch); funcargs = g_list_prepend(funcargs, node); } @@ -160,14 +180,15 @@ push_this(char *this) GString *cbuf; GList *list; int line; + int sigtype; } %token CLASS FROM -%token VOID STRUCT UNION ENUM SIGNED UNSIGNED LONG SHORT INT FLOAT DOUBLE CHAR -%token FIRST LAST +%token CONST VOID STRUCT UNION ENUM THREEDOTS +%token SIGNED UNSIGNED LONG SHORT INT FLOAT DOUBLE CHAR %token ONERROR -%token TOKEN NUMBER TYPETOKEN +%token TOKEN NUMBER TYPETOKEN ARRAY_DIM %token CCODE HCODE %token PUBLIC PRIVATE ARGUMENT VIRTUAL SIGNAL OVERRIDE @@ -202,6 +223,11 @@ class: classdec '{' classcode '}' { class_nodes = NULL; nodes = g_list_append(nodes,class); } + | classdec '{' '}' { + ((Class *)class)->nodes = NULL; + class_nodes = NULL; + nodes = g_list_append(nodes,class); + } ; classdec: CLASS TYPETOKEN FROM TYPETOKEN { @@ -218,11 +244,17 @@ classcode: classcode method { ; } ; variable: PUBLIC type TOKEN ';' { - push_variable($3,PUBLIC_SCOPE); + push_variable($3,PUBLIC_SCOPE,$1,NULL); } - | PRIVATE type TOKEN ';' { - push_variable($3,PRIVATE_SCOPE); + | PUBLIC type TOKEN ARRAY_DIM ';' { + push_variable($3,PUBLIC_SCOPE,$1,$4); } + | PRIVATE type TOKEN ';' { + push_variable($3,PRIVATE_SCOPE,$1,NULL); + } + | PRIVATE type TOKEN ARRAY_DIM ';' { + push_variable($3,PRIVATE_SCOPE,$1,$4); + } ; argument: ARGUMENT argflags TOKEN TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { if(strcmp($5,"get")==0 && @@ -231,7 +263,8 @@ argument: ARGUMENT argflags TOKEN TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { g_free($5); g_free($8); node = new_argument($3,$2,$4, $7,$6, - $10,$9); + $10,$9, + $1); class_nodes = g_list_append(class_nodes,node); } else if(strcmp($5,"set")==0 && strcmp($8,"get")==0) { @@ -239,7 +272,8 @@ argument: ARGUMENT argflags TOKEN TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { g_free($5); g_free($8); node = new_argument($3,$2,$4, $10,$9, - $7,$6); + $7,$6, + $1); class_nodes = g_list_append(class_nodes,node); } else { g_free($3); g_free($4); @@ -256,13 +290,15 @@ argument: ARGUMENT argflags TOKEN TOKEN TOKEN '{' CCODE TOKEN '{' CCODE ';' { Node *node; g_free($5); node = new_argument($3,$2,$4, - $7,$6,NULL,0); + $7,$6,NULL,0, + $1); class_nodes = g_list_append(class_nodes,node); } else if(strcmp($5,"set")==0) { Node *node; g_free($5); node = new_argument($3,$2,$4, - NULL,0,$7,$6); + NULL,0,$7,$6, + $1); class_nodes = g_list_append(class_nodes,node); } else { g_free($5); g_free($3); @@ -288,18 +324,27 @@ flaglist: TOKEN '|' flaglist { ; -type: type1 { - Node *node = new_type(0,$1); +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); typestack = g_list_prepend(typestack,node); } - | type1 stars { - Node *node = new_type(stars,$1); + | type2 stars { + Node *node = new_type(stars,$1,NULL); stars = 0; typestack = g_list_prepend(typestack,node); } ; -type1: UNSIGNED integer { +type2: UNSIGNED integer { $$ = g_strconcat("unsigned ",$2,NULL); } | SIGNED integer { @@ -369,127 +414,157 @@ tspecifier: ENUM { stars: '*' stars { stars++; } | '*' { stars++; } ; - -sigtype: TOKEN '(' tokenlist ')' { - gtktypes = g_list_prepend(gtktypes,$1); - } - ; -tokenlist: tokenlist ',' TOKEN { - gtktypes = g_list_append(gtktypes,$3); - } - | TOKEN { - gtktypes = g_list_append(gtktypes,$1); - } +optpublic: { ; } + | PUBLIC { ; } ; -/*here CCODE will include the ending '}' */ -method: SIGNAL TOKEN sigtype type TOKEN '(' funcargs ')' onerror '{' CCODE { - int sigtype = SIGNAL_LAST_METHOD; +fullsigtype: PRIVATE TOKEN sigtype { if(strcmp($2,"first")==0) - sigtype = SIGNAL_FIRST_METHOD; + $$ = PRIVATE_SIGNAL_FIRST_METHOD; else if(strcmp($2,"last")==0) - sigtype = SIGNAL_LAST_METHOD; + $$ = PRIVATE_SIGNAL_LAST_METHOD; else { yyerror(_("signal must be 'first' or 'last'")); g_free($2); YYERROR; } g_free($2); - - if(!has_this) { - yyerror(_("signal without 'this' as " - "first parameter")); + } + | TOKEN PRIVATE sigtype { + if(strcmp($1,"first")==0) + $$ = PRIVATE_SIGNAL_FIRST_METHOD; + else if(strcmp($1,"last")==0) + $$ = PRIVATE_SIGNAL_LAST_METHOD; + else { + yyerror(_("signal must be 'first' or 'last'")); + g_free($1); YYERROR; } - push_function(sigtype,NULL, - $5, $9, $11,$1,$10); - } - | SIGNAL TOKEN sigtype type TOKEN '(' funcargs ')' onerror ';' { - int sigtype = SIGNAL_LAST_METHOD; + g_free($1); + } + | PRIVATE sigtype { + $$ = PRIVATE_SIGNAL_LAST_METHOD; + } + | TOKEN sigtype { + if(strcmp($1,"first")==0) + $$ = SIGNAL_FIRST_METHOD; + else if(strcmp($1,"last")==0) + $$ = SIGNAL_LAST_METHOD; + else { + yyerror(_("signal must be 'first' or 'last'")); + g_free($1); + YYERROR; + } + g_free($1); + } + | PUBLIC TOKEN sigtype { if(strcmp($2,"first")==0) - sigtype = SIGNAL_FIRST_METHOD; + $$ = SIGNAL_FIRST_METHOD; else if(strcmp($2,"last")==0) - sigtype = SIGNAL_LAST_METHOD; + $$ = SIGNAL_LAST_METHOD; else { yyerror(_("signal must be 'first' or 'last'")); g_free($2); YYERROR; } g_free($2); - if(!has_this) { - yyerror(_("signal without 'this' as " + } + | TOKEN PUBLIC sigtype { + if(strcmp($1,"first")==0) + $$ = SIGNAL_FIRST_METHOD; + else if(strcmp($1,"last")==0) + $$ = SIGNAL_LAST_METHOD; + else { + yyerror(_("signal must be 'first' or 'last'")); + g_free($1); + YYERROR; + } + g_free($1); + } + | PUBLIC sigtype { + $$ = SIGNAL_LAST_METHOD; + } + | sigtype { + $$ = SIGNAL_LAST_METHOD; + } + ; + +sigtype: TOKEN '(' tokenlist ')' { + gtktypes = g_list_prepend(gtktypes,$1); + } + ; + +tokenlist: tokenlist ',' TOKEN { + gtktypes = g_list_append(gtktypes,$3); + } + | TOKEN { + gtktypes = g_list_append(gtktypes,$1); + } + ; + +codenocode: '{' CCODE { $$=$2; } + | ';' { $$ = NULL; } + ; + +/*here CCODE will include the ending '}' */ +method: SIGNAL fullsigtype type TOKEN '(' funcargs ')' onerror codenocode { + if(!has_self) { + yyerror(_("signal without 'self' as " "first parameter")); YYERROR; } - push_function(sigtype, NULL, - $5, $9, NULL,$1,0); + push_function($2,NULL, + $4, $8, $9,$1, + ccode_line,vararg); } - | SIGNAL sigtype type TOKEN '(' funcargs ')' onerror '{' CCODE { - if(!has_this) { - yyerror(_("signal without 'this' as " + | VIRTUAL PRIVATE type TOKEN '(' funcargs ')' onerror codenocode { + if(!has_self) { + yyerror(_("virtual method without 'self' as " "first parameter")); YYERROR; } - push_function(SIGNAL_LAST_METHOD, NULL, - $4, $8, $10,$1,$9); + push_function(PRIVATE_VIRTUAL_METHOD, NULL, $4, + $8, $9,$1, + ccode_line,vararg); } - | SIGNAL sigtype type TOKEN '(' funcargs ')' onerror ';' { - if(!has_this) { - yyerror(_("signal without 'this' as " + | VIRTUAL optpublic type TOKEN '(' funcargs ')' onerror codenocode { + if(!has_self) { + yyerror(_("virtual method without 'self' as " "first parameter")); YYERROR; } - push_function(SIGNAL_LAST_METHOD, NULL, $4, - $8, NULL,$1,0); - } - | VIRTUAL type TOKEN '(' funcargs ')' onerror '{' CCODE { - push_function(VIRTUAL_METHOD, NULL, $3, - $7, $9,$1,$8); - } - | VIRTUAL type TOKEN '(' funcargs ')' onerror ';' { - push_function(VIRTUAL_METHOD, NULL, $3, - $7, NULL,$1,0); + push_function(VIRTUAL_METHOD, NULL, $4, + $8, $9,$1, + ccode_line,vararg); } | OVERRIDE '(' TYPETOKEN ')' type TOKEN '(' funcargs ')' onerror '{' CCODE { push_function(OVERRIDE_METHOD, $3, - $6, $10, $12,$1,$11); + $6, $10, $12, + $1,$11, + vararg); } | PUBLIC type TOKEN '(' funcargs ')' onerror '{' CCODE { push_function(PUBLIC_SCOPE, NULL, $3, - $7, $9,$1,$8); + $7, $9,$1,$8, + vararg); } | PRIVATE type TOKEN '(' funcargs ')' onerror '{' CCODE { push_function(PRIVATE_SCOPE, NULL, $3, - $7, $9,$1,$8); + $7, $9,$1,$8, + vararg); } - | TOKEN '(' TOKEN ')' ';' { - if(strcmp($1,"init")==0) { - push_init_arg($3,FALSE); - push_function(INIT_METHOD, NULL, $1, - NULL, NULL,$2,0); - } else if(strcmp($1,"class_init")==0) { - push_init_arg($3,TRUE); - push_function(CLASS_INIT_METHOD, NULL, - $1, NULL, NULL,$2,0); - } else { - g_free($1); - g_free($3); - yyerror(_("parse error")); - YYERROR; - } - } - | TOKEN '(' TOKEN ')' '{' CCODE { + | TOKEN '(' TOKEN ')' codenocode { if(strcmp($1,"init")==0) { push_init_arg($3,FALSE); push_function(INIT_METHOD, NULL, - $1, NULL, $6,$2, - $5); + $1, NULL, $5,$2, + ccode_line,FALSE); } else if(strcmp($1,"class_init")==0) { push_init_arg($3,TRUE); push_function(CLASS_INIT_METHOD, NULL, - $1, NULL, $6,$2, - $5); + $1, NULL, $5,$2, + ccode_line,FALSE); } else { g_free($1); g_free($3); @@ -500,8 +575,7 @@ method: SIGNAL TOKEN sigtype type TOKEN '(' funcargs ')' onerror '{' CCODE { } ; -onerror: ONERROR TOKEN { $$ = $2; } - | ONERROR number { $$ = $2; } +onerror: ONERROR numtok { $$ = $2; } | ONERROR '{' CCODE { $$ = ($3)->str; g_string_free($3,FALSE); @@ -510,13 +584,12 @@ onerror: ONERROR TOKEN { $$ = $2; } | { $$ = NULL; } ; - - -funcargs: VOID { has_this = FALSE; } +funcargs: VOID { vararg = FALSE; has_self = FALSE; } | TOKEN { - has_this = TRUE; - if(strcmp($1,"this")==0) - push_this($1); + vararg = FALSE; + has_self = TRUE; + if(strcmp($1,"self")==0) + push_self($1); else { g_free($1); yyerror(_("parse error")); @@ -524,24 +597,31 @@ funcargs: VOID { has_this = FALSE; } } } | TOKEN ',' arglist { - has_this = TRUE; - if(strcmp($1,"this")==0) - push_this($1); + has_self = TRUE; + if(strcmp($1,"self")==0) + push_self($1); else { g_free($1); yyerror(_("parse error")); YYERROR; } } - | arglist { has_this = FALSE; } + | arglist { has_self = FALSE; } + ; + +arglist: arglist1 ',' THREEDOTS { vararg = TRUE; } + | arglist1 { vararg = FALSE; } ; -arglist: arglist ',' arg { ; } +arglist1: arglist1 ',' arg { ; } | arg { ; } ; arg: type TOKEN { - push_funcarg($2); + push_funcarg($2,NULL); + } + | type TOKEN ARRAY_DIM { + push_funcarg($2,$3); } | type TOKEN '(' TOKEN checklist ')' { if(strcmp($4,"check")!=0) { @@ -549,7 +629,15 @@ arg: type TOKEN { YYERROR; } g_free($4); - push_funcarg($2); + push_funcarg($2,NULL); + } + | type TOKEN ARRAY_DIM '(' TOKEN checklist ')' { + if(strcmp($5,"check")!=0) { + yyerror(_("parse error")); + YYERROR; + } + g_free($5); + push_funcarg($2,$3); } ; @@ -570,37 +658,38 @@ check: TOKEN { } g_free($1); } - | '>' number { + | '>' numtok { Node *node = new_check(GT_CHECK,$2); checks = g_list_append(checks,node); } - | '<' number { + | '<' numtok { Node *node = new_check(LT_CHECK,$2); checks = g_list_append(checks,node); } - | '>' '=' number { + | '>' '=' numtok { Node *node = new_check(GE_CHECK,$3); checks = g_list_append(checks,node); } - | '<' '=' number { + | '<' '=' numtok { Node *node = new_check(LE_CHECK,$3); checks = g_list_append(checks,node); } - | '=' '=' number { + | '=' '=' numtok { Node *node = new_check(EQ_CHECK,$3); checks = g_list_append(checks,node); } - | '!' '=' number { + | '!' '=' numtok { Node *node = new_check(NE_CHECK,$3); checks = g_list_append(checks,node); } ; -number: NUMBER { $$ = $1; } +numtok: NUMBER { $$ = $1; } | '-' NUMBER { $$ = g_strconcat("-",$2,NULL); g_free($2); } + | TOKEN { $$ = $1; } ; %%