[gtk+/wip/otte/tokenizer: 14/42] css: Add gtk_style_property_token_parse()



commit aa8d20471a5af399797aefb8878edb73bbbc0978
Author: Benjamin Otte <otte redhat com>
Date:   Tue Mar 15 06:47:00 2016 +0100

    css: Add gtk_style_property_token_parse()
    
    Slowly move the token parser into CSS value parsing.

 gtk/gtkcsscustomproperty.c           |    9 +++
 gtk/gtkcssdeclaration.c              |   55 ++++++++---------
 gtk/gtkcssparser.c                   |    2 +
 gtk/gtkcssshorthandproperty.c        |  109 ++++++++++++++++++++++++++++++++++
 gtk/gtkcssshorthandpropertyprivate.h |    4 +
 gtk/gtkcssstyleproperty.c            |   76 +++++++++++++++++++++++
 gtk/gtkcssstylepropertyprivate.h     |   17 +++--
 gtk/gtkstyleproperty.c               |   50 +++++++++++++++
 gtk/gtkstylepropertyprivate.h        |    7 ++-
 9 files changed, 292 insertions(+), 37 deletions(-)
---
diff --git a/gtk/gtkcsscustomproperty.c b/gtk/gtkcsscustomproperty.c
index f210ad3..3b65bac 100644
--- a/gtk/gtkcsscustomproperty.c
+++ b/gtk/gtkcsscustomproperty.c
@@ -43,6 +43,14 @@ gtk_css_custom_property_parse_value (GtkStyleProperty *property,
   return NULL;
 }
 
+static GtkCssValue *
+gtk_css_custom_property_token_parse (GtkStyleProperty  *property,
+                                     GtkCssTokenSource *source)
+{
+  gtk_css_token_source_unknown (source, "Custom CSS properties are no longer supported.");
+  return NULL;
+}
+
 static void
 gtk_css_custom_property_query (GtkStyleProperty   *property,
                                GValue             *value,
@@ -81,6 +89,7 @@ _gtk_css_custom_property_class_init (GtkCssCustomPropertyClass *klass)
   GtkStylePropertyClass *property_class = GTK_STYLE_PROPERTY_CLASS (klass);
 
   property_class->parse_value = gtk_css_custom_property_parse_value;
+  property_class->token_parse = gtk_css_custom_property_token_parse;
   property_class->query = gtk_css_custom_property_query;
   property_class->assign = gtk_css_custom_property_assign;
 }
diff --git a/gtk/gtkcssdeclaration.c b/gtk/gtkcssdeclaration.c
index 319c1fa..de40941 100644
--- a/gtk/gtkcssdeclaration.c
+++ b/gtk/gtkcssdeclaration.c
@@ -26,9 +26,8 @@
 typedef struct _GtkCssDeclarationPrivate GtkCssDeclarationPrivate;
 struct _GtkCssDeclarationPrivate {
   GtkCssStyleDeclaration *style;
-  char *name;
   GtkStyleProperty *prop;
-  char *value;
+  GtkCssValue *value;
 };
 
 G_DEFINE_TYPE_WITH_PRIVATE (GtkCssDeclaration, gtk_css_declaration, G_TYPE_OBJECT)
@@ -39,8 +38,8 @@ gtk_css_declaration_finalize (GObject *object)
   GtkCssDeclaration *declaration = GTK_CSS_DECLARATION (object);
   GtkCssDeclarationPrivate *priv = gtk_css_declaration_get_instance_private (declaration);
 
-  g_free (priv->name);
-  g_free (priv->value);
+  if (priv->value)
+    _gtk_css_value_unref (priv->value);
 
   G_OBJECT_CLASS (gtk_css_declaration_parent_class)->finalize (object);
 }
@@ -59,30 +58,13 @@ gtk_css_declaration_init (GtkCssDeclaration *declaration)
 }
 
 GtkCssDeclaration *
