]> git.draconx.ca Git - gob-dx.git/blobdiff - src/parse.y
Release 2.0.17
[gob-dx.git] / src / parse.y
index a6471cec26a3716f7374fd2d22b39119e8682fab..9c880cf8af435a3b59681a009aa34f1c9764c58d 100644 (file)
@@ -1,7 +1,7 @@
 /* GOB C Preprocessor
  * Copyright (C) 1999-2000 the Free Software Foundation.
  * Copyright (C) 2000 Eazel, Inc.
- * Copyright (C) 2001-2004 George (Jiri) Lebl
+ * Copyright (C) 2001-2009 George (Jiri) Lebl
  *
  * Author: George Lebl
  *
@@ -44,8 +44,10 @@ static GList *enum_vals = NULL;
 static GList *flag_vals = NULL;
 static GList *error_vals = NULL;
 
+static gboolean abstract = FALSE;
 static char *chunk_size = NULL;
 static char *bonobo_object_class = NULL;
+static int glade_xml = FALSE;
 static GList *interfaces = NULL;
 static GList *typestack = NULL;
 static GList *funcargs = NULL;
@@ -61,7 +63,9 @@ static int destructor_line = 0;
 static gboolean destructor_simple = TRUE;
 static char *initializer = NULL;
 static int initializer_line = 0;
+static int glade_widget = FALSE;
 
+static char *funcattrs = NULL;
 static char *onerror = NULL;
 static char *defreturn = NULL;
 
@@ -88,9 +92,10 @@ yyerror(char *str)
        char *out=NULL;
        char *p;
        
-       if(strcmp(yytext,"\n")==0) {
-               out=g_strconcat("Error: ",str," before newline",NULL);
-       } else if(yytext[0]=='\0') {
+       if (strcmp (yytext, "\n") == 0 ||
+           strcmp (yytext, "\r") == 0) {
+               out = g_strconcat ("Error: ", str, " before end of line", NULL);
+       } else if (yytext[0] == '\0') {
                out=g_strconcat("Error: ", str, " at end of input", NULL);
        } else {
                char *tmp = g_strdup(yytext);
@@ -126,6 +131,7 @@ push_variable (char *name, int scope, int line_no, char *postfix)
        var = node_new (VARIABLE_NODE,
                        "scope", scope,
                        "vtype:steal", type,
+                       "glade_widget", glade_widget,
                        "id:steal", name,
                        "line_no", line_no,
                        "destructor_unref", destructor_unref,
@@ -134,8 +140,10 @@ push_variable (char *name, int scope, int line_no, char *postfix)
                        "destructor_simple", destructor_simple,
                        "initializer:steal", initializer,
                        "initializer_line", initializer_line,
+                       "initializer_simple", TRUE,
                        NULL);
        class_nodes = g_list_append(class_nodes, var);
+       glade_widget = FALSE;
 }
 
 static void
@@ -149,7 +157,11 @@ push_function (int scope, int method, char *oid, char *id,
 
        g_assert(scope != CLASS_SCOPE);
        
-       if(method == INIT_METHOD || method == CLASS_INIT_METHOD) {
+       if(method == INIT_METHOD ||
+          method == CLASS_INIT_METHOD ||
+          method == CONSTRUCTOR_METHOD ||
+          method == DISPOSE_METHOD ||
+          method == FINALIZE_METHOD) {
                type = (Type *)node_new (TYPE_NODE,
                                         "name", "void",
                                         NULL);
@@ -199,6 +211,7 @@ push_function (int scope, int method, char *oid, char *id,
                         "flags:steal", flags,
                         "id:steal", id,
                         "args:steal", funcargs,
+                        "funcattrs:steal", funcattrs,
                         "onerror:steal", onerror,
                         "defreturn:steal", defreturn,
                         "cbuf:steal", c_cbuf,
@@ -218,6 +231,7 @@ push_function (int scope, int method, char *oid, char *id,
        gtktypes = NULL;
        funcargs = NULL;
 
+       funcattrs = NULL;
        onerror = NULL;
        defreturn = NULL;
 
@@ -227,6 +241,8 @@ push_function (int scope, int method, char *oid, char *id,
 static void
 free_all_global_state(void)
 {
+       g_free(funcattrs);
+       funcattrs = NULL;
        g_free(onerror);
        onerror = NULL;
        g_free(defreturn);
@@ -330,9 +346,15 @@ find_var_or_die(const char *id, int line)
 }
 
 static gboolean
-set_return_value(char *type, char *val)
+set_attr_value(char *type, char *val)
 {
-       if(strcmp(type, "onerror")==0) {
+       if(strcmp(type, "attr")==0) {
+               if(!funcattrs) {
+                       funcattrs = val;
+                       return TRUE;
+               } else
+                       return FALSE;
+       } else if(strcmp(type, "onerror")==0) {
                if(!onerror) {
                        onerror = val;
                        return TRUE;
@@ -462,6 +484,39 @@ get_prop_enum_flag_cast (Property *prop)
        return ret;
 }
 
+static void
+add_construct_glade (char * file, char * root, char * domain)
+{
+       Node *var;
+       Type * type;
+       
+       type = (Type *)node_new (TYPE_NODE,
+                                "name", "GladeXML",
+                                "pointer", "*",
+                                NULL);
+       initializer = g_strdup_printf("\t{\n"
+                                     "\tGtkWidget * root;\n"
+                                     "\t%%1$s->_priv->_glade_xml = glade_xml_new(%s, %s, %s);\n"
+                                     "\troot = glade_xml_get_widget(%%1$s->_priv->_glade_xml, %s);\n"
+                                     "\tgtk_widget_show(root);\n"
+                                     "\tgtk_container_add(GTK_CONTAINER(%%1$s), root);\n"
+                                     "\tglade_xml_signal_autoconnect_full(%%1$s->_priv->_glade_xml, (GladeXMLConnectFunc)___glade_xml_connect_foreach, (gpointer)%%1$s);\n"
+                                     "}\n", file, root, domain ? domain : "NULL", root);
+       
+       var = node_new (VARIABLE_NODE,
+                       "scope", PRIVATE_SCOPE,
+                       "vtype:steal", type,
+                       "glade_widget", FALSE,
+                       "id:steal", "_glade_xml",
+                       "destructor_unref", FALSE,
+                       "destructor", "g_object_unref", 
+                       "destructor_simple", TRUE,
+                       "initializer", initializer,
+                       "initializer_simple", FALSE,
+                       NULL);
+       class_nodes = g_list_prepend(class_nodes, var);
+}
+
 static void
 property_link_and_export (Node *node)
 {
@@ -638,7 +693,7 @@ ensure_property (void)
 %token SIGNED UNSIGNED LONG SHORT INT FLOAT DOUBLE CHAR
 
 %token <id> TOKEN NUMBER TYPETOKEN ARRAY_DIM SINGLE_CHAR
-%token <cbuf> CCODE HTCODE PHCODE HCODE ACODE ATCODE STRING
+%token <cbuf> CCODE ADCODE HTCODE PHCODE HCODE ACODE ATCODE STRING
 %token <line> PUBLIC PRIVATE PROTECTED CLASSWIDE PROPERTY ARGUMENT
 %token <line> VIRTUAL SIGNAL OVERRIDE
 %token <line> NICK BLURB MAXIMUM MINIMUM DEFAULT_VALUE ERROR FLAGS TYPE
@@ -661,6 +716,15 @@ ccode:             CCODE                   {
                        nodes = g_list_append(nodes,node);
                        g_string_free($<cbuf>1,FALSE);
                                        }
+       |       ADCODE                  {
+                       Node *node = node_new (CCODE_NODE,
+                                              "cctype", AD_CCODE,
+                                              "cbuf:steal", ($<cbuf>1)->str,
+                                              "line_no", ccode_line,
+                                              NULL);
+                       nodes = g_list_append(nodes,node);
+                       g_string_free($<cbuf>1,FALSE);
+                                       }
        |       HCODE                   {
                        Node *node = node_new (CCODE_NODE,
                                               "cctype", H_CCODE,
@@ -735,16 +799,27 @@ classdec: CLASS TYPETOKEN FROM TYPETOKEN  classflags {
                                          "otype:steal", $<id>2,
                                          "ptype:steal", $<id>4,
                                          "bonobo_object_class:steal", bonobo_object_class,
+                                         "glade_xml", glade_xml,
                                          "interfaces:steal", interfaces,
                                          "chunk_size:steal", chunk_size,
+                                         "abstract", abstract,
                                          NULL);
                        bonobo_object_class = NULL;
+                       glade_xml = FALSE;
                        chunk_size = NULL;
                        interfaces = NULL;
                                                }
        ;
 
 classflags:
+       | '(' TOKEN ')' classflags {
+                       if(strcmp($<id>2,"abstract") == 0) {
+                               abstract = TRUE;
+                       } else {
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+               }
        | '(' TOKEN TOKEN ')' classflags {
                        if(strcmp($<id>2,"chunks") == 0) {
                                g_free (chunk_size);
@@ -778,6 +853,42 @@ classflags:
                                YYERROR;
                        }
                }
+       | '(' TOKEN STRING STRING ')' classflags {
+                       if (strcmp ($<id>2, "GladeXML") == 0) {
+                               glade_xml = TRUE;
+                               add_construct_glade($<id>3, $<id>4, NULL);
+                       } else {
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+               }
+       | '(' TOKEN STRING STRING STRING ')' classflags {
+                       if (strcmp ($<id>2, "GladeXML") == 0) {
+                               glade_xml = TRUE;
+                               add_construct_glade($<id>3, $<id>4, $<id>5);
+                       } else {
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+               }
+       | '(' TOKEN TOKEN STRING ')' classflags {
+                       if (strcmp ($<id>2, "GladeXML") == 0) {
+                               glade_xml = TRUE;
+                               add_construct_glade($<id>3, $<id>4, NULL);
+                       } else {
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+               }
+       | '(' TOKEN TOKEN STRING STRING ')' classflags {
+                       if (strcmp ($<id>2, "GladeXML") == 0) {
+                               glade_xml = TRUE;
+                               add_construct_glade($<id>3, $<id>4, $<id>5);
+                       } else {
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+               }
        ;       
 
 classcode:     classcode thing                 { ; }
@@ -878,6 +989,14 @@ varoptions:        destructor initializer  { ; }
        |       initializer destructor  { ; }
        |       initializer             { destructor = NULL; }
        |       destructor              { initializer = NULL; }
+       |       TOKEN                   {
+                       if (strcmp ($<id>1, "GladeXML") == 0) {
+                               glade_widget = TRUE;
+                       } else {
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+                                       }
        |                               {
                        destructor = NULL;
                        initializer = NULL;
@@ -1570,7 +1689,7 @@ codenocode:       '{' CCODE                       { $<cbuf>$ = $<cbuf>2; }
        ;
 
 /*here CCODE will include the ending '}' */
