]> git.draconx.ca Git - gob-dx.git/blobdiff - src/parse.y
Release 0.93.0
[gob-dx.git] / src / parse.y
index 63f0a7a1d21e743c9051b6c571785fe2ed23c3a0..d0b56fe85679f1783dec67f2858fddcf61af6841 100644 (file)
@@ -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($<id>3,the_scope,$<line>1,NULL);
+destructor:    TOKEN TOKEN     {
+                       if(strcmp($<id>1, "destroywith")==0) {
+                               g_free($<id>1);
+                               destructor = $<id>2;
+                               destructor_line = ccode_line;
+                               destructor_simple = TRUE;
+                       } else {
+                               g_free($<id>1);
+                               g_free($<id>2);
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+                               }
+       |       TOKEN '{' CCODE         {
+                       if(strcmp($<id>1, "destroy")==0) {
+                               g_free($<id>1);
+                               destructor = ($<cbuf>3)->str;
+                               g_string_free($<cbuf>3, FALSE);
+                               destructor_line = ccode_line;
+                               destructor_simple = FALSE;
+                       } else {
+                               g_free($<id>1);
+                               g_string_free($<cbuf>3, TRUE);
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+                                       }
+       ;
+
+initializer:   '=' numtok      {
+                       initializer = $<id>2;
+                       initializer_line = ccode_line;
+                               }
+       |       '=' '{' CCODE   {
+                       initializer = ($<cbuf>3)->str;
+                       initializer_line = ccode_line;
+                       g_string_free($<cbuf>3, FALSE);
+                               }
+       ;
+
+
+varoptions:    destructor initializer  { ; }
+       |       initializer destructor  { ; }
+       |       initializer             { destructor = NULL; }
+       |       destructor              { initializer = NULL; }
+       |                               {
+                       destructor = NULL;
+                       initializer = NULL;
+                                       }
+       ;
+
+variable:      scope type TOKEN varoptions ';'         {
+                       push_variable($<id>3, the_scope,$<line>1, NULL);
                                                }
-       |       scope type TOKEN ARRAY_DIM ';'  {
-                       push_variable($<id>3,the_scope,$<line>1,$<id>4);
+       |       scope type TOKEN ARRAY_DIM varoptions ';'       {
+                       push_variable($<id>3, the_scope, $<line>1, $<id>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($<id>5,"link")!=0 &&
+                          strcmp($<id>5,"stringlink")!=0 &&
+                          strcmp($<id>5,"objectlink")!=0) {
+                               g_free($<id>5); g_free($<id>3);
+                               g_free($<id>4);
+                               g_list_foreach($<list>2,(GFunc)g_free,NULL);
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+
+                       type = pop_type();
+
+                       var = find_var_or_die($<id>4, $<line>1);
+                       if(var->scope == PRIVATE_SCOPE)
+                               root = "self->_priv";
+                       else
+                               root = "self";
+
+                       if(strcmp($<id>5,"link")==0) {
+                               set = g_strdup_printf("%s->%s = ARG;",
+                                                     root, $<id>4);
+                       } else if(strcmp($<id>5,"stringlink")==0) {
+                               set = g_strdup_printf("g_free(%s->%s); "
+                                                     "%s->%s = g_strdup(ARG);",
+                                                     root, $<id>4,
+                                                     root, $<id>4);
+                       } else if(strcmp($<id>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, $<id>4,
+                                 root, $<id>4,
+                                 root, $<id>4,
+                                 root, $<id>4,
+                                 root, $<id>4);
+                       } else {
+                               g_assert_not_reached();
+                       }
+
+                       /* get is the same for everything */
+                       get = g_strdup_printf("ARG = %s->%s;", root, $<id>4);
+
+                       g_free($<id>5);
+
+
+                       if(!type)
+                               type = copy_type(var->vtype);
+
+                       node = new_argument($<id>3, type, $<list>2,
+                                           $<id>4, get, $<line>1,
+                                           set, $<line>1, $<line>1);
+                       class_nodes = g_list_append(class_nodes,node);
+                                               }
        ;
 
 argtype:       TOKEN '(' TOKEN type ')'        {