-gtk_css_declaration_new (GtkCssStyleDeclaration *style,
-                         const char             *name,
-                         const char             *value)
-{
-  GtkCssDeclarationPrivate *priv;
-  GtkCssDeclaration *result;
-
-  result = g_object_new (GTK_TYPE_CSS_DECLARATION, NULL);
-  priv = gtk_css_declaration_get_instance_private (result);
-
-  priv->style = style;
-  priv->name = g_strdup (name);
-  priv->value = g_strdup (value);
-
-  return result;
-}
-
-GtkCssDeclaration *
 gtk_css_declaration_new_parse (GtkCssStyleDeclaration *style,
                                GtkCssTokenSource      *source)
 {
   GtkCssDeclarationPrivate *priv;
   const GtkCssToken *token;
   GtkCssDeclaration *decl;
+  char *name;
 
   decl = g_object_new (GTK_TYPE_CSS_DECLARATION, NULL);
   priv = gtk_css_declaration_get_instance_private (decl);
@@ -99,25 +81,40 @@ gtk_css_declaration_new_parse (GtkCssStyleDeclaration *style,
       g_object_unref (decl);
       return NULL;
     }
-  priv->name = g_strdup (token->string.string);
-  priv->prop = _gtk_style_property_lookup (priv->name);
+  name = g_utf8_strdown (token->string.string, -1);
+  priv->prop = _gtk_style_property_lookup (name);
   if (priv->prop == NULL)
-    gtk_css_token_source_unknown (source, "Unknown property name '%s'", priv->name);
-  else if (!g_str_equal (priv->name, _gtk_style_property_get_name (priv->prop)))
+    {
+      gtk_css_token_source_unknown (source, "Unknown property name '%s'", token->string.string);
+      gtk_css_token_source_consume_all (source);
+      g_object_unref (decl);
+      g_free (name);
+      return NULL;
+    }
+  else if (!g_str_equal (name, _gtk_style_property_get_name (priv->prop)))
     gtk_css_token_source_deprecated (source,
                                      "The '%s' property has been renamed to '%s'",
-                                     priv->name, _gtk_style_property_get_name (priv->prop));
+                                     name, _gtk_style_property_get_name (priv->prop));
   gtk_css_token_source_consume_token (source);
   gtk_css_token_source_consume_whitespace (source);
+  g_free (name);
+
   token = gtk_css_token_source_get_token (source);
   if (!gtk_css_token_is (token, GTK_CSS_TOKEN_COLON))
     {
+      gtk_css_token_source_error (source, "No colon following property name");
       gtk_css_token_source_consume_all (source);
       g_object_unref (decl);
       return NULL;
     }
-
-  priv->value = gtk_css_token_source_consume_to_string (source);
+  gtk_css_token_source_consume_token (source);
+   
+  priv->value = gtk_style_property_token_parse (priv->prop, source);
+  if (priv->value == NULL)
+    {
+      g_object_unref (decl);
+      return NULL;
+    }
 
   return decl;
 }
diff --git a/gtk/gtkcssparser.c b/gtk/gtkcssparser.c
index 2a732e6..4cfd20a 100644
--- a/gtk/gtkcssparser.c
+++ b/gtk/gtkcssparser.c
@@ -75,6 +75,7 @@ do_the_tokenizer (const char *data)
 
   gtk_css_tokenizer_unref (tokenizer);
 #else
+#if 0
   GtkCssStyleSheet *sheet;
   GtkCssTokenSource *source;
   GtkCssTokenizer *tokenizer;
@@ -91,6 +92,7 @@ do_the_tokenizer (const char *data)
   gtk_css_tokenizer_unref (tokenizer);
   g_bytes_unref (bytes);
 #endif
+#endif
 }
 
 GtkCssParser *
diff --git a/gtk/gtkcssshorthandproperty.c b/gtk/gtkcssshorthandproperty.c
index 5e05761..34f83bc 100644
--- a/gtk/gtkcssshorthandproperty.c
+++ b/gtk/gtkcssshorthandproperty.c
@@ -156,6 +156,112 @@ gtk_css_shorthand_property_parse_value (GtkStyleProperty *property,
   return result;
 }
 