-method:                SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenocode {
+method:                SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' methodmods codenocode {
                        if(!has_self) {
                                yyerror(_("signal without 'self' as "
                                          "first parameter"));
@@ -1582,11 +1701,18 @@ method:         SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenoc
                                free_all_global_state();
                                YYERROR;
                        }
+                       if (funcattrs != NULL) {
+                               char *error = g_strdup_printf
+                                       (_("function attribute macros ('%s' in this case) may not be used with signal methods"),
+                                        funcattrs);
+                               yyerror (error);
+                               YYERROR;
+                       }
                        push_function(the_scope, $<sigtype>3,NULL,
                                      $<id>5, $<cbuf>10,$<line>1,
                                      ccode_line, vararg, $<list>2);
                                                                        }
-       |       scope SIGNAL flags simplesigtype type TOKEN '(' funcargs ')' returnvals codenocode {
+       |       scope SIGNAL flags simplesigtype type TOKEN '(' funcargs ')' methodmods codenocode {
                        if(!has_self) {
                                yyerror(_("signal without 'self' as "
                                          "first parameter"));
@@ -1598,11 +1724,18 @@ method:         SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenoc
                                free_all_global_state();
                                YYERROR;
                        }
+                       if (funcattrs != NULL) {
+                               char *error = g_strdup_printf
+                                       (_("function attribute macros ('%s' in this case) may not be used with signal methods"),
+                                        funcattrs);
+                               yyerror (error);
+                               YYERROR;
+                       }
                        push_function(the_scope, $<sigtype>4, NULL,
                                      $<id>6, $<cbuf>11, $<line>2,
                                      ccode_line, vararg, $<list>3);
                                                                        }
-       |       VIRTUAL scope type TOKEN '(' funcargs ')' returnvals codenocode {
+       |       VIRTUAL scope type TOKEN '(' funcargs ')' methodmods codenocode {
                        if(!has_self) {
                                yyerror(_("virtual method without 'self' as "
                                          "first parameter"));
@@ -1614,11 +1747,18 @@ method:         SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenoc
                                free_all_global_state();
                                YYERROR;
                        }
+                       if (funcattrs != NULL) {
+                               char *error = g_strdup_printf
+                                       (_("function attribute macros ('%s' in this case) may not be used with virtual methods"),
+                                        funcattrs);
+                               yyerror (error);
+                               YYERROR;
+                       }
                        push_function(the_scope, VIRTUAL_METHOD, NULL, $<id>4,
                                      $<cbuf>9, $<line>1,
                                      ccode_line, vararg, NULL);
                                                                        }
-       |       scope VIRTUAL type TOKEN '(' funcargs ')' returnvals codenocode {
+       |       scope VIRTUAL type TOKEN '(' funcargs ')' methodmods codenocode {
                        if(!has_self) {
                                yyerror(_("virtual method without 'self' as "
                                          "first parameter"));
@@ -1630,28 +1770,49 @@ method:         SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenoc
                                free_all_global_state();
                                YYERROR;
                        }
+                       if (funcattrs != NULL) {
+                               char *error = g_strdup_printf
+                                       (_("function attribute macros ('%s' in this case) may not be used with virtual methods"),
+                                        funcattrs);
+                               yyerror (error);
+                               YYERROR;
+                       }
                        push_function(the_scope, VIRTUAL_METHOD, NULL, $<id>4,
                                      $<cbuf>9, $<line>2,
                                      ccode_line, vararg, NULL);
                                                                        }
-       |       VIRTUAL type TOKEN '(' funcargs ')' returnvals codenocode       {
+       |       VIRTUAL type TOKEN '(' funcargs ')' methodmods codenocode       {
                        if(!has_self) {
-                               yyerror(_("virtual method without 'self' as "
+                               yyerror(_("virtual method without 'szelf' as "
                                          "first parameter"));
                                free_all_global_state();
                                YYERROR;
                        }
+                       if (funcattrs != NULL) {
+                               char *error = g_strdup_printf
+                                       (_("function attribute macros ('%s' in this case) may not be used with virtual methods"),
+                                        funcattrs);
+                               yyerror (error);
+                               YYERROR;
+                       }
                        push_function(PUBLIC_SCOPE, VIRTUAL_METHOD, NULL,
                                      $<id>3, $<cbuf>8, $<line>1,
                                      ccode_line, vararg, NULL);
                                                                        }
-       |       OVERRIDE '(' TYPETOKEN ')' type TOKEN '(' funcargs ')' returnvals codenocode    {
+       |       OVERRIDE '(' TYPETOKEN ')' type TOKEN '(' funcargs ')' methodmods codenocode    {
+                       if (funcattrs != NULL) {
+                               char *error = g_strdup_printf
+                                       (_("function attribute macros ('%s' in this case) may not be used with override methods"),
+                                        funcattrs);
+                               yyerror (error);
+                               YYERROR;
+                       }
                        push_function(NO_SCOPE, OVERRIDE_METHOD, $<id>3,
                                      $<id>6, $<cbuf>11,
                                      $<line>1, ccode_line,
                                      vararg, NULL);
                                                                        }
-       |       scope type TOKEN '(' funcargs ')' returnvals codenocode {
+       |       scope type TOKEN '(' funcargs ')' methodmods codenocode {
                        if(the_scope == CLASS_SCOPE) {
                                yyerror(_("a method cannot be of class scope"));
                                free_all_global_state();
@@ -1672,22 +1833,40 @@ method:         SIGNAL flags fullsigtype type TOKEN '(' funcargs ')' returnvals codenoc
                                push_function(NO_SCOPE, CLASS_INIT_METHOD, NULL,
                                              $<id>1, $<cbuf>5, $<line>2,
                                              ccode_line, FALSE, NULL);
+                       } else if(strcmp($<id>1, "constructor")==0) {
+                               push_init_arg($<id>3, FALSE);
+                               push_function(NO_SCOPE, CONSTRUCTOR_METHOD, NULL,
+                                             $<id>1, $<cbuf>5, $<line>2,
+                                             ccode_line, FALSE, NULL);
+                       } else if(strcmp($<id>1, "dispose")==0) {
+                               push_init_arg($<id>3, FALSE);
+                               push_function(NO_SCOPE, DISPOSE_METHOD, NULL,
+                                             $<id>1, $<cbuf>5, $<line>2,
+                                             ccode_line, FALSE, NULL);
+                       } else if(strcmp($<id>1, "finalize")==0) {
+                               push_init_arg($<id>3, FALSE);
+                               push_function(NO_SCOPE, FINALIZE_METHOD, NULL,
+                                             $<id>1, $<cbuf>5, $<line>2,
+                                             ccode_line, FALSE, NULL);
+
                        } else {
                                g_free($<id>1);
                                g_free($<id>3);
                                g_string_free($<cbuf>5,TRUE);
                                yyerror(_("parse error "
-                                         "(untyped blocks must be init or "
-                                         "class_init)"));
+                                         "(untyped blocks must be init, "
+                                         "class_init, constructor, dispose "
+                                         "or finalize)"));
                                YYERROR;
                        }
                                                }
        ;
 
-returnvals:    TOKEN retcode           {
+methodmods:    TOKEN retcode           {
+                       g_free(funcattrs); funcattrs = NULL;
                        g_free(onerror); onerror = NULL;
                        g_free(defreturn); defreturn = NULL;
-                       if(!set_return_value($<id>1, $<id>2)) {
+                       if(!set_attr_value($<id>1, $<id>2)) {
                                g_free($<id>1);
                                g_free($<id>2);
                                yyerror(_("parse error"));
@@ -1696,16 +1875,17 @@ returnvals:     TOKEN retcode           {
                        g_free($<id>1);
                                        }
        |       TOKEN retcode TOKEN retcode     {
+                       g_free(funcattrs); funcattrs = NULL;
                        g_free(onerror); onerror = NULL;
                        g_free(defreturn); defreturn = NULL;
-                       if(!set_return_value($<id>1, $<id>2)) {
+                       if(!set_attr_value($<id>1, $<id>2)) {
                                g_free($<id>1); g_free($<id>2);
                                g_free($<id>3); g_free($<id>4);
                                yyerror(_("parse error"));
                                YYERROR;
                        }
-                       if(!set_return_value($<id>3, $<id>4)) {
-                               onerror = defreturn = NULL;
+                       if(!set_attr_value($<id>3, $<id>4)) {
+                               funcattrs = onerror = defreturn = NULL;
                                g_free($<id>1); g_free($<id>2);
                                g_free($<id>3); g_free($<id>4);
                                yyerror(_("parse error"));
@@ -1714,7 +1894,39 @@ returnvals:      TOKEN retcode           {
                        g_free($<id>1);
                        g_free($<id>3);
                                                }
+       |       TOKEN retcode TOKEN retcode TOKEN retcode       {
+                       g_free(funcattrs); funcattrs = NULL;
+                       g_free(onerror); onerror = NULL;
+                       g_free(defreturn); defreturn = NULL;
+                       if(!set_attr_value($<id>1, $<id>2)) {
+                               g_free($<id>1); g_free($<id>2);
+                               g_free($<id>3); g_free($<id>4);
+                               g_free($<id>5); g_free($<id>6);
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+                       if(!set_attr_value($<id>3, $<id>4)) {
+                               funcattrs = onerror = defreturn = NULL;
+                               g_free($<id>1); g_free($<id>2);
+                               g_free($<id>3); g_free($<id>4);
+                               g_free($<id>5); g_free($<id>6);
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+                       if(!set_attr_value($<id>5, $<id>6)) {
+                               funcattrs = onerror = defreturn = NULL;
+                               g_free($<id>1); g_free($<id>2);
+                               g_free($<id>3); g_free($<id>4);
+                               g_free($<id>5); g_free($<id>6);
+                               yyerror(_("parse error"));
+                               YYERROR;
+                       }
+                       g_free($<id>1);
+                       g_free($<id>3);
+                       g_free($<id>5);
+                                               }
        |                               {
+                       g_free(funcattrs); funcattrs = NULL;
                        g_free(onerror); onerror = NULL;
                        g_free(defreturn); defreturn = NULL;
                                        }