+static GtkCssValue *
+gtk_css_shorthand_property_token_parse (GtkStyleProperty  *property,
+                                        GtkCssTokenSource *source)
+{
+  GtkCssShorthandProperty *shorthand = GTK_CSS_SHORTHAND_PROPERTY (property);
+  const GtkCssToken *token;
+  GtkCssValue **data;
+  GtkCssValue *result;
+  guint i;
+
+  data = g_new0 (GtkCssValue *, shorthand->subproperties->len);
+
+  token = gtk_css_token_source_get_token (source);
+  if (gtk_css_token_is_ident (token, "initial"))
+    {
+      /* the initial value can be explicitly specified with the
+       * ‘initial’ keyword which all properties accept.
+       */
+      for (i = 0; i < shorthand->subproperties->len; i++)
+        {
+          data[i] = _gtk_css_initial_value_new ();
+        }
+      gtk_css_token_source_consume_token (source);
+    }
+  else if (gtk_css_token_is_ident (token, "inherit"))
+    {
+      /* All properties accept the ‘inherit’ value which
+       * explicitly specifies that the value will be determined
+       * by inheritance. The ‘inherit’ value can be used to
+       * strengthen inherited values in the cascade, and it can
+       * also be used on properties that are not normally inherited.
+       */
+      for (i = 0; i < shorthand->subproperties->len; i++)
+        {
+          data[i] = _gtk_css_inherit_value_new ();
+        }
+      gtk_css_token_source_consume_token (source);
+    }
+  else if (gtk_css_token_is_ident (token, "unset"))
+    {
+      /* If the cascaded value of a property is the unset keyword,
+       * then if it is an inherited property, this is treated as
+       * inherit, and if it is not, this is treated as initial.
+       */
+      for (i = 0; i < shorthand->subproperties->len; i++)
+        {
+          data[i] = _gtk_css_unset_value_new ();
+        }
+      gtk_css_token_source_consume_token (source);
+    }
+  else if (!shorthand->token_parse (shorthand, data, source))
+    {
+      for (i = 0; i < shorthand->subproperties->len; i++)
+        {
+          if (data[i] != NULL)
+            _gtk_css_value_unref (data[i]);
+        }
+      g_free (data);
+      return NULL;
+    }
+
+  /* All values that aren't set by the parse func are set to their
+   * default values here.
+   * XXX: Is the default always initial or can it be inherit? */
+  for (i = 0; i < shorthand->subproperties->len; i++)
+    {
+      if (data[i] == NULL)
+        data[i] = _gtk_css_initial_value_new ();
+    }
+
+  result = _gtk_css_array_value_new_from_array (data, shorthand->subproperties->len);
+  g_free (data);
+  
+  return result;
+}
+
+static void
+forward_error_to_source (GtkCssParser *parser,
+                         const GError *error,
+                         gpointer      source)
+{
+  /* XXX: This is bad because it doesn't emit the error on the right token */
+  gtk_css_token_source_emit_error (source, error);
+}
+
+static gboolean
+gtk_css_shorthand_token_parse_default (GtkCssShorthandProperty *shorthand,
+                                       GtkCssValue            **values,
+                                       GtkCssTokenSource       *source)
+{
+  GtkCssParser *parser;
+  char *str;
+  gboolean result;
+
+  str = gtk_css_token_source_consume_to_string (source);
+  parser = _gtk_css_parser_new (str,
+                                NULL,
+                                forward_error_to_source,
+                                source);
+  result = shorthand->parse (shorthand, values, parser);
+  _gtk_css_parser_free (parser);
+  g_free (str);
+
+  return result;
+}
+
 static void
 _gtk_css_shorthand_property_class_init (GtkCssShorthandPropertyClass *klass)
 {
@@ -175,12 +281,15 @@ _gtk_css_shorthand_property_class_init (GtkCssShorthandPropertyClass *klass)
   property_class->assign = _gtk_css_shorthand_property_assign;
   property_class->query = _gtk_css_shorthand_property_query;
   property_class->parse_value = gtk_css_shorthand_property_parse_value;
+  property_class->token_parse = gtk_css_shorthand_property_token_parse;
 }
 
 static void
 _gtk_css_shorthand_property_init (GtkCssShorthandProperty *shorthand)
 {
   shorthand->subproperties = g_ptr_array_new_with_free_func (g_object_unref);
+
+  shorthand->token_parse = gtk_css_shorthand_token_parse_default;
 }
 
 GtkCssStyleProperty *
diff --git a/gtk/gtkcssshorthandpropertyprivate.h b/gtk/gtkcssshorthandpropertyprivate.h
index d548370..55d4af4 100644
--- a/gtk/gtkcssshorthandpropertyprivate.h
+++ b/gtk/gtkcssshorthandpropertyprivate.h
@@ -41,6 +41,9 @@ typedef struct _GtkCssShorthandPropertyClass      GtkCssShorthandPropertyClass;
 typedef gboolean              (* GtkCssShorthandPropertyParseFunc)      (GtkCssShorthandProperty *shorthand,
                                                                          GtkCssValue            **values,
                                                                          GtkCssParser            *parser);
+typedef gboolean              (* GtkCssShorthandPropertyTokenParseFunc) (GtkCssShorthandProperty *shorthand,
+                                                                         GtkCssValue            **values,
+                                                                         GtkCssTokenSource       *source);
 typedef void                  (* GtkCssShorthandPropertyAssignFunc)     (GtkCssShorthandProperty *shorthand,
                                                                          GtkStyleProperties      *props,
                                                                          GtkStateFlags            state,
@@ -57,6 +60,7 @@ struct _GtkCssShorthandProperty
   GPtrArray *subproperties;
 
   GtkCssShorthandPropertyParseFunc parse;
+  GtkCssShorthandPropertyTokenParseFunc token_parse;
   GtkCssShorthandPropertyAssignFunc assign;
   GtkCssShorthandPropertyQueryFunc query;
 };
diff --git a/gtk/gtkcssstyleproperty.c b/gtk/gtkcssstyleproperty.c
index e4d3f8f..6379151 100644
--- a/gtk/gtkcssstyleproperty.c
+++ b/gtk/gtkcssstyleproperty.c
@@ -193,6 +193,80 @@ gtk_css_style_property_parse_value (GtkStyleProperty *property,
 }
 
 static void
+forward_error_to_source (GtkCssParser *parser,
+                         const GError *error,
+                         gpointer      source)
+{
+  /* XXX: This is bad because it doesn't emit the error on the right token */
+  gtk_css_token_source_emit_error (source, error);
+}
+
+static GtkCssValue *
+gtk_css_style_property_token_parse_default (GtkCssStyleProperty *property,
+                                            GtkCssTokenSource   *source)
+{
+  GtkCssParser *parser;
+  GtkCssValue *value;
+  char *str;
+
+  str = gtk_css_token_source_consume_to_string (source);
+  parser = _gtk_css_parser_new (str,
+                                NULL,
+                                forward_error_to_source,
+                                source);
+  value = property->parse_value (property, parser);
+  _gtk_css_parser_free (parser);
+  g_free (str);
+
+  return value;
+}
+
+static GtkCssValue *
+gtk_css_style_property_token_parse (GtkStyleProperty  *property,
+                                    GtkCssTokenSource *source)
+{
+  GtkCssStyleProperty *style_property = GTK_CSS_STYLE_PROPERTY (property);
+  const GtkCssToken *token;
+  GtkCssValue *value;
+
+  token = gtk_css_token_source_get_token (source);
+  if (gtk_css_token_is_ident (token, "initial"))
+    {
+      /* the initial value can be explicitly specified with the
+       * ‘initial’ keyword which all properties accept.
+       */
+      value = _gtk_css_initial_value_new ();
+      gtk_css_token_source_consume_token (source);
+    }
+  else if (gtk_css_token_is_ident (token, "inherit"))
+    {
+      /* All properties accept the ‘inherit’ value which
+       * explicitly specifies that the value will be determined
+       * by inheritance. The ‘inherit’ value can be used to
+       * strengthen inherited values in the cascade, and it can
+       * also be used on properties that are not normally inherited.
+       */
+      value = _gtk_css_inherit_value_new ();
+      gtk_css_token_source_consume_token (source);
+    }
+  else if (gtk_css_token_is_ident (token, "unset"))
+    {
+      /* If the cascaded value of a property is the unset keyword,
+       * then if it is an inherited property, this is treated as
+       * inherit, and if it is not, this is treated as initial.
+       */
+      value = _gtk_css_unset_value_new ();
+      gtk_css_token_source_consume_token (source);
+    }
+  else
+    {
+      value = (* style_property->token_parse) (style_property, source);
+    }
+
+  return value;
+}
+
+static void
 _gtk_css_style_property_class_init (GtkCssStylePropertyClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -242,6 +316,7 @@ _gtk_css_style_property_class_init (GtkCssStylePropertyClass *klass)
   property_class->assign = _gtk_css_style_property_assign;
   property_class->query = _gtk_css_style_property_query;
   property_class->parse_value = gtk_css_style_property_parse_value;
+  property_class->token_parse = gtk_css_style_property_token_parse;
 
   klass->style_properties = g_ptr_array_new ();
 
@@ -260,6 +335,7 @@ static void
 _gtk_css_style_property_init (GtkCssStyleProperty *property)
 {
   property->parse_value = gtk_css_style_property_real_parse_value;
+  property->token_parse = gtk_css_style_property_token_parse_default;
 }
 
 /**
diff --git a/gtk/gtkcssstylepropertyprivate.h b/gtk/gtkcssstylepropertyprivate.h
index 2dbe6ed..c78f81f 100644
--- a/gtk/gtkcssstylepropertyprivate.h
+++ b/gtk/gtkcssstylepropertyprivate.h
@@ -34,13 +34,15 @@ G_BEGIN_DECLS
 typedef struct _GtkCssStyleProperty           GtkCssStyleProperty;
 typedef struct _GtkCssStylePropertyClass      GtkCssStylePropertyClass;
 
-typedef GtkCssValue *    (* GtkCssStylePropertyParseFunc)  (GtkCssStyleProperty    *property,
-                                                            GtkCssParser           *parser);
-typedef void             (* GtkCssStylePropertyQueryFunc)  (GtkCssStyleProperty    *property,
-                                                            const GtkCssValue      *cssvalue,
-                                                            GValue                 *value);
-typedef GtkCssValue *    (* GtkCssStylePropertyAssignFunc) (GtkCssStyleProperty    *property,
-                                                            const GValue           *value);
+typedef GtkCssValue *    (* GtkCssStylePropertyParseFunc)       (GtkCssStyleProperty    *property,
+                                                                 GtkCssParser           *parser);
+typedef GtkCssValue *    (* GtkCssStylePropertyTokenParseFunc)  (GtkCssStyleProperty    *property,
+                                                                 GtkCssTokenSource      *source);
+typedef void             (* GtkCssStylePropertyQueryFunc)       (GtkCssStyleProperty    *property,
+                                                                 const GtkCssValue      *cssvalue,
+                                                                 GValue                 *value);
+typedef GtkCssValue *    (* GtkCssStylePropertyAssignFunc)      (GtkCssStyleProperty    *property,
+                                                                 const GValue           *value);
 struct _GtkCssStyleProperty
 {
   GtkStyleProperty parent;
@@ -52,6 +54,7 @@ struct _GtkCssStyleProperty
   guint animated :1;
 
   GtkCssStylePropertyParseFunc parse_value;
+  GtkCssStylePropertyTokenParseFunc token_parse;
   GtkCssStylePropertyQueryFunc query_value;
   GtkCssStylePropertyAssignFunc assign_value;
 };
diff --git a/gtk/gtkstyleproperty.c b/gtk/gtkstyleproperty.c
index 9639ae4..75279aa 100644
--- a/gtk/gtkstyleproperty.c
+++ b/gtk/gtkstyleproperty.c
@@ -159,6 +159,56 @@ _gtk_style_property_parse_value (GtkStyleProperty *property,
 }
 
 /**
+ * _gtk_style_property_parse_value:
+ * @property: the property
+ * @parser: the parser to parse from
+ *
+ * Tries to parse the given @property from the given @parser into
+ * @value. The type that @value will be assigned is dependant on
+ * the parser and no assumptions must be made about it. If the
+ * parsing fails, %FALSE will be returned and @value will be
+ * left uninitialized.
+ *
+ * Only if @property is a #GtkCssShorthandProperty, the @value will
+ * always be a #GtkCssValue whose values can be queried with
+ * _gtk_css_array_value_get_nth().
+ *
+ * Returns: %NULL on failure or the parsed #GtkCssValue
+ **/
+GtkCssValue *
+gtk_style_property_token_parse (GtkStyleProperty  *property,
+                                GtkCssTokenSource *source)
+{
+  GtkStylePropertyClass *klass;
+  GtkCssValue *value;
+
+  g_return_val_if_fail (GTK_IS_STYLE_PROPERTY (property), NULL);
+  g_return_val_if_fail (source != NULL, NULL);
+
+  klass = GTK_STYLE_PROPERTY_GET_CLASS (property);
+
+  gtk_css_token_source_consume_whitespace (source);
+
+  value = klass->token_parse (property, source);
+
+  if (value == NULL)
+    return NULL;
+
+  gtk_css_token_source_consume_whitespace (source);
+
+  if (!gtk_css_token_is (gtk_css_token_source_get_token (source),
+                         GTK_CSS_TOKEN_EOF))
+    {
+      gtk_css_token_source_error (source, "Junk at end of value");
+      gtk_css_token_source_consume_all (source);
+      _gtk_css_value_unref (value);
+      return NULL;
+    }
+
+  return value;
+}
+
+/**
  * _gtk_style_property_assign:
  * @property: the property
  * @props: The properties to assign to
diff --git a/gtk/gtkstylepropertyprivate.h b/gtk/gtkstylepropertyprivate.h
index 59b281f..d7ff8ab 100644
--- a/gtk/gtkstylepropertyprivate.h
+++ b/gtk/gtkstylepropertyprivate.h
@@ -19,6 +19,7 @@
 #define __GTK_STYLEPROPERTY_PRIVATE_H__
 
 #include "gtkcssparserprivate.h"
+#include "gtkcsstokensourceprivate.h"
 #include "gtkstylecontextprivate.h"
 #include "gtkcssvalueprivate.h"
 
@@ -57,8 +58,10 @@ struct _GtkStylePropertyClass
                                                             GValue                 *value,
                                                             GtkStyleQueryFunc       query_func,
                                                             gpointer                query_data);
-  GtkCssValue *     (* parse_value)                        (GtkStyleProperty *      property,
+  GtkCssValue *     (* parse_value)                        (GtkStyleProperty       *property,
                                                             GtkCssParser           *parser);
+  GtkCssValue *     (* token_parse)                        (GtkStyleProperty       *property,
+                                                            GtkCssTokenSource      *source);
 
   GHashTable   *properties;
 };
@@ -76,6 +79,8 @@ const char *             _gtk_style_property_get_name      (GtkStyleProperty
 
 GtkCssValue *            _gtk_style_property_parse_value   (GtkStyleProperty *      property,
                                                             GtkCssParser           *parser);
+GtkCssValue *            gtk_style_property_token_parse    (GtkStyleProperty       *property,
+                                                            GtkCssTokenSource      *source);
 
 GType                    _gtk_style_property_get_value_type(GtkStyleProperty *      property);
 void                     _gtk_style_property_query         (GtkStyleProperty *      property,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]