[Swfdec-commits] 33 commits - AUTHORS swfdec/swfdec_as_strings.c swfdec/swfdec_font.c swfdec/swfdec_font.h swfdec/swfdec_player.c swfdec/swfdec_tag.c swfdec/swfdec_text_format.c vivified/code

Pekka Lampila medar at kemper.freedesktop.org
Tue Apr 1 10:45:17 PDT 2008


 AUTHORS                                       |    1 
 swfdec/swfdec_as_strings.c                    |    4 
 swfdec/swfdec_font.c                          |   20 
 swfdec/swfdec_font.h                          |    6 
 swfdec/swfdec_player.c                        |    2 
 swfdec/swfdec_tag.c                           |    2 
 swfdec/swfdec_text_format.c                   |   72 +
 vivified/code/.gitignore                      |    1 
 vivified/code/Makefile.am                     |   12 
 vivified/code/compiler.c                      |   59 +
 vivified/code/vivi_code_assignment.c          |   16 
 vivified/code/vivi_compiler.c                 | 1062 ++++++++++++++++++++++++++
 vivified/code/vivi_compiler.h                 |   35 
 vivified/code/vivi_compiler_empty_statement.c |   69 +
 vivified/code/vivi_compiler_empty_statement.h |   56 +
 15 files changed, 1408 insertions(+), 9 deletions(-)

New commits:
commit f75836b3695f28b87a3067cfdd61581697adc7ac
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Tue Apr 1 20:43:54 2008 +0300

    Add James Bowes to the AUTHORS file

diff --git a/AUTHORS b/AUTHORS
index 51e5a0e..0bb0266 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -3,6 +3,7 @@ Benjamin Otte <otte at gnome.org>
 Cristian Grada <krigenator at gmail.com>
 David Schleef <ds at schleef.org>
 Eric Anholt <eric at anholt.net>
+James Bowes <jbowes at dangerouslyinc.com>
 Nguyễn Thái Ngọc Duy <pclouds at gmail.com>
 Pavel Roskin <proski at gnu.org>
 Pekka Lampila <pekka.lampila at iki.fi>
commit eed47549e6bb802a6d5039cb6ba1da06278bcb01
Author: James Bowes <jbowes at dangerouslyinc.com>
Date:   Tue Apr 1 20:42:42 2008 +0300

    Implement TextFormat.getTextExtent

diff --git a/swfdec/swfdec_as_strings.c b/swfdec/swfdec_as_strings.c
index 8e6cb9c..2170366 100644
--- a/swfdec/swfdec_as_strings.c
+++ b/swfdec/swfdec_as_strings.c
@@ -496,5 +496,9 @@ const char swfdec_as_strings[] =
   SWFDEC_AS_CONSTANT_STRING ("Selection")
   SWFDEC_AS_CONSTANT_STRING ("tabEnabled")
   SWFDEC_AS_CONSTANT_STRING ("focusEnabled")
+  SWFDEC_AS_CONSTANT_STRING ("ascent")
+  SWFDEC_AS_CONSTANT_STRING ("descent")
+  SWFDEC_AS_CONSTANT_STRING ("textFieldHeight")
+  SWFDEC_AS_CONSTANT_STRING ("textFieldWidth")
   /* add more here */
 ;
diff --git a/swfdec/swfdec_text_format.c b/swfdec/swfdec_text_format.c
index 79e82ee..fcc4b85 100644
--- a/swfdec/swfdec_text_format.c
+++ b/swfdec/swfdec_text_format.c
@@ -24,6 +24,7 @@
 
 #include <math.h>
 #include <string.h>
+#include <pango/pangocairo.h>
 
 #include "swfdec_text_format.h"
 #include "swfdec_as_native_function.h"
@@ -852,7 +853,76 @@ static void
 swfdec_text_format_getTextExtent (SwfdecAsContext *cx, SwfdecAsObject *object,
     guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
 {
-  SWFDEC_STUB ("TextFormat.getTextExtent");
+  SwfdecTextFormat *format;
+  SwfdecAsObject *obj = swfdec_as_object_new_empty (cx);
+  SwfdecAsValue val;
+  const gchar *text;
+  GList *item_list;
+  PangoAnalysis analysis;
+  PangoFontMap *fontmap;
+  PangoContext *pcontext;
+  PangoAttrList *attrs;
+  PangoGlyphString *glyph_string = pango_glyph_string_new();
+  PangoRectangle ink_rect;
+  PangoFontDescription *desc;
+  PangoFont *font;
+
+  SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FORMAT, &format, "s", &text);
+
+  fontmap = pango_cairo_font_map_get_default ();
+  pcontext =
+    pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap));
+
+  attrs = pango_attr_list_new ();
+  item_list = pango_itemize (pcontext, text, 0, strlen(text), attrs, NULL);
+  pango_attr_list_unref (attrs);
+
+  analysis = ((PangoItem *)(item_list[0].data))->analysis;
+  pango_shape (text, strlen(text), &analysis, glyph_string);
+
+  desc = pango_font_description_new ();
+  pango_font_description_set_family_static (desc, format->font);
+  pango_font_description_set_size (desc, format->size * PANGO_SCALE);
+  if (format->bold){
+    pango_font_description_set_weight (desc, PANGO_WEIGHT_BOLD);
+  }
+  if (format->italic)
+    pango_font_description_set_style (desc, PANGO_STYLE_ITALIC);
+
+  font = pango_font_map_load_font (fontmap, pcontext, desc);
+  pango_glyph_string_extents (glyph_string, font, &ink_rect, NULL);
+
+  pango_glyph_string_free (glyph_string);
+  g_list_foreach (item_list, (GFunc) pango_item_free, NULL);
+  g_list_free (item_list);
+  pango_font_description_free (desc);
+  g_object_unref (G_OBJECT (pcontext));
+  g_object_unref (G_OBJECT (fontmap));
+  g_object_unref (G_OBJECT (font));
+
+  SWFDEC_AS_VALUE_SET_INT (&val, ink_rect.width / PANGO_SCALE +
+						   format->left_margin + format->right_margin);
+  swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_width, &val);
+
+  SWFDEC_AS_VALUE_SET_INT (&val, (ink_rect.height / PANGO_SCALE +
+								  format->leading));
+  swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_height, &val);
+
+  SWFDEC_AS_VALUE_SET_INT (&val, PANGO_ASCENT(ink_rect) / PANGO_SCALE);
+  swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_ascent, &val);
+
+  SWFDEC_AS_VALUE_SET_INT (&val, PANGO_DESCENT (ink_rect) / PANGO_SCALE);
+  swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_descent, &val);
+
+  SWFDEC_AS_VALUE_SET_INT (&val, ink_rect.width / PANGO_SCALE +
+						   format->left_margin + format->right_margin + 4);
+  swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_textFieldWidth, &val);
+
+  SWFDEC_AS_VALUE_SET_INT (&val, ink_rect.height / PANGO_SCALE + 4 +
+						   format->leading);
+  swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_textFieldHeight, &val);
+
+  SWFDEC_AS_VALUE_SET_OBJECT (ret, obj);
 }
 
 void
commit 581b3f7f25670732159f506b28441e3631bf5bdd
Author: James Bowes <jbowes at dangerouslyinc.com>
Date:   Tue Apr 1 20:42:04 2008 +0300

    Implement the DefineFontName tag

diff --git a/swfdec/swfdec_font.c b/swfdec/swfdec_font.c
index a1dc936..82314f2 100644
--- a/swfdec/swfdec_font.c
+++ b/swfdec/swfdec_font.c
@@ -362,3 +362,23 @@ tag_func_define_font_2 (SwfdecSwfDecoder * s, guint tag)
 
   return SWFDEC_STATUS_OK;
 }
+
+int
+tag_func_define_font_name (SwfdecSwfDecoder * s, guint tag)
+{
+  guint id;
+  SwfdecFont *font;
+
+  id = swfdec_bits_get_u16 (&s->b);
+  font = swfdec_swf_decoder_get_character (s, id);
+
+  if (!SWFDEC_IS_FONT (font)) {
+    SWFDEC_ERROR ("didn't find a font with id %u", id);
+    return SWFDEC_STATUS_OK;
+  }
+
+  font->name = swfdec_bits_get_string (&s->b, s->version);
+  font->copyright = swfdec_bits_get_string (&s->b, s->version);
+
+  return SWFDEC_STATUS_OK;
+}
diff --git a/swfdec/swfdec_font.h b/swfdec/swfdec_font.h
index e1425e0..01bbbba 100644
--- a/swfdec/swfdec_font.h
+++ b/swfdec/swfdec_font.h
@@ -59,7 +59,8 @@ struct _SwfdecFont
 {
   SwfdecCharacter	character;
 
-  char *		name;		/* name of the font (FIXME: what name?) */
+  char *		name;		/* name of the font */
+  char *		copyright;	/* copyright of the font */
   PangoFontDescription *desc;
   gboolean		bold;		/* font is bold */
   gboolean		italic;		/* font is italic */
@@ -89,5 +90,8 @@ int		tag_func_define_font		(SwfdecSwfDecoder *	s,
 int		tag_func_define_font_2		(SwfdecSwfDecoder *	s,
 						 guint			tag);
 
+int		tag_func_define_font_name	(SwfdecSwfDecoder *	s,
+						 guint			tag);
+
 G_END_DECLS
 #endif
diff --git a/swfdec/swfdec_tag.c b/swfdec/swfdec_tag.c
index 16582e9..1d83bd0 100644
--- a/swfdec/swfdec_tag.c
+++ b/swfdec/swfdec_tag.c
@@ -432,7 +432,7 @@ static struct tag_func_struct tag_funcs[] = {
   [SWFDEC_TAG_PRIVATE_IMAGE] = { "PrivateImage", NULL, 0},
   [SWFDEC_TAG_DEFINESCENEDATA] = { "DefineSceneData", NULL, 0},
   [SWFDEC_TAG_DEFINEBINARYDATA] = { "DefineBinaryData", NULL, 0},
-  [SWFDEC_TAG_DEFINEFONTNAME] = { "DefineFontName", NULL, 0},
+  [SWFDEC_TAG_DEFINEFONTNAME] = { "DefineFontName", tag_func_define_font_name, 0},
   [SWFDEC_TAG_STARTSOUND2] = {"StartSound2", NULL, SWFDEC_TAG_DEFINE_SPRITE }
 };
 
commit 53a3f86bda5d594661e5efc0737907b000369000
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Tue Apr 1 20:40:33 2008 +0300

    Silence a compiler warning

diff --git a/swfdec/swfdec_player.c b/swfdec/swfdec_player.c
index ba7a880..641fc1d 100644
--- a/swfdec/swfdec_player.c
+++ b/swfdec/swfdec_player.c
@@ -1424,7 +1424,7 @@ static gboolean
 swfdec_player_handle_tab_list (SwfdecPlayer *player, SwfdecMovie *movie, SwfdecMovie *stop, gboolean forward)
 {
   SwfdecPlayerPrivate *priv;
-  SwfdecMovie *cur;
+  SwfdecMovie *cur = NULL;
   GList *list, *walk;
 
   priv = player->priv;
commit 85ec4fad8cd001abf9caaa1bfddaa6523dc5e413
Merge: 3e44bd6... d672757...
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Tue Apr 1 20:36:47 2008 +0300

    Merge branch 'master' of ssh://medar@git.freedesktop.org/git/swfdec/swfdec
    
    Conflicts:
    
    	vivified/code/Makefile.am

commit 3e44bd6c9570450180540525b3903bbdf487e1cb
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Mon Mar 31 19:22:14 2008 +0300

    Add support for giving error messages in the compiler

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index e759536..760c14e 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -47,12 +47,6 @@
 
 #include "vivi_code_text_printer.h"
 
-typedef enum {
-  STATUS_FAIL = -1,
-  STATUS_OK = 0,
-  STATUS_CANCEL = 1
-} ParseStatus;
-
 enum {
   // keywords
   TOKEN_BREAK = G_TOKEN_LAST + 1,
@@ -87,7 +81,14 @@ enum {
   TOKEN_NULL,
   // misc
   TOKEN_PLUSPLUS,
-  TOKEN_MINUSMINUS
+  TOKEN_MINUSMINUS,
+  // errors
+  ERROR_TOKEN_BOOLEAN,
+  ERROR_TOKEN_LITERAL,
+  ERROR_TOKEN_PROPERTY_NAME,
+  ERROR_TOKEN_PRIMARY_EXPRESSION,
+  ERROR_TOKEN_EXPRESSION_STATEMENT,
+  ERROR_TOKEN_STATEMENT
 };
 
 typedef struct {
@@ -163,13 +164,26 @@ static const TokenDescription custom_tokens[] = {
   { G_TOKEN_NONE, NULL }
 };
 
-typedef ParseStatus (*ParseStatementFunction) (GScanner *scanner, ViviCodeStatement **statement);
-typedef ParseStatus (*ParseValueFunction) (GScanner *scanner, ViviCodeValue **value);
+static const TokenDescription error_tokens[] = {
+  // errors
+  { ERROR_TOKEN_BOOLEAN, "boolean" },
+  { ERROR_TOKEN_LITERAL, "literal" },
+  { ERROR_TOKEN_PROPERTY_NAME, "property name" },
+  { ERROR_TOKEN_PRIMARY_EXPRESSION, "primary expression" },
+  { ERROR_TOKEN_EXPRESSION_STATEMENT, "expression statement" },
+  { ERROR_TOKEN_STATEMENT, "statement" },
+  { G_TOKEN_NONE, NULL }
+};
+
+#define FAIL(x) ((x) < 0 ? -x : x)
+
+typedef int (*ParseStatementFunction) (GScanner *scanner, ViviCodeStatement **statement);
+typedef int (*ParseValueFunction) (GScanner *scanner, ViviCodeValue **value);
 
-static ParseStatus
+static int
 parse_statement_list (GScanner *scanner, ParseStatementFunction function,
     ViviCodeStatement **statement, guint separator);
-static ParseStatus
+static int
 parse_value_list (GScanner *scanner, ParseValueFunction function,
     ViviCodeValue ***list, guint separator);
 
@@ -198,63 +212,62 @@ free_value_list (ViviCodeValue **list)
 
 // values
 
-static ParseStatus
+static int
 parse_null_literal (GScanner *scanner, ViviCodeValue **value)
 {
   *value = NULL;
 
   if (!check_token (scanner, TOKEN_NULL))
-    return STATUS_CANCEL;
+    return -TOKEN_NULL;
 
   *value = vivi_code_constant_new_null ();
-  return STATUS_OK;
+  return G_TOKEN_NONE;
 }
 
-static ParseStatus
+static int
 parse_boolean_literal (GScanner *scanner, ViviCodeValue **value)
 {
   *value = NULL;
 
   if (check_token (scanner, TOKEN_TRUE)) {
     *value = vivi_code_constant_new_boolean (TRUE);
-    return STATUS_OK;
+    return G_TOKEN_NONE;
   } else if (check_token (scanner, TOKEN_FALSE)) {
     *value = vivi_code_constant_new_boolean (FALSE);
-    return STATUS_OK;
+    return G_TOKEN_NONE;
   } else {
-    return STATUS_CANCEL;
+    return -ERROR_TOKEN_BOOLEAN;
   }
 }
 
-static ParseStatus
+static int
 parse_numeric_literal (GScanner *scanner, ViviCodeValue **value)
 {
   *value = NULL;
 
   if (!check_token (scanner, G_TOKEN_FLOAT))
-    return STATUS_CANCEL;
+    return -G_TOKEN_FLOAT;
 
   *value = vivi_code_constant_new_number (scanner->value.v_float);
-  return STATUS_OK;
+  return G_TOKEN_NONE;
 }
 
-static ParseStatus
+static int
 parse_string_literal (GScanner *scanner, ViviCodeValue **value)
 {
   *value = NULL;
 
   if (!check_token (scanner, G_TOKEN_STRING))
-    return STATUS_CANCEL;
+    return -G_TOKEN_STRING;
 
   *value = vivi_code_constant_new_string (scanner->value.v_string);
-  return STATUS_OK;
+  return G_TOKEN_NONE;
 }
 
-static ParseStatus
+static int
 parse_literal (GScanner *scanner, ViviCodeValue **value)
 {
-  int i;
-  ParseStatus status;
+  int i, expected;
   ParseValueFunction functions[] = {
     parse_null_literal,
     parse_boolean_literal,
@@ -266,32 +279,31 @@ parse_literal (GScanner *scanner, ViviCodeValue **value)
   *value = NULL;
 
   for (i = 0; functions[i] != NULL; i++) {
-    status = functions[i] (scanner, value);
-    if (status != STATUS_CANCEL)
-      return status;
+    expected = functions[i] (scanner, value);
+    if (expected >= 0)
+      return expected;
   }
 
-  return STATUS_CANCEL;
+  return -ERROR_TOKEN_LITERAL;
 }
 
-static ParseStatus
+static int
 parse_identifier (GScanner *scanner, ViviCodeValue **value)
 {
   *value = NULL;
 
   if (!check_token (scanner, G_TOKEN_IDENTIFIER))
-    return STATUS_CANCEL;
+    return -G_TOKEN_IDENTIFIER;
 
   *value = vivi_code_get_new_name (scanner->value.v_identifier);
 
-  return STATUS_OK;
+  return G_TOKEN_NONE;
 }
 
-static ParseStatus
+static int
 parse_property_name (GScanner *scanner, ViviCodeValue **value)
 {
-  int i;
-  ParseStatus status;
+  int i, expected;
   ParseValueFunction functions[] = {
     parse_identifier,
     parse_string_literal,
@@ -302,24 +314,26 @@ parse_property_name (GScanner *scanner, ViviCodeValue **value)
   *value = NULL;
 
   for (i = 0; functions[i] != NULL; i++) {
-    status = functions[i] (scanner, value);
-    if (status != STATUS_CANCEL)
-      return status;
+    expected = functions[i] (scanner, value);
+    if (expected >= 0)
+      return expected;
   }
 
-  return STATUS_CANCEL;
+  return -ERROR_TOKEN_PROPERTY_NAME;
 }
 
-static ParseStatus
+static int
 parse_operator_expression (GScanner *scanner, ViviCodeValue **value);
 
-static ParseStatus
+static int
 parse_object_literal (GScanner *scanner, ViviCodeValue **value)
 {
+  int expected;
+
   *value = NULL;
 
   if (!check_token (scanner, '{'))
-    return STATUS_CANCEL;
+    return -'{';
 
   *value = vivi_code_init_object_new ();
 
@@ -327,53 +341,62 @@ parse_object_literal (GScanner *scanner, ViviCodeValue **value)
     do {
       ViviCodeValue *property, *initializer;
 
-      if (parse_property_name (scanner, &property) != STATUS_OK)
-	goto fail;
+      expected = parse_property_name (scanner, &property);
+      if (expected != G_TOKEN_NONE) {
+	g_object_unref (*value);
+	*value = NULL;
+	return FAIL (expected);
+      }
 
-      if (!check_token (scanner, ':'))
-	goto fail;
+      if (!check_token (scanner, ':')) {
+	g_object_unref (*value);
+	*value = NULL;
+	return ':';
+      }
 
       // FIXME: assignment expression
-      if (parse_operator_expression (scanner, &initializer) != STATUS_OK)
-	goto fail;
+      expected = parse_operator_expression (scanner, &initializer);
+      if (expected != G_TOKEN_NONE) {
+	g_object_unref (*value);
+	*value = NULL;
+	return FAIL (expected);
+      }
 
       vivi_code_init_object_add_variable (VIVI_CODE_INIT_OBJECT (*value),
 	  property, initializer);
     } while (check_token (scanner, ','));
   }
 
-  if (!check_token (scanner, '}'))
-    goto fail;
-
-  return STATUS_OK;
-
-fail:
+  if (!check_token (scanner, '}')) {
+    g_object_unref (*value);
+    *value = NULL;
+    return '}';
+  }
 
-  g_object_unref (*value);
-  *value = NULL;
-  return STATUS_FAIL;
+  return G_TOKEN_NONE;
 }
 
 // misc
 
-static ParseStatus
+static int
 parse_variable_declaration (GScanner *scanner, ViviCodeStatement **statement)
 {
-  ParseStatus status;
+  int expected;
   ViviCodeValue *identifier;
   ViviCodeValue *value;
 
   *statement = NULL;
 
-  status = parse_identifier (scanner, &identifier);
-  if (status != STATUS_OK)
-    return status;
+  expected = parse_identifier (scanner, &identifier);
+  if (expected != G_TOKEN_NONE)
+    return expected;
 
   if (check_token (scanner, '=')) {
     // FIXME: assignment expression
-    if (parse_operator_expression (scanner, &value) != STATUS_OK) {
+    expected = parse_operator_expression (scanner, &value);
+    if (expected != G_TOKEN_NONE) {
       g_object_unref (identifier);
-      return STATUS_FAIL;
+      return FAIL (expected);
     }
   } else {
     value = vivi_code_constant_new_undefined ();
@@ -382,16 +405,15 @@ parse_variable_declaration (GScanner *scanner, ViviCodeStatement **statement)
   *statement = vivi_code_assignment_new (NULL, identifier, value);
   vivi_code_assignment_set_local (VIVI_CODE_ASSIGNMENT (*statement), TRUE);
 
-  return STATUS_OK;
+  return G_TOKEN_NONE;
 }
 
 // expression
 
-static ParseStatus
+static int
 parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
 {
-  int i;
-  ParseStatus status;
+  int i, expected;
   ParseValueFunction functions[] = {
     parse_identifier,
     parse_literal,
@@ -404,59 +426,62 @@ parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
 
   if (check_token (scanner, TOKEN_THIS)) {
     *value = vivi_code_get_new_name ("this");
-    return STATUS_OK;
+    return G_TOKEN_NONE;
   }
 
   if (check_token (scanner, '(')) {
     // FIXME: assignment expression
-    if (parse_operator_expression (scanner, value) != STATUS_OK)
-      return STATUS_FAIL;
+    expected = parse_operator_expression (scanner, value);
+    if (expected != G_TOKEN_NONE)
+      return FAIL (expected);
     if (!check_token (scanner, ')')) {
       g_object_unref (*value);
       *value = NULL;
-      return STATUS_FAIL;
+      return ')';
     }
-    return STATUS_OK;
+    return G_TOKEN_NONE;
   }
 
   for (i = 0; functions[i] != NULL; i++) {
-    status = functions[i] (scanner, value);
-    if (status != STATUS_CANCEL)
-      return status;
+    expected = functions[i] (scanner, value);
+    if (expected >= 0)
+      return expected;
   }
 
-  return STATUS_CANCEL;
+  return -ERROR_TOKEN_PRIMARY_EXPRESSION;
 }
 
-static ParseStatus
+static int
 parse_member_expression (GScanner *scanner, ViviCodeValue **value)
 {
-  ParseStatus status;
+  int expected;
   ViviCodeValue *member;
 
   // TODO: new MemberExpression Arguments
 
-  status = parse_primary_expression (scanner, value);
-  //if (status == STATUS_CANCEL)
-  //  status = parse_function_expression (scanner, value);
+  expected = parse_primary_expression (scanner, value);
+  //if (expected == STATUS_CANCEL)
+  //  expected = parse_function_expression (scanner, value);
 
-  if (status != 0)
-    return status;
+  if (expected != G_TOKEN_NONE)
+    return expected;
 
   do {
     ViviCodeValue *tmp;
 
     if (check_token (scanner, '[')) {
       // FIXME: expression
-      if (parse_operator_expression (scanner, &member) != STATUS_OK)
-	return STATUS_FAIL;
+      expected = parse_operator_expression (scanner, &member);
+      if (expected != G_TOKEN_NONE)
+	return FAIL (expected);
       if (!check_token (scanner, ']'))
-	return STATUS_FAIL;
+	return ']';
     } else if (check_token (scanner, '.')) {
-      if (parse_identifier (scanner, &member) != STATUS_OK)
-	return STATUS_FAIL;
+      expected = parse_identifier (scanner, &member);
+      if (expected != G_TOKEN_NONE)
+	return FAIL (expected);
     } else {
-      return STATUS_OK;
+      return G_TOKEN_NONE;
     }
 
     tmp = *value;
@@ -466,17 +491,19 @@ parse_member_expression (GScanner *scanner, ViviCodeValue **value)
   } while (TRUE);
 
   g_assert_not_reached ();
-  return STATUS_FAIL;
 }
 
-static ParseStatus
+static int
 parse_new_expression (GScanner *scanner, ViviCodeValue **value)
 {
+  int expected;
+
   *value = NULL;
 
   if (check_token (scanner, TOKEN_NEW)) {
-    if (parse_new_expression (scanner, value) != STATUS_OK)
-      return STATUS_FAIL;
+    expected = parse_new_expression (scanner, value);
+    if (expected != G_TOKEN_NONE)
+      return FAIL (expected);
     if (!VIVI_IS_CODE_FUNCTION_CALL (*value)) {
       ViviCodeValue *tmp = VIVI_CODE_VALUE (*value);
       *value = vivi_code_function_call_new (NULL, tmp);
@@ -484,47 +511,60 @@ parse_new_expression (GScanner *scanner, ViviCodeValue **value)
     }
     vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*value),
 	TRUE);
-    return STATUS_OK;
+    return G_TOKEN_NONE;
   } else {
     return parse_member_expression (scanner, value);
   }
 }
 
-static ParseStatus
+static int
 parse_left_hand_side_expression (GScanner *scanner, ViviCodeValue **value)
 {
-  ParseStatus status;
+  int expected;
 
   *value = NULL;
 
-  status = parse_new_expression (scanner, value);
-  //if (status == STATUS_CANCEL)
-  //  status = parse_call_expression (scanner, value);
+  expected = parse_new_expression (scanner, value);
+  //if (expected == STATUS_CANCEL)
+  //  expected = parse_call_expression (scanner, value);
 
-  return status;
+  return expected;
 }
 
-static ParseStatus
+static int
 parse_postfix_expression (GScanner *scanner, ViviCodeValue **value)
 {
-  ParseStatus status;
+  int expected;
+  ViviCodeValue *tmp, *one;
+  const char *operator;
 
-  status = parse_left_hand_side_expression (scanner, value);
-  if (status != STATUS_OK)
-    return status;
+  expected = parse_left_hand_side_expression (scanner, value);
+  if (expected != G_TOKEN_NONE)
+    return expected;
 
   // FIXME: Don't allow new line here
 
-  /*if (check_token (scanner, TOKEN_PLUSPLUS)) {
-    ViviCodeValue *tmp = *value;
-    *value = vivi_code_postfix_new (tmp, "++");
-    g_object_unref (tmp);
-  } else {*/
-    return STATUS_OK;
-  //}
+  if (check_token (scanner, TOKEN_PLUSPLUS)) {
+    operator = "+";
+  } else if (check_token (scanner, TOKEN_MINUSMINUS)) {
+    operator = "-";
+  } else {
+    return G_TOKEN_NONE;
+  }
+
+  one = vivi_code_constant_new_number (1);
+
+  // FIXME: Side effect!
+  tmp = *value;
+  *value = vivi_code_binary_new_name (tmp, one, operator);
+  g_object_unref (tmp);
+
+  g_object_unref (one);
+
+  return G_TOKEN_NONE;
 }
 
-static ParseStatus
+static int
 parse_unary_expression (GScanner *scanner, ViviCodeValue **value)
 {
   ViviCodeValue *tmp;
@@ -532,82 +572,88 @@ parse_unary_expression (GScanner *scanner, ViviCodeValue **value)
   *value = NULL;
 
   if (check_token (scanner, '!')) {
-    parse_unary_expression (scanner, value);
+    int expected = parse_unary_expression (scanner, value);
+    if (expected != G_TOKEN_NONE)
+      return FAIL (expected);
     tmp = VIVI_CODE_VALUE (*value);
     *value = vivi_code_unary_new (tmp, '!');
     g_object_unref (tmp);
-    return STATUS_OK;
+    return G_TOKEN_NONE;
   } else {
     return parse_postfix_expression (scanner, value);
   }
 }
 
-static ParseStatus
+static int
 parse_operator_expression (GScanner *scanner, ViviCodeValue **value)
 {
-  ParseStatus status;
+  int expected;
   ViviCodeValue *left;
   ViviCodeValue *right;
 
   *value = NULL;
 
-  status = parse_unary_expression (scanner, value);
-  if (status != STATUS_OK)
-    return status;
+  expected = parse_unary_expression (scanner, value);
+  if (expected != G_TOKEN_NONE)
+    return expected;
 
-  do {
-    if (!check_token (scanner, '+'))
-      return STATUS_OK;
-
-    if (parse_unary_expression (scanner, &right) != STATUS_OK) {
+  while (check_token (scanner, '+')) {
+    expected = parse_unary_expression (scanner, &right);
+    if (expected != G_TOKEN_NONE) {
       g_object_unref (*value);
       *value = NULL;
-      return STATUS_FAIL;
+      return FAIL (expected);
     }
 
     left = VIVI_CODE_VALUE (*value);
     *value = vivi_code_binary_new_name (left, VIVI_CODE_VALUE (right), "+");
     g_object_unref (left);
     g_object_unref (right);
-  } while (TRUE);
-
-  g_object_unref (*value);
-  *value = NULL;
+  };
 
-  return STATUS_FAIL;
+  return G_TOKEN_NONE;
 }
 
-static ParseStatus
+static int
 parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement);
 
-static ParseStatus
+static int
 parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
 {
-  ParseStatus status;
+  int expected;
   ViviCodeValue *value;
   ViviCodeStatement *if_statement, *else_statement;
 
   *statement = NULL;
-  if_statement = NULL;
 
-  status = parse_operator_expression (scanner, &value);
-  if (status != STATUS_OK)
-    return status;
+  expected = parse_operator_expression (scanner, &value);
+  if (expected != G_TOKEN_NONE)
+    return expected;
 
   if (!check_token (scanner, '?')) {
     *statement = vivi_code_value_statement_new (VIVI_CODE_VALUE (value));
     g_object_unref (value);
-    return STATUS_OK;
+    return G_TOKEN_NONE;
   }
 
-  if (parse_assignment_expression (scanner, &if_statement) != STATUS_OK)
-    goto fail;
+  expected = parse_assignment_expression (scanner, &if_statement);
+  if (expected != G_TOKEN_NONE) {
+    g_object_unref (value);
+    return FAIL (expected);
+  }
 
-  if (!check_token (scanner, ':'))
-    goto fail;
+  if (!check_token (scanner, ':')) {
+    g_object_unref (value);
+    g_object_unref (if_statement);
+    return ':';
+  }
 
-  if (parse_assignment_expression (scanner, &else_statement) != STATUS_OK)
-    goto fail;
+  expected = parse_assignment_expression (scanner, &else_statement);
+  if (expected != G_TOKEN_NONE) {
+    g_object_unref (value);
+    g_object_unref (if_statement);
+    return FAIL (expected);
+  }
 
   *statement = vivi_code_if_new (value);
   vivi_code_if_set_if (VIVI_CODE_IF (*statement), if_statement);
@@ -617,18 +663,10 @@ parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
   g_object_unref (if_statement);
   g_object_unref (else_statement);
 
-  return STATUS_OK;
-
-fail:
-
-  g_object_unref (value);
-  if (if_statement != NULL)
-    g_object_unref (if_statement);
-
-  return STATUS_FAIL;
+  return G_TOKEN_NONE;
 }
 
-static ParseStatus
+static int
 parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement)
 {
   *statement = NULL;
@@ -638,7 +676,7 @@ parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement)
   return parse_conditional_expression (scanner, statement);
 }
 
-static ParseStatus
+static int
 parse_expression (GScanner *scanner, ViviCodeStatement **statement)
 {
   *statement = NULL;
@@ -649,59 +687,62 @@ parse_expression (GScanner *scanner, ViviCodeStatement **statement)
 
 // statement
 
-static ParseStatus
+static int
 parse_expression_statement (GScanner *scanner, ViviCodeStatement **statement)
 {
-  ParseStatus status;
+  int expected;
 
   *statement = NULL;
 
   g_scanner_peek_next_token (scanner);
   if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
-    return STATUS_CANCEL;
+    return -ERROR_TOKEN_EXPRESSION_STATEMENT;
 
-  status = parse_expression (scanner, statement);
-  if (status != STATUS_OK)
-    return status;
+  expected = parse_expression (scanner, statement);
+  if (expected != G_TOKEN_NONE)
+    return expected;
 
   if (!check_token (scanner, ';')) {
     g_object_unref (*statement);
     *statement = NULL;
-    return STATUS_FAIL;
+    return ';';
   }
 
-  return STATUS_OK;
+  return G_TOKEN_NONE;
 }
 
-static ParseStatus
+static int
 parse_empty_statement (GScanner *scanner, ViviCodeStatement **statement)
 {
   *statement = NULL;
 
   if (!check_token (scanner, ';'))
-    return STATUS_CANCEL;
+    return -';';
 
   *statement = vivi_compiler_empty_statement_new ();
 
-  return STATUS_OK;
+  return G_TOKEN_NONE;
 }
 
-static ParseStatus
+static int
 parse_statement (GScanner *scanner, ViviCodeStatement **statement);
 
-static ParseStatus
+static int
 parse_block (GScanner *scanner, ViviCodeStatement **statement)
 {
+  int expected;
+
   *statement = NULL;
 
   if (!check_token (scanner, '{'))
-    return STATUS_CANCEL;
+    return -'{';
 
   g_scanner_peek_next_token (scanner);
   if (scanner->next_token != '}') {
-    if (parse_statement_list (scanner, parse_statement, statement,
-	  G_TOKEN_NONE) != STATUS_OK)
-      return STATUS_FAIL;
+    expected =
+      parse_statement_list (scanner, parse_statement, statement, G_TOKEN_NONE);
+    if (expected != G_TOKEN_NONE)
+      return FAIL (expected);
   } else {
     *statement = vivi_code_block_new ();
   }
@@ -709,37 +750,40 @@ parse_block (GScanner *scanner, ViviCodeStatement **statement)
   if (!check_token (scanner, '}')) {
     g_object_unref (*statement);
     *statement = NULL;
-    return STATUS_FAIL;
+    return '}';
   }
 
-  return STATUS_OK;
+  return G_TOKEN_NONE;
 }
 
-static ParseStatus
+static int
 parse_variable_statement (GScanner *scanner, ViviCodeStatement **statement)
 {
+  int expected;
+
   *statement = NULL;
 
   if (!check_token (scanner, TOKEN_VAR))
-    return STATUS_CANCEL;
+    return -TOKEN_VAR;
 
-  if (parse_statement_list (scanner, parse_variable_declaration, statement,
-	',') != STATUS_OK)
-    return STATUS_FAIL;
+  expected =
+    parse_statement_list (scanner, parse_variable_declaration, statement, ',');
+  if (expected != G_TOKEN_NONE)
+    return FAIL (expected);
 
   if (!check_token (scanner, ';')) {
     g_object_unref (*statement);
     *statement = NULL;
-    return STATUS_FAIL;
+    return ';';
   }
 
-  return STATUS_OK;
+  return G_TOKEN_NONE;
 }
 
-static ParseStatus
+static int
 parse_statement (GScanner *scanner, ViviCodeStatement **statement)
 {
-  int i, status;
+  int i, expected;
   ParseStatementFunction functions[] = {
     parse_block,
     parse_variable_statement,
@@ -761,26 +805,27 @@ parse_statement (GScanner *scanner, ViviCodeStatement **statement)
   *statement = NULL;
 
   for (i = 0; functions[i] != NULL; i++) {
-    status = functions[i] (scanner, statement);
-    if (status != STATUS_CANCEL)
-      return status;
+    expected = functions[i] (scanner, statement);
+    if (expected >= 0)
+      return expected;
   }
 
-  return STATUS_CANCEL;
+  return -ERROR_TOKEN_STATEMENT;
 }
 
 // function
 
-static ParseStatus
+static int
 parse_source_element (GScanner *scanner, ViviCodeStatement **statement);
 
-static ParseStatus
+static int
 parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
 {
   //ViviCodeStatement *function;
   ViviCodeValue *identifier;
   ViviCodeValue **arguments;
   ViviCodeStatement *body;
+  int expected;
 
   *statement = NULL;
 
@@ -789,30 +834,47 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
   body = NULL;
 
   if (!check_token (scanner, TOKEN_FUNCTION))
-    return STATUS_CANCEL;
+    return -TOKEN_FUNCTION;
 
-  if (parse_identifier (scanner, &identifier) != STATUS_OK)
-    return STATUS_FAIL;
+  expected = parse_identifier (scanner, &identifier);
+  if (expected != G_TOKEN_NONE)
+    return FAIL (expected);
 
-  if (!check_token (scanner, '('))
-    goto fail;
+  if (!check_token (scanner, '(')) {
+    g_object_unref (identifier);
+    return '(';
+  }
 
-  if (parse_value_list (scanner, parse_identifier, &arguments, ',') ==
-      STATUS_FAIL)
-    goto fail;
+  expected = parse_value_list (scanner, parse_identifier, &arguments, ',');
+  if (expected != G_TOKEN_NONE && expected >= 0)
+    return expected;
 
-  if (!check_token (scanner, ')'))
-    goto fail;
+  if (!check_token (scanner, ')')) {
+    g_object_unref (identifier);
+    free_value_list (arguments);
+    return ')';
+  }
 
-  if (!check_token (scanner, '{'))
-    goto fail;
+  if (!check_token (scanner, '{')) {
+    g_object_unref (identifier);
+    free_value_list (arguments);
+    return '{';
+  }
 
-  if (parse_statement_list (scanner, parse_source_element, &body, G_TOKEN_NONE)
-      == STATUS_FAIL)
-    goto fail;
+  expected = parse_statement_list (scanner, parse_source_element, &body,
+      G_TOKEN_NONE);
+  if (expected != G_TOKEN_NONE && expected >= 0) {
+    g_object_unref (identifier);
+    free_value_list (arguments);
+    return expected;
+  }
 
-  if (!check_token (scanner, '}'))
-    goto fail;
+  if (!check_token (scanner, '}')) {
+    g_object_unref (identifier);
+    free_value_list (arguments);
+    g_object_unref (body);
+    return '}';
+  }
 
   /*function = vivi_code_function_new (arguments, body);
   *statement = vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
@@ -820,67 +882,66 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
   *statement = vivi_compiler_empty_statement_new ();
 
   g_object_unref (identifier);
-  if (arguments != NULL)
-    free_value_list (arguments);
-  if (body != NULL)
-    g_object_unref (body);
-
-  return STATUS_OK;
-
-fail:
-  if (identifier != NULL)
-    g_object_unref (identifier);
-  if (arguments != NULL)
-    free_value_list (arguments);
-  if (body != NULL)
-    g_object_unref (body);
+  free_value_list (arguments);
+  g_object_unref (body);
 
-  return STATUS_FAIL;
+  return G_TOKEN_NONE;
 }
 
 // top
 
-static ParseStatus
+static int
 parse_source_element (GScanner *scanner, ViviCodeStatement **statement)
 {
-  ParseStatus status;
+  int expected;
 
   *statement = NULL;
 
-  status = parse_function_declaration (scanner, statement);
-  if (status == STATUS_CANCEL)
-    status = parse_statement (scanner, statement);
+  expected = parse_function_declaration (scanner, statement);
+  if (expected < 0)
+    expected = parse_statement (scanner, statement);
 
-  return status;
+  return expected;
 }
 
-static ParseStatus
+static int
 parse_program (GScanner *scanner, ViviCodeStatement **statement)
 {
+  int expected;
+
   *statement = NULL;
 
-  return parse_statement_list (scanner, parse_source_element, statement,
+  expected = parse_statement_list (scanner, parse_source_element, statement,
       G_TOKEN_NONE);
+  if (expected != G_TOKEN_NONE)
+    return FAIL (expected);
+
+  if (!check_token (scanner, G_TOKEN_EOF)) {
+    *statement = NULL;
+    return FAIL (parse_statement (scanner, statement));
+  }
+
+  return G_TOKEN_NONE;
 }
 
 // parsing
 
-static ParseStatus
+static int
 parse_statement_list (GScanner *scanner, ParseStatementFunction function,
     ViviCodeStatement **block, guint separator)
 {
   ViviCodeStatement *statement;
-  ParseStatus status;
+  int expected;
 
-  g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
-  g_return_val_if_fail (function != NULL, STATUS_FAIL);
-  g_return_val_if_fail (block != NULL, STATUS_FAIL);
+  g_assert (scanner != NULL);
+  g_assert (function != NULL);
+  g_assert (block != NULL);
 
   *block = NULL;
 
-  status = function (scanner, &statement);
-  if (status != STATUS_OK)
-    return status;
+  expected = function (scanner, &statement);
+  if (expected != G_TOKEN_NONE)
+    return expected;
 
   *block = vivi_code_block_new ();
 
@@ -891,32 +952,32 @@ parse_statement_list (GScanner *scanner, ParseStatementFunction function,
     if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
       break;
 
-    status = function (scanner, &statement);
-    if (status == STATUS_FAIL) {
+    expected = function (scanner, &statement);
+    if (expected != G_TOKEN_NONE && expected >= 0) {
       g_object_unref (*block);
       *block = NULL;
-      return STATUS_FAIL;
+      return expected;
     }
-  } while (status == STATUS_OK);
+  } while (expected == G_TOKEN_NONE);
 
-  return STATUS_OK;
+  return G_TOKEN_NONE;
 }
 
-static ParseStatus
+static int
 parse_value_list (GScanner *scanner, ParseValueFunction function,
     ViviCodeValue ***list, guint separator)
 {
   GPtrArray *array;
   ViviCodeValue *value;
-  ParseStatus status;
+  int expected;
 
-  g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
-  g_return_val_if_fail (function != NULL, STATUS_FAIL);
-  g_return_val_if_fail (list != NULL, STATUS_FAIL);
+  g_assert (scanner != NULL);
+  g_assert (function != NULL);
+  g_assert (list != NULL);
 
-  status = function (scanner, &value);
-  if (status != STATUS_OK)
-    return status;
+  expected = function (scanner, &value);
+  if (expected != G_TOKEN_NONE)
+    return expected;
 
   array = g_ptr_array_new ();
 
@@ -926,15 +987,15 @@ parse_value_list (GScanner *scanner, ParseValueFunction function,
     if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
       break;
 
-    status = function (scanner, &value);
-    if (status == STATUS_FAIL)
-      return STATUS_FAIL;
-  } while (status == STATUS_OK);
+    expected = function (scanner, &value);
+    if (expected != G_TOKEN_NONE && expected >= 0)
+      return expected;
+  } while (expected == G_TOKEN_NONE);
   g_ptr_array_add (array, NULL);
 
   *list = (ViviCodeValue **)g_ptr_array_free (array, FALSE);
 
-  return STATUS_OK;
+  return G_TOKEN_NONE;
 }
 
 // public
@@ -944,8 +1005,7 @@ vivi_compile_text (const char *text, gsize len, const char *input_name)
 {
   GScanner *scanner;
   ViviCodeStatement *statement;
-  ParseStatus status;
-  int i;
+  int expected, i;
 
   g_return_val_if_fail (text != NULL, NULL);
 
@@ -970,9 +1030,31 @@ vivi_compile_text (const char *text, gsize len, const char *input_name)
   scanner->input_name = input_name;
   g_scanner_input_text (scanner, text, len);
 
-  status = parse_program (scanner, &statement);
-  g_assert ((status == STATUS_OK && VIVI_IS_CODE_STATEMENT (statement)) ||
-	(status != STATUS_OK && statement == NULL));
+  expected = parse_program (scanner, &statement);
+  g_assert ((expected == G_TOKEN_NONE && VIVI_IS_CODE_STATEMENT (statement)) ||
+	(expected != G_TOKEN_NONE && statement == NULL));
+  if (expected != G_TOKEN_NONE) {
+    char *name = NULL;
+
+    for (i = 0; custom_tokens[i].token != G_TOKEN_NONE; i++) {
+      if (custom_tokens[i].token == FAIL (expected)) {
+	name = g_ascii_strup (custom_tokens[i].symbol, -1);
+	break;
+      }
+    }
+    if (custom_tokens[i].token == G_TOKEN_NONE) {
+      for (i = 0; error_tokens[i].token != G_TOKEN_NONE; i++) {
+	if (error_tokens[i].token == FAIL (expected)) {
+	  name = g_ascii_strup (error_tokens[i].symbol, -1);
+	  break;
+	}
+      }
+    }
+
+    g_scanner_get_next_token (scanner);
+    g_scanner_unexp_token (scanner, FAIL (expected), NULL, name, NULL, NULL,
+	TRUE);
+  }
 
   g_scanner_destroy (scanner);
 
commit 7fea8b48db4b0d01358805860b97df4b37a8b1fc
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sun Mar 30 04:04:49 2008 +0300

    Use operator expression in some places, instead of (assignment) expression
    
    Just temporarily, since we don't support side-effects properly yet

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 3d31c30..e759536 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -310,7 +310,6 @@ parse_property_name (GScanner *scanner, ViviCodeValue **value)
   return STATUS_CANCEL;
 }
 
-// FIXME
 static ParseStatus
 parse_operator_expression (GScanner *scanner, ViviCodeValue **value);
 
@@ -334,7 +333,7 @@ parse_object_literal (GScanner *scanner, ViviCodeValue **value)
       if (!check_token (scanner, ':'))
 	goto fail;
 
-      // FIXME
+      // FIXME: assignment expression
       if (parse_operator_expression (scanner, &initializer) != STATUS_OK)
 	goto fail;
 
@@ -371,8 +370,11 @@ parse_variable_declaration (GScanner *scanner, ViviCodeStatement **statement)
     return status;
 
   if (check_token (scanner, '=')) {
-    // TODO
-    return STATUS_FAIL;
+    // FIXME: assignment expression
+    if (parse_operator_expression (scanner, &value) != STATUS_OK) {
+      g_object_unref (identifier);
+      return STATUS_FAIL;
+    }
   } else {
     value = vivi_code_constant_new_undefined ();
   }
@@ -405,9 +407,17 @@ parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
     return STATUS_OK;
   }
 
-  /*if (check_token (scanner, '(')) {
+  if (check_token (scanner, '(')) {
+    // FIXME: assignment expression
+    if (parse_operator_expression (scanner, value) != STATUS_OK)
+      return STATUS_FAIL;
+    if (!check_token (scanner, ')')) {
+      g_object_unref (*value);
+      *value = NULL;
+      return STATUS_FAIL;
+    }
     return STATUS_OK;
-  }*/
+  }
 
   for (i = 0; functions[i] != NULL; i++) {
     status = functions[i] (scanner, value);
@@ -436,13 +446,13 @@ parse_member_expression (GScanner *scanner, ViviCodeValue **value)
   do {
     ViviCodeValue *tmp;
 
-    /*if (check_token (scanner, '[')) {
-      if (parse_expression (scanner, &member) != STATUS_OK)
+    if (check_token (scanner, '[')) {
+      // FIXME: expression
+      if (parse_operator_expression (scanner, &member) != STATUS_OK)
 	return STATUS_FAIL;
       if (!check_token (scanner, ']'))
 	return STATUS_FAIL;
-    } else*/
-    if (check_token (scanner, '.')) {
+    } else if (check_token (scanner, '.')) {
       if (parse_identifier (scanner, &member) != STATUS_OK)
 	return STATUS_FAIL;
     } else {
commit d79a2eeb0ed4014ca408ba612d537b78e83cf0d1
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sun Mar 30 02:51:42 2008 +0200

    Parse object literals, except for side effects in initializers

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index ca66429..3d31c30 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -199,35 +199,82 @@ free_value_list (ViviCodeValue **list)
 // values
 
 static ParseStatus
-parse_literal (GScanner *scanner, ViviCodeValue **value)
+parse_null_literal (GScanner *scanner, ViviCodeValue **value)
 {
   *value = NULL;
 
-  if (check_token (scanner, G_TOKEN_STRING)) {
-    *value = vivi_code_constant_new_string (scanner->value.v_string);
-    return STATUS_OK;
-  } else if (check_token (scanner, G_TOKEN_FLOAT)) {
-    *value = vivi_code_constant_new_number (scanner->value.v_float);
-    return STATUS_OK;
-  } else if (check_token (scanner, TOKEN_TRUE)) {
+  if (!check_token (scanner, TOKEN_NULL))
+    return STATUS_CANCEL;
+
+  *value = vivi_code_constant_new_null ();
+  return STATUS_OK;
+}
+
+static ParseStatus
+parse_boolean_literal (GScanner *scanner, ViviCodeValue **value)
+{
+  *value = NULL;
+
+  if (check_token (scanner, TOKEN_TRUE)) {
     *value = vivi_code_constant_new_boolean (TRUE);
     return STATUS_OK;
   } else if (check_token (scanner, TOKEN_FALSE)) {
     *value = vivi_code_constant_new_boolean (FALSE);
     return STATUS_OK;
-  } else if (check_token (scanner, TOKEN_NULL)) {
-    *value = vivi_code_constant_new_null ();
-    return STATUS_OK;
   } else {
     return STATUS_CANCEL;
   }
+}
 
-  *value = vivi_code_get_new_name (scanner->value.v_identifier);
+static ParseStatus
+parse_numeric_literal (GScanner *scanner, ViviCodeValue **value)
+{
+  *value = NULL;
+
+  if (!check_token (scanner, G_TOKEN_FLOAT))
+    return STATUS_CANCEL;
 
+  *value = vivi_code_constant_new_number (scanner->value.v_float);
   return STATUS_OK;
 }
 
 static ParseStatus
+parse_string_literal (GScanner *scanner, ViviCodeValue **value)
+{
+  *value = NULL;
+
+  if (!check_token (scanner, G_TOKEN_STRING))
+    return STATUS_CANCEL;
+
+  *value = vivi_code_constant_new_string (scanner->value.v_string);
+  return STATUS_OK;
+}
+
+static ParseStatus
+parse_literal (GScanner *scanner, ViviCodeValue **value)
+{
+  int i;
+  ParseStatus status;
+  ParseValueFunction functions[] = {
+    parse_null_literal,
+    parse_boolean_literal,
+    parse_numeric_literal,
+    parse_string_literal,
+    NULL
+  };
+
+  *value = NULL;
+
+  for (i = 0; functions[i] != NULL; i++) {
+    status = functions[i] (scanner, value);
+    if (status != STATUS_CANCEL)
+      return status;
+  }
+
+  return STATUS_CANCEL;
+}
+
+static ParseStatus
 parse_identifier (GScanner *scanner, ViviCodeValue **value)
 {
   *value = NULL;
@@ -240,6 +287,74 @@ parse_identifier (GScanner *scanner, ViviCodeValue **value)
   return STATUS_OK;
 }
 
+static ParseStatus
+parse_property_name (GScanner *scanner, ViviCodeValue **value)
+{
+  int i;
+  ParseStatus status;
+  ParseValueFunction functions[] = {
+    parse_identifier,
+    parse_string_literal,
+    parse_numeric_literal,
+    NULL
+  };
+
+  *value = NULL;
+
+  for (i = 0; functions[i] != NULL; i++) {
+    status = functions[i] (scanner, value);
+    if (status != STATUS_CANCEL)
+      return status;
+  }
+
+  return STATUS_CANCEL;
+}
+
+// FIXME
+static ParseStatus
+parse_operator_expression (GScanner *scanner, ViviCodeValue **value);
+
+static ParseStatus
+parse_object_literal (GScanner *scanner, ViviCodeValue **value)
+{
+  *value = NULL;
+
+  if (!check_token (scanner, '{'))
+    return STATUS_CANCEL;
+
+  *value = vivi_code_init_object_new ();
+
+  if (!check_token (scanner, '}')) {
+    do {
+      ViviCodeValue *property, *initializer;
+
+      if (parse_property_name (scanner, &property) != STATUS_OK)
+	goto fail;
+
+      if (!check_token (scanner, ':'))
+	goto fail;
+
+      // FIXME
+      if (parse_operator_expression (scanner, &initializer) != STATUS_OK)
+	goto fail;
+
+      vivi_code_init_object_add_variable (VIVI_CODE_INIT_OBJECT (*value),
+	  property, initializer);
+    } while (check_token (scanner, ','));
+  }
+
+  if (!check_token (scanner, '}'))
+    goto fail;
+
+  return STATUS_OK;
+
+fail:
+
+  g_object_unref (*value);
+  *value = NULL;
+  return STATUS_FAIL;
+}
+
 // misc
 
 static ParseStatus
@@ -279,7 +394,7 @@ parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
     parse_identifier,
     parse_literal,
     //parse_array_literal,
-    //parse_object_literal,
+    parse_object_literal,
     NULL
   };
 
commit 0ac05be76f6d160b1f51f4096e8b16a71f267c6e
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sun Mar 30 02:35:56 2008 +0200

    Oops, fix a missing asterisk

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index c4b60c2..ca66429 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -760,7 +760,7 @@ parse_statement_list (GScanner *scanner, ParseStatementFunction function,
   *block = vivi_code_block_new ();
 
   do {
-    vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), statement);
+    vivi_code_block_add_statement (VIVI_CODE_BLOCK (*block), statement);
     g_object_unref (statement);
 
     if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
commit cb9d2d4c8a957872e1219c4a96f6c2a3c169cc9c
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sun Mar 30 02:27:54 2008 +0200

    Make parse_statement_list give ViviCodeBlock instead of an array of statements

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index fa7f2dd..c4b60c2 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -168,7 +168,7 @@ typedef ParseStatus (*ParseValueFunction) (GScanner *scanner, ViviCodeValue **va
 
 static ParseStatus
 parse_statement_list (GScanner *scanner, ParseStatementFunction function,
-    ViviCodeStatement ***list, guint separator);
+    ViviCodeStatement **statement, guint separator);
 static ParseStatus
 parse_value_list (GScanner *scanner, ParseValueFunction function,
     ViviCodeValue ***list, guint separator);
@@ -186,17 +186,6 @@ check_token (GScanner *scanner, guint token)
 }
 
 static void
-free_statement_list (ViviCodeStatement **list)
-{
-  int i;
-
-  for (i = 0; list[i] != NULL; i++) {
-    g_object_unref (list[i]);
-  }
-  g_free (list);
-}
-
-static void
 free_value_list (ViviCodeValue **list)
 {
   int i;
@@ -207,21 +196,6 @@ free_value_list (ViviCodeValue **list)
   g_free (list);
 }
 
-static ViviCodeStatement *
-create_block (ViviCodeStatement **list)
-{
-  ViviCodeBlock *block;
-  int i;
-
-  block = VIVI_CODE_BLOCK (vivi_code_block_new ());
-
-  for (i = 0; list[i] != NULL; i++) {
-    vivi_code_block_add_statement (block, list[i]);
-  }
-
-  return VIVI_CODE_STATEMENT (block);
-}
-
 // values
 
 static ParseStatus
@@ -542,20 +516,10 @@ parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement)
 static ParseStatus
 parse_expression (GScanner *scanner, ViviCodeStatement **statement)
 {
-  ViviCodeStatement **list;
-  ParseStatus status;
-
   *statement = NULL;
 
-  status =
-    parse_statement_list (scanner, parse_assignment_expression, &list, ',');
-  if (status != STATUS_OK)
-    return status;
-
-  *statement = create_block (list);
-  free_statement_list (list);
-
-  return STATUS_OK;
+  return parse_statement_list (scanner, parse_assignment_expression, statement,
+      ',');
 }
 
 // statement
@@ -603,8 +567,6 @@ parse_statement (GScanner *scanner, ViviCodeStatement **statement);
 static ParseStatus
 parse_block (GScanner *scanner, ViviCodeStatement **statement)
 {
-  ViviCodeStatement **list;
-
   *statement = NULL;
 
   if (!check_token (scanner, '{'))
@@ -612,49 +574,40 @@ parse_block (GScanner *scanner, ViviCodeStatement **statement)
 
   g_scanner_peek_next_token (scanner);
   if (scanner->next_token != '}') {
-    if (parse_statement_list (scanner, parse_statement, &list, G_TOKEN_NONE)
-	!= STATUS_OK)
+    if (parse_statement_list (scanner, parse_statement, statement,
+	  G_TOKEN_NONE) != STATUS_OK)
       return STATUS_FAIL;
   } else {
-    list = g_new0 (ViviCodeStatement *, 1);
+    *statement = vivi_code_block_new ();
   }
 
   if (!check_token (scanner, '}')) {
-    free_statement_list (list);
+    g_object_unref (*statement);
+    *statement = NULL;
     return STATUS_FAIL;
   }
 
-  *statement = create_block (list);
-  free_statement_list (list);
-
   return STATUS_OK;
 }
 
 static ParseStatus
 parse_variable_statement (GScanner *scanner, ViviCodeStatement **statement)
 {
-  ViviCodeStatement **list;
-  ParseStatus status;
-
   *statement = NULL;
 
-  if (!check_token (scanner, TOKEN_VAR)) {
+  if (!check_token (scanner, TOKEN_VAR))
     return STATUS_CANCEL;
-  }
 
-  status =
-    parse_statement_list (scanner, parse_variable_declaration, &list, ',');
-  if (status != STATUS_OK)
-    return status;
+  if (parse_statement_list (scanner, parse_variable_declaration, statement,
+	',') != STATUS_OK)
+    return STATUS_FAIL;
 
   if (!check_token (scanner, ';')) {
-    free_statement_list (list);
+    g_object_unref (*statement);
+    *statement = NULL;
     return STATUS_FAIL;
   }
 
-  *statement = create_block (list);
-  free_statement_list (list);
-
   return STATUS_OK;
 }
 
@@ -702,7 +655,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
   //ViviCodeStatement *function;
   ViviCodeValue *identifier;
   ViviCodeValue **arguments;
-  ViviCodeStatement **body;
+  ViviCodeStatement *body;
 
   *statement = NULL;
 
@@ -745,7 +698,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
   if (arguments != NULL)
     free_value_list (arguments);
   if (body != NULL)
-    free_statement_list (body);
+    g_object_unref (body);
 
   return STATUS_OK;
 
@@ -755,7 +708,7 @@ fail:
   if (arguments != NULL)
     free_value_list (arguments);
   if (body != NULL)
-    free_statement_list (body);
+    g_object_unref (body);
 
   return STATUS_FAIL;
 }
@@ -779,54 +732,47 @@ parse_source_element (GScanner *scanner, ViviCodeStatement **statement)
 static ParseStatus
 parse_program (GScanner *scanner, ViviCodeStatement **statement)
 {
-  ParseStatus status;
-  ViviCodeStatement **list;
-
   *statement = NULL;
 
-  status = parse_statement_list (scanner, parse_source_element, &list,
+  return parse_statement_list (scanner, parse_source_element, statement,
       G_TOKEN_NONE);
-  if (status != STATUS_OK)
-    return status;
-
-  *statement = create_block (list);
-
-  return STATUS_OK;
 }
 
 // parsing
 
 static ParseStatus
 parse_statement_list (GScanner *scanner, ParseStatementFunction function,
-    ViviCodeStatement ***list, guint separator)
+    ViviCodeStatement **block, guint separator)
 {
-  GPtrArray *array;
   ViviCodeStatement *statement;
   ParseStatus status;
 
   g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
   g_return_val_if_fail (function != NULL, STATUS_FAIL);
-  g_return_val_if_fail (list != NULL, STATUS_FAIL);
+  g_return_val_if_fail (block != NULL, STATUS_FAIL);
+
+  *block = NULL;
 
   status = function (scanner, &statement);
   if (status != STATUS_OK)
     return status;
 
-  array = g_ptr_array_new ();
+  *block = vivi_code_block_new ();
 
   do {
-    g_ptr_array_add (array, statement);
+    vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), statement);
+    g_object_unref (statement);
 
     if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
       break;
 
     status = function (scanner, &statement);
-    if (status == STATUS_FAIL)
+    if (status == STATUS_FAIL) {
+      g_object_unref (*block);
+      *block = NULL;
       return STATUS_FAIL;
+    }
   } while (status == STATUS_OK);
-  g_ptr_array_add (array, NULL);
-
-  *list = (ViviCodeStatement **)g_ptr_array_free (array, FALSE);
 
   return STATUS_OK;
 }
commit 110f3e73417235ea2a30f826b3368bd7df82d77d
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sun Mar 30 02:15:03 2008 +0200

    parse_statement_symbol can now be called parse_statement

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 481b487..fa7f2dd 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -598,7 +598,7 @@ parse_empty_statement (GScanner *scanner, ViviCodeStatement **statement)
 }
 
 static ParseStatus
-parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement);
+parse_statement (GScanner *scanner, ViviCodeStatement **statement);
 
 static ParseStatus
 parse_block (GScanner *scanner, ViviCodeStatement **statement)
@@ -612,8 +612,8 @@ parse_block (GScanner *scanner, ViviCodeStatement **statement)
 
   g_scanner_peek_next_token (scanner);
   if (scanner->next_token != '}') {
-    if (parse_statement_list (scanner, parse_statement_symbol, &list,
-	  G_TOKEN_NONE) != STATUS_OK)
+    if (parse_statement_list (scanner, parse_statement, &list, G_TOKEN_NONE)
+	!= STATUS_OK)
       return STATUS_FAIL;
   } else {
     list = g_new0 (ViviCodeStatement *, 1);
@@ -659,7 +659,7 @@ parse_variable_statement (GScanner *scanner, ViviCodeStatement **statement)
 }
 
 static ParseStatus
-parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement)
+parse_statement (GScanner *scanner, ViviCodeStatement **statement)
 {
   int i, status;
   ParseStatementFunction functions[] = {
@@ -771,7 +771,7 @@ parse_source_element (GScanner *scanner, ViviCodeStatement **statement)
 
   status = parse_function_declaration (scanner, statement);
   if (status == STATUS_CANCEL)
-    status = parse_statement_symbol (scanner, statement);
+    status = parse_statement (scanner, statement);
 
   return status;
 }
commit db25fcdf7b424e81a9ada1cae588d5e54f9a6f54
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sun Mar 30 02:13:52 2008 +0200

    Make parse_value_list and parse_statement_list take function instead of symbol
    
    Got rid of the whole symbol definitions

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index c9c7f24..481b487 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -163,69 +163,14 @@ static const TokenDescription custom_tokens[] = {
   { G_TOKEN_NONE, NULL }
 };
 
-typedef enum {
-  SYMBOL_NONE,
-  // top
-  SYMBOL_PROGRAM,
-  SYMBOL_SOURCE_ELEMENT,
-  // function
-  SYMBOL_FUNCTION_DECLARATION,
-  // statement
-  SYMBOL_STATEMENT,
-  SYMBOL_BLOCK,
-  SYMBOL_VARIABLE_STATEMENT,
-  SYMBOL_EMPTY_STATEMENT,
-  SYMBOL_EXPRESSION_STATEMENT,
-  SYMBOL_IF_STATEMENT,
-  SYMBOL_ITERATION_STATEMENT,
-  SYMBOL_CONTINUE_STATEMENT,
-  SYMBOL_BREAK_STATEMENT,
-  SYMBOL_RETURN_STATEMENT,
-  SYMBOL_WITH_STATEMENT,
-  SYMBOL_LABELLED_STATEMENT,
-  SYMBOL_SWITCH_STATEMENT,
-  SYMBOL_THROW_STATEMENT,
-  SYMBOL_TRY_STATEMENT,
-  // expression
-  SYMBOL_EXPRESSION,
-  SYMBOL_ASSIGNMENT_EXPRESSION,
-  SYMBOL_CONDITIONAL_EXPRESSION,
-  SYMBOL_LEFT_HAND_SIDE_EXPRESSION,
-  SYMBOL_OPERATOR_EXPRESSION,
-  SYMBOL_UNARY_EXPRESSION,
-  SYMBOL_POSTFIX_EXPRESSION,
-  SYMBOL_NEW_EXPRESSION,
-  SYMBOL_CALL_EXPRESSION,
-  SYMBOL_MEMBER_EXPRESSION,
-  SYMBOL_FUNCTION_EXPRESSION,
-  SYMBOL_PRIMARY_EXPRESSION,
-  // values
-  SYMBOL_IDENTIFIER,
-  SYMBOL_LITERAL,
-  SYMBOL_ARRAY_LITERAL,
-  SYMBOL_OBJECT_LITERAL,
-  // misc
-  SYMBOL_VARIABLE_DECLARATION,
-  SYMBOL_ASSIGNMENT_OPERATOR,
-  SYMBOL_ARGUMENTS,
-} ParseSymbol;
-
 typedef ParseStatus (*ParseStatementFunction) (GScanner *scanner, ViviCodeStatement **statement);
 typedef ParseStatus (*ParseValueFunction) (GScanner *scanner, ViviCodeValue **value);
 
 static ParseStatus
-parse_statement (GScanner *scanner, ParseSymbol symbol,
-    ViviCodeStatement **statement);
-
-static ParseStatus
-parse_value (GScanner *scanner, ParseSymbol symbol, ViviCodeValue **value);
-
-static ParseStatus
-parse_statement_list (GScanner *scanner, ParseSymbol symbol,
+parse_statement_list (GScanner *scanner, ParseStatementFunction function,
     ViviCodeStatement ***list, guint separator);
-
 static ParseStatus
-parse_value_list (GScanner *scanner, ParseSymbol symbol,
+parse_value_list (GScanner *scanner, ParseValueFunction function,
     ViviCodeValue ***list, guint separator);
 
 // helpers
@@ -603,7 +548,7 @@ parse_expression (GScanner *scanner, ViviCodeStatement **statement)
   *statement = NULL;
 
   status =
-    parse_statement_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
+    parse_statement_list (scanner, parse_assignment_expression, &list, ',');
   if (status != STATUS_OK)
     return status;
 
@@ -653,6 +598,9 @@ parse_empty_statement (GScanner *scanner, ViviCodeStatement **statement)
 }
 
 static ParseStatus
+parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement);
+
+static ParseStatus
 parse_block (GScanner *scanner, ViviCodeStatement **statement)
 {
   ViviCodeStatement **list;
@@ -664,8 +612,8 @@ parse_block (GScanner *scanner, ViviCodeStatement **statement)
 
   g_scanner_peek_next_token (scanner);
   if (scanner->next_token != '}') {
-    if (parse_statement_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
-	!= STATUS_OK)
+    if (parse_statement_list (scanner, parse_statement_symbol, &list,
+	  G_TOKEN_NONE) != STATUS_OK)
       return STATUS_FAIL;
   } else {
     list = g_new0 (ViviCodeStatement *, 1);
@@ -695,7 +643,7 @@ parse_variable_statement (GScanner *scanner, ViviCodeStatement **statement)
   }
 
   status =
-    parse_statement_list (scanner, SYMBOL_VARIABLE_DECLARATION, &list, ',');
+    parse_statement_list (scanner, parse_variable_declaration, &list, ',');
   if (status != STATUS_OK)
     return status;
 
@@ -746,6 +694,9 @@ parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement)
 // function
 
 static ParseStatus
+parse_source_element (GScanner *scanner, ViviCodeStatement **statement);
+
+static ParseStatus
 parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
 {
   //ViviCodeStatement *function;
@@ -768,7 +719,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
   if (!check_token (scanner, '('))
     goto fail;
 
-  if (parse_value_list (scanner, SYMBOL_IDENTIFIER, &arguments, ',') ==
+  if (parse_value_list (scanner, parse_identifier, &arguments, ',') ==
       STATUS_FAIL)
     goto fail;
 
@@ -778,7 +729,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
   if (!check_token (scanner, '{'))
     goto fail;
 
-  if (parse_statement_list (scanner, SYMBOL_SOURCE_ELEMENT, &body, G_TOKEN_NONE)
+  if (parse_statement_list (scanner, parse_source_element, &body, G_TOKEN_NONE)
       == STATUS_FAIL)
     goto fail;
 
@@ -833,7 +784,7 @@ parse_program (GScanner *scanner, ViviCodeStatement **statement)
 
   *statement = NULL;
 
-  status = parse_statement_list (scanner, SYMBOL_SOURCE_ELEMENT, &list,
+  status = parse_statement_list (scanner, parse_source_element, &list,
       G_TOKEN_NONE);
   if (status != STATUS_OK)
     return status;
@@ -845,119 +796,8 @@ parse_program (GScanner *scanner, ViviCodeStatement **statement)
 
 // parsing
 
-typedef struct {
-  ParseSymbol			id;
-  const char *			name;
-  ParseStatementFunction	parse;
-} SymbolStatementFunctionList;
-
-static const SymbolStatementFunctionList statement_symbols[] = {
-  // top
-  { SYMBOL_PROGRAM, "Program", parse_program },
-  { SYMBOL_SOURCE_ELEMENT, "SourceElement", parse_source_element },
-  // function
-  { SYMBOL_FUNCTION_DECLARATION, "FunctionDeclaration",
-    parse_function_declaration },
-  // statement
-  { SYMBOL_STATEMENT, "Statement", parse_statement_symbol },
-  { SYMBOL_BLOCK, "Block", parse_block },
-  { SYMBOL_VARIABLE_STATEMENT, "VariableStatement", parse_variable_statement },
-  { SYMBOL_EMPTY_STATEMENT, "EmptyStatement", parse_empty_statement },
-  { SYMBOL_EXPRESSION_STATEMENT, "ExpressionStatement",
-    parse_expression_statement },
-  /*{ SYMBOL_IF_STATEMENT, "IfStatement", parse_if_statement },
-  { SYMBOL_ITERATION_STATEMENT, "IterationStatement",
-    parse_iteration_statement },
-  { SYMBOL_CONTINUE_STATEMENT, "ContinueStatement", parse_continue_statement },
-  { SYMBOL_BREAK_STATEMENT, "BreakStatement", parse_break_statement },
-  { SYMBOL_RETURN_STATEMENT, "ReturnStatement", parse_return_statement },
-  { SYMBOL_WITH_STATEMENT, "WithStatement", parse_with_statement },
-  { SYMBOL_LABELLED_STATEMENT, "LabelledStatement", parse_labelled_statement },
-  { SYMBOL_SWITCH_STATEMENT, "SwitchStatement", parse_switch_statement },
-  { SYMBOL_THROW_STATEMENT, "ThrowStatement", parse_throw_statement },
-  { SYMBOL_TRY_STATEMENT, "TryStatement", parse_try_statement },*/
-  // expression
-  { SYMBOL_EXPRESSION, "Expression", parse_expression },
-  { SYMBOL_ASSIGNMENT_EXPRESSION, "AssigmentExpression",
-    parse_assignment_expression },
-  { SYMBOL_CONDITIONAL_EXPRESSION, "ConditionalExpression",
-    parse_conditional_expression },
-  // misc
-  { SYMBOL_VARIABLE_DECLARATION, "VariableDeclaration",
-    parse_variable_declaration },
-  { SYMBOL_NONE, NULL, NULL }
-};
-
-typedef struct {
-  ParseSymbol			id;
-  const char *			name;
-  ParseValueFunction		parse;
-} SymbolValueFunctionList;
-
-static const SymbolValueFunctionList value_symbols[] = {
-  // expression
-  { SYMBOL_OPERATOR_EXPRESSION, "OperatorExpression",
-    parse_operator_expression },
-  { SYMBOL_UNARY_EXPRESSION, "UnaryExpression", parse_unary_expression },
-  { SYMBOL_POSTFIX_EXPRESSION, "PostfixExpression", parse_postfix_expression },
-  { SYMBOL_LEFT_HAND_SIDE_EXPRESSION, "LeftHandSideExpression",
-    parse_left_hand_side_expression },
-  { SYMBOL_NEW_EXPRESSION, "NewExpression", parse_new_expression },
-  { SYMBOL_MEMBER_EXPRESSION, "MemberExpression", parse_member_expression },
-  { SYMBOL_PRIMARY_EXPRESSION, "PrimaryExpression", parse_primary_expression },
-  // value
-  { SYMBOL_IDENTIFIER, "Identifier", parse_identifier },
-  { SYMBOL_LITERAL, "Literal", parse_literal },
-  { SYMBOL_NONE, NULL, NULL }
-};
-
-static ParseStatus
-parse_statement (GScanner *scanner, ParseSymbol symbol,
-    ViviCodeStatement **statement)
-{
-  int i;
-
-  g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
-  g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
-  g_return_val_if_fail (statement != NULL, STATUS_FAIL);
-
-  for (i = 0; statement_symbols[i].id != SYMBOL_NONE; i++) {
-    if (statement_symbols[i].id == symbol) {
-      ParseStatus status = statement_symbols[i].parse (scanner, statement);
-      g_assert ((status == STATUS_OK && VIVI_IS_CODE_TOKEN (*statement)) ||
-	  (status != STATUS_OK && *statement == NULL));
-      return status;
-    }
-  }
-
-  //g_assert_not_reached ();
-  return STATUS_CANCEL;
-}
-
-static ParseStatus
-parse_value (GScanner *scanner, ParseSymbol symbol, ViviCodeValue **value)
-{
-  int i;
-
-  g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
-  g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
-  g_return_val_if_fail (value != NULL, STATUS_FAIL);
-
-  for (i = 0; value_symbols[i].id != SYMBOL_NONE; i++) {
-    if (value_symbols[i].id == symbol) {
-      ParseStatus status = value_symbols[i].parse (scanner, value);
-      g_assert ((status == STATUS_OK && VIVI_IS_CODE_TOKEN (*value)) ||
-	  (status != STATUS_OK && *value == NULL));
-      return status;
-    }
-  }
-
-  //g_assert_not_reached ();
-  return STATUS_CANCEL;
-}
-
 static ParseStatus
-parse_statement_list (GScanner *scanner, ParseSymbol symbol,
+parse_statement_list (GScanner *scanner, ParseStatementFunction function,
     ViviCodeStatement ***list, guint separator)
 {
   GPtrArray *array;
@@ -965,10 +805,10 @@ parse_statement_list (GScanner *scanner, ParseSymbol symbol,
   ParseStatus status;
 
   g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
-  g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
+  g_return_val_if_fail (function != NULL, STATUS_FAIL);
   g_return_val_if_fail (list != NULL, STATUS_FAIL);
 
-  status = parse_statement (scanner, symbol, &statement);
+  status = function (scanner, &statement);
   if (status != STATUS_OK)
     return status;
 
@@ -980,7 +820,7 @@ parse_statement_list (GScanner *scanner, ParseSymbol symbol,
     if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
       break;
 
-    status = parse_statement (scanner, symbol, &statement);
+    status = function (scanner, &statement);
     if (status == STATUS_FAIL)
       return STATUS_FAIL;
   } while (status == STATUS_OK);
@@ -992,18 +832,18 @@ parse_statement_list (GScanner *scanner, ParseSymbol symbol,
 }
 
 static ParseStatus
-parse_value_list (GScanner *scanner, ParseSymbol symbol, ViviCodeValue ***list,
-    guint separator)
+parse_value_list (GScanner *scanner, ParseValueFunction function,
+    ViviCodeValue ***list, guint separator)
 {
   GPtrArray *array;
   ViviCodeValue *value;
   ParseStatus status;
 
   g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
-  g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
+  g_return_val_if_fail (function != NULL, STATUS_FAIL);
   g_return_val_if_fail (list != NULL, STATUS_FAIL);
 
-  status = parse_value (scanner, symbol, &value);
+  status = function (scanner, &value);
   if (status != STATUS_OK)
     return status;
 
@@ -1015,7 +855,7 @@ parse_value_list (GScanner *scanner, ParseSymbol symbol, ViviCodeValue ***list,
     if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
       break;
 
-    status = parse_value (scanner, symbol, &value);
+    status = function (scanner, &value);
     if (status == STATUS_FAIL)
       return STATUS_FAIL;
   } while (status == STATUS_OK);
@@ -1059,7 +899,7 @@ vivi_compile_text (const char *text, gsize len, const char *input_name)
   scanner->input_name = input_name;
   g_scanner_input_text (scanner, text, len);
 
-  status = parse_statement (scanner, SYMBOL_PROGRAM, &statement);
+  status = parse_program (scanner, &statement);
   g_assert ((status == STATUS_OK && VIVI_IS_CODE_STATEMENT (statement)) ||
 	(status != STATUS_OK && statement == NULL));
 
commit 8daea1d58c670d413e26640187741b359c6c5dc0
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sun Mar 30 02:06:49 2008 +0200

    Don't use the parse_statment and parse_value functions, but call directly

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 6746ff6..c9c7f24 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -332,7 +332,7 @@ parse_variable_declaration (GScanner *scanner, ViviCodeStatement **statement)
 
   *statement = NULL;
 
-  status = parse_value (scanner, SYMBOL_IDENTIFIER, &identifier);
+  status = parse_identifier (scanner, &identifier);
   if (status != STATUS_OK)
     return status;
 
@@ -356,12 +356,12 @@ parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
 {
   int i;
   ParseStatus status;
-  ParseSymbol options[] = {
-    SYMBOL_IDENTIFIER,
-    SYMBOL_LITERAL,
-    SYMBOL_ARRAY_LITERAL,
-    SYMBOL_OBJECT_LITERAL,
-    SYMBOL_NONE
+  ParseValueFunction functions[] = {
+    parse_identifier,
+    parse_literal,
+    //parse_array_literal,
+    //parse_object_literal,
+    NULL
   };
 
   *value = NULL;
@@ -375,8 +375,8 @@ parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
     return STATUS_OK;
   }*/
 
-  for (i = 0; options[i] != SYMBOL_NONE; i++) {
-    status = parse_value (scanner, options[i], value);
+  for (i = 0; functions[i] != NULL; i++) {
+    status = functions[i] (scanner, value);
     if (status != STATUS_CANCEL)
       return status;
   }
@@ -392,9 +392,9 @@ parse_member_expression (GScanner *scanner, ViviCodeValue **value)
 
   // TODO: new MemberExpression Arguments
 
-  status = parse_value (scanner, SYMBOL_PRIMARY_EXPRESSION, value);
-  if (status == STATUS_CANCEL)
-    status = parse_value (scanner, SYMBOL_FUNCTION_EXPRESSION, value);
+  status = parse_primary_expression (scanner, value);
+  //if (status == STATUS_CANCEL)
+  //  status = parse_function_expression (scanner, value);
 
   if (status != 0)
     return status;
@@ -402,13 +402,14 @@ parse_member_expression (GScanner *scanner, ViviCodeValue **value)
   do {
     ViviCodeValue *tmp;
 
-    if (check_token (scanner, '[')) {
-      if (parse_value (scanner, SYMBOL_EXPRESSION, &member) != STATUS_OK)
+    /*if (check_token (scanner, '[')) {
+      if (parse_expression (scanner, &member) != STATUS_OK)
 	return STATUS_FAIL;
       if (!check_token (scanner, ']'))
 	return STATUS_FAIL;
-    } else if (check_token (scanner, '.')) {
-      if (parse_value (scanner, SYMBOL_IDENTIFIER, &member) != STATUS_OK)
+    } else*/
+    if (check_token (scanner, '.')) {
+      if (parse_identifier (scanner, &member) != STATUS_OK)
 	return STATUS_FAIL;
     } else {
       return STATUS_OK;
@@ -430,7 +431,7 @@ parse_new_expression (GScanner *scanner, ViviCodeValue **value)
   *value = NULL;
 
   if (check_token (scanner, TOKEN_NEW)) {
-    if (parse_value (scanner, SYMBOL_NEW_EXPRESSION, value) != STATUS_OK)
+    if (parse_new_expression (scanner, value) != STATUS_OK)
       return STATUS_FAIL;
     if (!VIVI_IS_CODE_FUNCTION_CALL (*value)) {
       ViviCodeValue *tmp = VIVI_CODE_VALUE (*value);
@@ -441,7 +442,7 @@ parse_new_expression (GScanner *scanner, ViviCodeValue **value)
 	TRUE);
     return STATUS_OK;
   } else {
-    return parse_value (scanner, SYMBOL_MEMBER_EXPRESSION, value);
+    return parse_member_expression (scanner, value);
   }
 }
 
@@ -452,9 +453,9 @@ parse_left_hand_side_expression (GScanner *scanner, ViviCodeValue **value)
 
   *value = NULL;
 
-  status = parse_value (scanner, SYMBOL_NEW_EXPRESSION, value);
-  if (status == STATUS_CANCEL)
-    status = parse_value (scanner, SYMBOL_CALL_EXPRESSION, value);
+  status = parse_new_expression (scanner, value);
+  //if (status == STATUS_CANCEL)
+  //  status = parse_call_expression (scanner, value);
 
   return status;
 }
@@ -464,7 +465,7 @@ parse_postfix_expression (GScanner *scanner, ViviCodeValue **value)
 {
   ParseStatus status;
 
-  status = parse_value (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION, value);
+  status = parse_left_hand_side_expression (scanner, value);
   if (status != STATUS_OK)
     return status;
 
@@ -487,13 +488,13 @@ parse_unary_expression (GScanner *scanner, ViviCodeValue **value)
   *value = NULL;
 
   if (check_token (scanner, '!')) {
-    parse_value (scanner, SYMBOL_UNARY_EXPRESSION, value);
+    parse_unary_expression (scanner, value);
     tmp = VIVI_CODE_VALUE (*value);
     *value = vivi_code_unary_new (tmp, '!');
     g_object_unref (tmp);
     return STATUS_OK;
   } else {
-    return parse_value (scanner, SYMBOL_POSTFIX_EXPRESSION, value);
+    return parse_postfix_expression (scanner, value);
   }
 }
 
@@ -506,7 +507,7 @@ parse_operator_expression (GScanner *scanner, ViviCodeValue **value)
 
   *value = NULL;
 
-  status = parse_value (scanner, SYMBOL_UNARY_EXPRESSION, value);
+  status = parse_unary_expression (scanner, value);
   if (status != STATUS_OK)
     return status;
 
@@ -514,7 +515,7 @@ parse_operator_expression (GScanner *scanner, ViviCodeValue **value)
     if (!check_token (scanner, '+'))
       return STATUS_OK;
 
-    if (parse_value (scanner, SYMBOL_UNARY_EXPRESSION, &right) != STATUS_OK) {
+    if (parse_unary_expression (scanner, &right) != STATUS_OK) {
       g_object_unref (*value);
       *value = NULL;
       return STATUS_FAIL;
@@ -533,6 +534,9 @@ parse_operator_expression (GScanner *scanner, ViviCodeValue **value)
 }
 
 static ParseStatus
+parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement);
+
+static ParseStatus
 parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
 {
   ParseStatus status;
@@ -542,7 +546,7 @@ parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
   *statement = NULL;
   if_statement = NULL;
 
-  status = parse_value (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
+  status = parse_operator_expression (scanner, &value);
   if (status != STATUS_OK)
     return status;
 
@@ -552,15 +556,13 @@ parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
     return STATUS_OK;
   }
 
-  if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &if_statement) !=
-      STATUS_OK)
+  if (parse_assignment_expression (scanner, &if_statement) != STATUS_OK)
     goto fail;
 
   if (!check_token (scanner, ':'))
     goto fail;
 
-  if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION,
-	&else_statement) != STATUS_OK)
+  if (parse_assignment_expression (scanner, &else_statement) != STATUS_OK)
     goto fail;
 
   *statement = vivi_code_if_new (value);
@@ -589,7 +591,7 @@ parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement)
 
   // TODO
 
-  return parse_statement (scanner, SYMBOL_CONDITIONAL_EXPRESSION, statement);
+  return parse_conditional_expression (scanner, statement);
 }
 
 static ParseStatus
@@ -624,7 +626,7 @@ parse_expression_statement (GScanner *scanner, ViviCodeStatement **statement)
   if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
     return STATUS_CANCEL;
 
-  status = parse_statement (scanner, SYMBOL_EXPRESSION, statement);
+  status = parse_expression (scanner, statement);
   if (status != STATUS_OK)
     return status;
 
@@ -712,28 +714,28 @@ static ParseStatus
 parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement)
 {
   int i, status;
-  ParseSymbol options[] = {
-    SYMBOL_BLOCK,
-    SYMBOL_VARIABLE_STATEMENT,
-    SYMBOL_EMPTY_STATEMENT,
-    SYMBOL_EXPRESSION_STATEMENT,
-    SYMBOL_IF_STATEMENT,
-    SYMBOL_ITERATION_STATEMENT,
-    SYMBOL_CONTINUE_STATEMENT,
-    SYMBOL_BREAK_STATEMENT,
-    SYMBOL_RETURN_STATEMENT,
-    SYMBOL_WITH_STATEMENT,
-    SYMBOL_LABELLED_STATEMENT,
-    SYMBOL_SWITCH_STATEMENT,
-    SYMBOL_THROW_STATEMENT,
-    SYMBOL_TRY_STATEMENT,
-    SYMBOL_NONE
+  ParseStatementFunction functions[] = {
+    parse_block,
+    parse_variable_statement,
+    parse_empty_statement,
+    parse_expression_statement,
+    //parse_if_statement,
+    //parse_iteration_statement,
+    //parse_continue_statement,
+    //parse_break_statement,
+    //parse_return_statement,
+    //parse_with_statement,
+    //parse_labelled_statement,
+    //parse_switch_statement,
+    //parse_throw_statement,
+    //parse_try_statement,
+    NULL
   };
 
   *statement = NULL;
 
-  for (i = 0; options[i] != SYMBOL_NONE; i++) {
-    status = parse_statement (scanner, options[i], statement);
+  for (i = 0; functions[i] != NULL; i++) {
+    status = functions[i] (scanner, statement);
     if (status != STATUS_CANCEL)
       return status;
   }
@@ -760,7 +762,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
   if (!check_token (scanner, TOKEN_FUNCTION))
     return STATUS_CANCEL;
 
-  if (parse_value (scanner, SYMBOL_IDENTIFIER, &identifier) != STATUS_OK)
+  if (parse_identifier (scanner, &identifier) != STATUS_OK)
     return STATUS_FAIL;
 
   if (!check_token (scanner, '('))
@@ -816,10 +818,9 @@ parse_source_element (GScanner *scanner, ViviCodeStatement **statement)
 
   *statement = NULL;
 
-  status = parse_statement (scanner, SYMBOL_FUNCTION_DECLARATION, statement);
-
+  status = parse_function_declaration (scanner, statement);
   if (status == STATUS_CANCEL)
-    status = parse_statement (scanner, SYMBOL_STATEMENT, statement);
+    status = parse_statement_symbol (scanner, statement);
 
   return status;
 }
commit a31beb32b65b89b5944df8ea40bdd4d7a2c2710b
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sun Mar 30 01:54:40 2008 +0200

    Reorder some more functions in the compiler code

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 12db713..6746ff6 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -321,6 +321,296 @@ parse_identifier (GScanner *scanner, ViviCodeValue **value)
   return STATUS_OK;
 }
 
+// misc
+
+static ParseStatus
+parse_variable_declaration (GScanner *scanner, ViviCodeStatement **statement)
+{
+  ParseStatus status;
+  ViviCodeValue *identifier;
+  ViviCodeValue *value;
+
+  *statement = NULL;
+
+  status = parse_value (scanner, SYMBOL_IDENTIFIER, &identifier);
+  if (status != STATUS_OK)
+    return status;
+
+  if (check_token (scanner, '=')) {
+    // TODO
+    return STATUS_FAIL;
+  } else {
+    value = vivi_code_constant_new_undefined ();
+  }
+
+  *statement = vivi_code_assignment_new (NULL, identifier, value);
+  vivi_code_assignment_set_local (VIVI_CODE_ASSIGNMENT (*statement), TRUE);
+
+  return STATUS_OK;
+}
+
+// expression
+
+static ParseStatus
+parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
+{
+  int i;
+  ParseStatus status;
+  ParseSymbol options[] = {
+    SYMBOL_IDENTIFIER,
+    SYMBOL_LITERAL,
+    SYMBOL_ARRAY_LITERAL,
+    SYMBOL_OBJECT_LITERAL,
+    SYMBOL_NONE
+  };
+
+  *value = NULL;
+
+  if (check_token (scanner, TOKEN_THIS)) {
+    *value = vivi_code_get_new_name ("this");
+    return STATUS_OK;
+  }
+
+  /*if (check_token (scanner, '(')) {
+    return STATUS_OK;
+  }*/
+
+  for (i = 0; options[i] != SYMBOL_NONE; i++) {
+    status = parse_value (scanner, options[i], value);
+    if (status != STATUS_CANCEL)
+      return status;
+  }
+
+  return STATUS_CANCEL;
+}
+
+static ParseStatus
+parse_member_expression (GScanner *scanner, ViviCodeValue **value)
+{
+  ParseStatus status;
+  ViviCodeValue *member;
+
+  // TODO: new MemberExpression Arguments
+
+  status = parse_value (scanner, SYMBOL_PRIMARY_EXPRESSION, value);
+  if (status == STATUS_CANCEL)
+    status = parse_value (scanner, SYMBOL_FUNCTION_EXPRESSION, value);
+
+  if (status != 0)
+    return status;
+
+  do {
+    ViviCodeValue *tmp;
+
+    if (check_token (scanner, '[')) {
+      if (parse_value (scanner, SYMBOL_EXPRESSION, &member) != STATUS_OK)
+	return STATUS_FAIL;
+      if (!check_token (scanner, ']'))
+	return STATUS_FAIL;
+    } else if (check_token (scanner, '.')) {
+      if (parse_value (scanner, SYMBOL_IDENTIFIER, &member) != STATUS_OK)
+	return STATUS_FAIL;
+    } else {
+      return STATUS_OK;
+    }
+
+    tmp = *value;
+    *value = vivi_code_get_new (tmp, VIVI_CODE_VALUE (member));
+    g_object_unref (tmp);
+    g_object_unref (member);
+  } while (TRUE);
+
+  g_assert_not_reached ();
+  return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_new_expression (GScanner *scanner, ViviCodeValue **value)
+{
+  *value = NULL;
+
+  if (check_token (scanner, TOKEN_NEW)) {
+    if (parse_value (scanner, SYMBOL_NEW_EXPRESSION, value) != STATUS_OK)
+      return STATUS_FAIL;
+    if (!VIVI_IS_CODE_FUNCTION_CALL (*value)) {
+      ViviCodeValue *tmp = VIVI_CODE_VALUE (*value);
+      *value = vivi_code_function_call_new (NULL, tmp);
+      g_object_unref (tmp);
+    }
+    vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*value),
+	TRUE);
+    return STATUS_OK;
+  } else {
+    return parse_value (scanner, SYMBOL_MEMBER_EXPRESSION, value);
+  }
+}
+
+static ParseStatus
+parse_left_hand_side_expression (GScanner *scanner, ViviCodeValue **value)
+{
+  ParseStatus status;
+
+  *value = NULL;
+
+  status = parse_value (scanner, SYMBOL_NEW_EXPRESSION, value);
+  if (status == STATUS_CANCEL)
+    status = parse_value (scanner, SYMBOL_CALL_EXPRESSION, value);
+
+  return status;
+}
+
+static ParseStatus
+parse_postfix_expression (GScanner *scanner, ViviCodeValue **value)
+{
+  ParseStatus status;
+
+  status = parse_value (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION, value);
+  if (status != STATUS_OK)
+    return status;
+
+  // FIXME: Don't allow new line here
+
+  /*if (check_token (scanner, TOKEN_PLUSPLUS)) {
+    ViviCodeValue *tmp = *value;
+    *value = vivi_code_postfix_new (tmp, "++");
+    g_object_unref (tmp);
+  } else {*/
+    return STATUS_OK;
+  //}
+}
+
+static ParseStatus
+parse_unary_expression (GScanner *scanner, ViviCodeValue **value)
+{
+  ViviCodeValue *tmp;
+
+  *value = NULL;
+
+  if (check_token (scanner, '!')) {
+    parse_value (scanner, SYMBOL_UNARY_EXPRESSION, value);
+    tmp = VIVI_CODE_VALUE (*value);
+    *value = vivi_code_unary_new (tmp, '!');
+    g_object_unref (tmp);
+    return STATUS_OK;
+  } else {
+    return parse_value (scanner, SYMBOL_POSTFIX_EXPRESSION, value);
+  }
+}
+
+static ParseStatus
+parse_operator_expression (GScanner *scanner, ViviCodeValue **value)
+{
+  ParseStatus status;
+  ViviCodeValue *left;
+  ViviCodeValue *right;
+
+  *value = NULL;
+
+  status = parse_value (scanner, SYMBOL_UNARY_EXPRESSION, value);
+  if (status != STATUS_OK)
+    return status;
+
+  do {
+    if (!check_token (scanner, '+'))
+      return STATUS_OK;
+
+    if (parse_value (scanner, SYMBOL_UNARY_EXPRESSION, &right) != STATUS_OK) {
+      g_object_unref (*value);
+      *value = NULL;
+      return STATUS_FAIL;
+    }
+
+    left = VIVI_CODE_VALUE (*value);
+    *value = vivi_code_binary_new_name (left, VIVI_CODE_VALUE (right), "+");
+    g_object_unref (left);
+    g_object_unref (right);
+  } while (TRUE);
+
+  g_object_unref (*value);
+  *value = NULL;
+
+  return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
+{
+  ParseStatus status;
+  ViviCodeValue *value;
+  ViviCodeStatement *if_statement, *else_statement;
+
+  *statement = NULL;
+  if_statement = NULL;
+
+  status = parse_value (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
+  if (status != STATUS_OK)
+    return status;
+
+  if (!check_token (scanner, '?')) {
+    *statement = vivi_code_value_statement_new (VIVI_CODE_VALUE (value));
+    g_object_unref (value);
+    return STATUS_OK;
+  }
+
+  if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &if_statement) !=
+      STATUS_OK)
+    goto fail;
+
+  if (!check_token (scanner, ':'))
+    goto fail;
+
+  if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION,
+	&else_statement) != STATUS_OK)
+    goto fail;
+
+  *statement = vivi_code_if_new (value);
+  vivi_code_if_set_if (VIVI_CODE_IF (*statement), if_statement);
+  vivi_code_if_set_else (VIVI_CODE_IF (*statement), else_statement);
+
+  g_object_unref (value);
+  g_object_unref (if_statement);
+  g_object_unref (else_statement);
+
+  return STATUS_OK;
+
+fail:
+
+  g_object_unref (value);
+  if (if_statement != NULL)
+    g_object_unref (if_statement);
+
+  return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement)
+{
+  *statement = NULL;
+
+  // TODO
+
+  return parse_statement (scanner, SYMBOL_CONDITIONAL_EXPRESSION, statement);
+}
+
+static ParseStatus
+parse_expression (GScanner *scanner, ViviCodeStatement **statement)
+{
+  ViviCodeStatement **list;
+  ParseStatus status;
+
+  *statement = NULL;
+
+  status =
+    parse_statement_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
+  if (status != STATUS_OK)
+    return status;
+
+  *statement = create_block (list);
+  free_statement_list (list);
+
+  return STATUS_OK;
+}
+
 // statement
 
 static ParseStatus
@@ -418,12 +708,6 @@ parse_variable_statement (GScanner *scanner, ViviCodeStatement **statement)
   return STATUS_OK;
 }
 
-/*
- * if ((a = c) && (b = 1))
- *
- * a = c; if (a) { b = 1; if (b) }
- */
-
 static ParseStatus
 parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement)
 {
@@ -558,296 +842,6 @@ parse_program (GScanner *scanner, ViviCodeStatement **statement)
   return STATUS_OK;
 }
 
-// expression
-
-static ParseStatus
-parse_expression (GScanner *scanner, ViviCodeStatement **statement)
-{
-  ViviCodeStatement **list;
-  ParseStatus status;
-
-  *statement = NULL;
-
-  status =
-    parse_statement_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
-  if (status != STATUS_OK)
-    return status;
-
-  *statement = create_block (list);
-  free_statement_list (list);
-
-  return STATUS_OK;
-}
-
-static ParseStatus
-parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement)
-{
-  *statement = NULL;
-
-  // TODO
-
-  return parse_statement (scanner, SYMBOL_CONDITIONAL_EXPRESSION, statement);
-}
-
-static ParseStatus
-parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
-{
-  ParseStatus status;
-  ViviCodeValue *value;
-  ViviCodeStatement *if_statement, *else_statement;
-
-  *statement = NULL;
-  if_statement = NULL;
-
-  status = parse_value (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
-  if (status != STATUS_OK)
-    return status;
-
-  if (!check_token (scanner, '?')) {
-    *statement = vivi_code_value_statement_new (VIVI_CODE_VALUE (value));
-    g_object_unref (value);
-    return STATUS_OK;
-  }
-
-  if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &if_statement) !=
-      STATUS_OK)
-    goto fail;
-
-  if (!check_token (scanner, ':'))
-    goto fail;
-
-  if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION,
-	&else_statement) != STATUS_OK)
-    goto fail;
-
-  *statement = vivi_code_if_new (value);
-  vivi_code_if_set_if (VIVI_CODE_IF (*statement), if_statement);
-  vivi_code_if_set_else (VIVI_CODE_IF (*statement), else_statement);
-
-  g_object_unref (value);
-  g_object_unref (if_statement);
-  g_object_unref (else_statement);
-
-  return STATUS_OK;
-
-fail:
-
-  g_object_unref (value);
-  if (if_statement != NULL)
-    g_object_unref (if_statement);
-
-  return STATUS_FAIL;
-}
-
-static ParseStatus
-parse_operator_expression (GScanner *scanner, ViviCodeValue **value)
-{
-  ParseStatus status;
-  ViviCodeValue *left;
-  ViviCodeValue *right;
-
-  *value = NULL;
-
-  status = parse_value (scanner, SYMBOL_UNARY_EXPRESSION, value);
-  if (status != STATUS_OK)
-    return status;
-
-  do {
-    if (!check_token (scanner, '+'))
-      return STATUS_OK;
-
-    if (parse_value (scanner, SYMBOL_UNARY_EXPRESSION, &right) != STATUS_OK) {
-      g_object_unref (*value);
-      *value = NULL;
-      return STATUS_FAIL;
-    }
-
-    left = VIVI_CODE_VALUE (*value);
-    *value = vivi_code_binary_new_name (left, VIVI_CODE_VALUE (right), "+");
-    g_object_unref (left);
-    g_object_unref (right);
-  } while (TRUE);
-
-  g_object_unref (*value);
-  *value = NULL;
-
-  return STATUS_FAIL;
-}
-
-static ParseStatus
-parse_unary_expression (GScanner *scanner, ViviCodeValue **value)
-{
-  ViviCodeValue *tmp;
-
-  *value = NULL;
-
-  if (check_token (scanner, '!')) {
-    parse_value (scanner, SYMBOL_UNARY_EXPRESSION, value);
-    tmp = VIVI_CODE_VALUE (*value);
-    *value = vivi_code_unary_new (tmp, '!');
-    g_object_unref (tmp);
-    return STATUS_OK;
-  } else {
-    return parse_value (scanner, SYMBOL_POSTFIX_EXPRESSION, value);
-  }
-}
-
-static ParseStatus
-parse_postfix_expression (GScanner *scanner, ViviCodeValue **value)
-{
-  ParseStatus status;
-
-  status = parse_value (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION, value);
-  if (status != STATUS_OK)
-    return status;
-
-  // FIXME: Don't allow new line here
-
-  /*if (check_token (scanner, TOKEN_PLUSPLUS)) {
-    ViviCodeValue *tmp = *value;
-    *value = vivi_code_postfix_new (tmp, "++");
-    g_object_unref (tmp);
-  } else {*/
-    return STATUS_OK;
-  //}
-}
-
-static ParseStatus
-parse_left_hand_side_expression (GScanner *scanner, ViviCodeValue **value)
-{
-  ParseStatus status;
-
-  *value = NULL;
-
-  status = parse_value (scanner, SYMBOL_NEW_EXPRESSION, value);
-  if (status == STATUS_CANCEL)
-    status = parse_value (scanner, SYMBOL_CALL_EXPRESSION, value);
-
-  return status;
-}
-
-static ParseStatus
-parse_new_expression (GScanner *scanner, ViviCodeValue **value)
-{
-  *value = NULL;
-
-  if (check_token (scanner, TOKEN_NEW)) {
-    if (parse_value (scanner, SYMBOL_NEW_EXPRESSION, value) != STATUS_OK)
-      return STATUS_FAIL;
-    if (!VIVI_IS_CODE_FUNCTION_CALL (*value)) {
-      ViviCodeValue *tmp = VIVI_CODE_VALUE (*value);
-      *value = vivi_code_function_call_new (NULL, tmp);
-      g_object_unref (tmp);
-    }
-    vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*value),
-	TRUE);
-    return STATUS_OK;
-  } else {
-    return parse_value (scanner, SYMBOL_MEMBER_EXPRESSION, value);
-  }
-}
-
-static ParseStatus
-parse_member_expression (GScanner *scanner, ViviCodeValue **value)
-{
-  ParseStatus status;
-  ViviCodeValue *member;
-
-  // TODO: new MemberExpression Arguments
-
-  status = parse_value (scanner, SYMBOL_PRIMARY_EXPRESSION, value);
-  if (status == STATUS_CANCEL)
-    status = parse_value (scanner, SYMBOL_FUNCTION_EXPRESSION, value);
-
-  if (status != 0)
-    return status;
-
-  do {
-    ViviCodeValue *tmp;
-
-    if (check_token (scanner, '[')) {
-      if (parse_value (scanner, SYMBOL_EXPRESSION, &member) != STATUS_OK)
-	return STATUS_FAIL;
-      if (!check_token (scanner, ']'))
-	return STATUS_FAIL;
-    } else if (check_token (scanner, '.')) {
-      if (parse_value (scanner, SYMBOL_IDENTIFIER, &member) != STATUS_OK)
-	return STATUS_FAIL;
-    } else {
-      return STATUS_OK;
-    }
-
-    tmp = *value;
-    *value = vivi_code_get_new (tmp, VIVI_CODE_VALUE (member));
-    g_object_unref (tmp);
-    g_object_unref (member);
-  } while (TRUE);
-
-  g_assert_not_reached ();
-  return STATUS_FAIL;
-}
-
-static ParseStatus
-parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
-{
-  int i;
-  ParseStatus status;
-  ParseSymbol options[] = {
-    SYMBOL_IDENTIFIER,
-    SYMBOL_LITERAL,
-    SYMBOL_ARRAY_LITERAL,
-    SYMBOL_OBJECT_LITERAL,
-    SYMBOL_NONE
-  };
-
-  *value = NULL;
-
-  if (check_token (scanner, TOKEN_THIS)) {
-    *value = vivi_code_get_new_name ("this");
-    return STATUS_OK;
-  }
-
-  /*if (check_token (scanner, '(')) {
-    return STATUS_OK;
-  }*/
-
-  for (i = 0; options[i] != SYMBOL_NONE; i++) {
-    status = parse_value (scanner, options[i], value);
-    if (status != STATUS_CANCEL)
-      return status;
-  }
-
-  return STATUS_CANCEL;
-}
-
-// misc
-
-static ParseStatus
-parse_variable_declaration (GScanner *scanner, ViviCodeStatement **statement)
-{
-  ParseStatus status;
-  ViviCodeValue *identifier;
-  ViviCodeValue *value;
-
-  *statement = NULL;
-
-  status = parse_value (scanner, SYMBOL_IDENTIFIER, &identifier);
-  if (status != STATUS_OK)
-    return status;
-
-  if (check_token (scanner, '=')) {
-    // TODO
-    return STATUS_FAIL;
-  } else {
-    value = vivi_code_constant_new_undefined ();
-  }
-
-  *statement = vivi_code_assignment_new (NULL, identifier, value);
-  vivi_code_assignment_set_local (VIVI_CODE_ASSIGNMENT (*statement), TRUE);
-
-  return STATUS_OK;
-}
-
 // parsing
 
 typedef struct {
commit a02163032fc771d8ddf666bb7cb95b77e8c3a4f5
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sat Mar 29 02:09:21 2008 +0200

    Handle variable statements, except for assignments

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 5d20e07..12db713 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -205,6 +205,7 @@ typedef enum {
   SYMBOL_ARRAY_LITERAL,
   SYMBOL_OBJECT_LITERAL,
   // misc
+  SYMBOL_VARIABLE_DECLARATION,
   SYMBOL_ASSIGNMENT_OPERATOR,
   SYMBOL_ARGUMENTS,
 } ParseSymbol;
@@ -389,6 +390,34 @@ parse_block (GScanner *scanner, ViviCodeStatement **statement)
   return STATUS_OK;
 }
 
+static ParseStatus
+parse_variable_statement (GScanner *scanner, ViviCodeStatement **statement)
+{
+  ViviCodeStatement **list;
+  ParseStatus status;
+
+  *statement = NULL;
+
+  if (!check_token (scanner, TOKEN_VAR)) {
+    return STATUS_CANCEL;
+  }
+
+  status =
+    parse_statement_list (scanner, SYMBOL_VARIABLE_DECLARATION, &list, ',');
+  if (status != STATUS_OK)
+    return status;
+
+  if (!check_token (scanner, ';')) {
+    free_statement_list (list);
+    return STATUS_FAIL;
+  }
+
+  *statement = create_block (list);
+  free_statement_list (list);
+
+  return STATUS_OK;
+}
+
 /*
  * if ((a = c) && (b = 1))
  *
@@ -761,7 +790,8 @@ parse_member_expression (GScanner *scanner, ViviCodeValue **value)
 static ParseStatus
 parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
 {
-  int i, status;
+  int i;
+  ParseStatus status;
   ParseSymbol options[] = {
     SYMBOL_IDENTIFIER,
     SYMBOL_LITERAL,
@@ -790,6 +820,34 @@ parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
   return STATUS_CANCEL;
 }
 
+// misc
+
+static ParseStatus
+parse_variable_declaration (GScanner *scanner, ViviCodeStatement **statement)
+{
+  ParseStatus status;
+  ViviCodeValue *identifier;
+  ViviCodeValue *value;
+
+  *statement = NULL;
+
+  status = parse_value (scanner, SYMBOL_IDENTIFIER, &identifier);
+  if (status != STATUS_OK)
+    return status;
+
+  if (check_token (scanner, '=')) {
+    // TODO
+    return STATUS_FAIL;
+  } else {
+    value = vivi_code_constant_new_undefined ();
+  }
+
+  *statement = vivi_code_assignment_new (NULL, identifier, value);
+  vivi_code_assignment_set_local (VIVI_CODE_ASSIGNMENT (*statement), TRUE);
+
+  return STATUS_OK;
+}
+
 // parsing
 
 typedef struct {
@@ -808,7 +866,7 @@ static const SymbolStatementFunctionList statement_symbols[] = {
   // statement
   { SYMBOL_STATEMENT, "Statement", parse_statement_symbol },
   { SYMBOL_BLOCK, "Block", parse_block },
-  //{ SYMBOL_VARIABLE_STATEMENT, "VariableStatement", parse_variable_statement },
+  { SYMBOL_VARIABLE_STATEMENT, "VariableStatement", parse_variable_statement },
   { SYMBOL_EMPTY_STATEMENT, "EmptyStatement", parse_empty_statement },
   { SYMBOL_EXPRESSION_STATEMENT, "ExpressionStatement",
     parse_expression_statement },
@@ -829,6 +887,9 @@ static const SymbolStatementFunctionList statement_symbols[] = {
     parse_assignment_expression },
   { SYMBOL_CONDITIONAL_EXPRESSION, "ConditionalExpression",
     parse_conditional_expression },
+  // misc
+  { SYMBOL_VARIABLE_DECLARATION, "VariableDeclaration",
+    parse_variable_declaration },
   { SYMBOL_NONE, NULL, NULL }
 };
 
commit c7bc33c91f3e5e410615aee0cdfe91be54d1dd69
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sat Mar 29 02:06:55 2008 +0200

    ViviCodeAssignment: Handle varname for Get. Don't print out undefined if local

diff --git a/vivified/code/vivi_code_assignment.c b/vivified/code/vivi_code_assignment.c
index f8bbd36..af4c909 100644
--- a/vivified/code/vivi_code_assignment.c
+++ b/vivified/code/vivi_code_assignment.c
@@ -23,6 +23,7 @@
 
 #include "vivi_code_assignment.h"
 #include "vivi_code_constant.h"
+#include "vivi_code_get.h"
 #include "vivi_code_printer.h"
 
 G_DEFINE_TYPE (ViviCodeAssignment, vivi_code_assignment, VIVI_TYPE_CODE_STATEMENT)
@@ -46,10 +47,13 @@ vivi_code_assignment_print (ViviCodeToken *token, ViviCodePrinter*printer)
   ViviCodeAssignment *assignment = VIVI_CODE_ASSIGNMENT (token);
   char *varname;
 
-  if (VIVI_IS_CODE_CONSTANT (assignment->name))
+  if (VIVI_IS_CODE_CONSTANT (assignment->name)) {
     varname = vivi_code_constant_get_variable_name (VIVI_CODE_CONSTANT (assignment->name));
-  else
+  } else if (VIVI_IS_CODE_GET (assignment->name)) {
+    varname = vivi_code_constant_get_variable_name (VIVI_CODE_CONSTANT (VIVI_CODE_GET (assignment->name)->name));
+  } else {
     varname = NULL;
+  }
 
   if (assignment->local)
     vivi_code_printer_print (printer, "var ");
@@ -76,8 +80,12 @@ vivi_code_assignment_print (ViviCodeToken *token, ViviCodePrinter*printer)
       goto finalize;
     }
   }
-  vivi_code_printer_print (printer, " = ");
-  vivi_code_printer_print_value (printer, assignment->value, VIVI_PRECEDENCE_ASSIGNMENT);
+  if (!assignment->local || !VIVI_IS_CODE_CONSTANT (assignment->value) ||
+      vivi_code_constant_get_value_type (
+	VIVI_CODE_CONSTANT (assignment->value)) != SWFDEC_AS_TYPE_UNDEFINED) {
+    vivi_code_printer_print (printer, " = ");
+    vivi_code_printer_print_value (printer, assignment->value, VIVI_PRECEDENCE_ASSIGNMENT);
+  }
   g_free (varname);
 finalize:
   vivi_code_printer_print (printer, ";");
commit 0299f0eb67800da2b8f72cdff96beaedc7be55a0
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sat Mar 29 01:16:18 2008 +0200

    Reorder some functions in the compiler code

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index c9baced..5d20e07 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -276,39 +276,156 @@ create_block (ViviCodeStatement **list)
   return VIVI_CODE_STATEMENT (block);
 }
 
-// top
+// values
 
 static ParseStatus
-parse_program (GScanner *scanner, ViviCodeStatement **statement)
+parse_literal (GScanner *scanner, ViviCodeValue **value)
+{
+  *value = NULL;
+
+  if (check_token (scanner, G_TOKEN_STRING)) {
+    *value = vivi_code_constant_new_string (scanner->value.v_string);
+    return STATUS_OK;
+  } else if (check_token (scanner, G_TOKEN_FLOAT)) {
+    *value = vivi_code_constant_new_number (scanner->value.v_float);
+    return STATUS_OK;
+  } else if (check_token (scanner, TOKEN_TRUE)) {
+    *value = vivi_code_constant_new_boolean (TRUE);
+    return STATUS_OK;
+  } else if (check_token (scanner, TOKEN_FALSE)) {
+    *value = vivi_code_constant_new_boolean (FALSE);
+    return STATUS_OK;
+  } else if (check_token (scanner, TOKEN_NULL)) {
+    *value = vivi_code_constant_new_null ();
+    return STATUS_OK;
+  } else {
+    return STATUS_CANCEL;
+  }
+
+  *value = vivi_code_get_new_name (scanner->value.v_identifier);
+
+  return STATUS_OK;
+}
+
+static ParseStatus
+parse_identifier (GScanner *scanner, ViviCodeValue **value)
+{
+  *value = NULL;
+
+  if (!check_token (scanner, G_TOKEN_IDENTIFIER))
+    return STATUS_CANCEL;
+
+  *value = vivi_code_get_new_name (scanner->value.v_identifier);
+
+  return STATUS_OK;
+}
+
+// statement
+
+static ParseStatus
+parse_expression_statement (GScanner *scanner, ViviCodeStatement **statement)
 {
   ParseStatus status;
-  ViviCodeStatement **list;
 
   *statement = NULL;
 
-  status = parse_statement_list (scanner, SYMBOL_SOURCE_ELEMENT, &list,
-      G_TOKEN_NONE);
+  g_scanner_peek_next_token (scanner);
+  if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
+    return STATUS_CANCEL;
+
+  status = parse_statement (scanner, SYMBOL_EXPRESSION, statement);
   if (status != STATUS_OK)
     return status;
 
-  *statement = create_block (list);
+  if (!check_token (scanner, ';')) {
+    g_object_unref (*statement);
+    *statement = NULL;
+    return STATUS_FAIL;
+  }
 
   return STATUS_OK;
 }
 
 static ParseStatus
-parse_source_element (GScanner *scanner, ViviCodeStatement **statement)
+parse_empty_statement (GScanner *scanner, ViviCodeStatement **statement)
 {
-  ParseStatus status;
+  *statement = NULL;
+
+  if (!check_token (scanner, ';'))
+    return STATUS_CANCEL;
+
+  *statement = vivi_compiler_empty_statement_new ();
+
+  return STATUS_OK;
+}
+
+static ParseStatus
+parse_block (GScanner *scanner, ViviCodeStatement **statement)
+{
+  ViviCodeStatement **list;
 
   *statement = NULL;
 
-  status = parse_statement (scanner, SYMBOL_FUNCTION_DECLARATION, statement);
+  if (!check_token (scanner, '{'))
+    return STATUS_CANCEL;
 
-  if (status == STATUS_CANCEL)
-    status = parse_statement (scanner, SYMBOL_STATEMENT, statement);
+  g_scanner_peek_next_token (scanner);
+  if (scanner->next_token != '}') {
+    if (parse_statement_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
+	!= STATUS_OK)
+      return STATUS_FAIL;
+  } else {
+    list = g_new0 (ViviCodeStatement *, 1);
+  }
 
-  return status;
+  if (!check_token (scanner, '}')) {
+    free_statement_list (list);
+    return STATUS_FAIL;
+  }
+
+  *statement = create_block (list);
+  free_statement_list (list);
+
+  return STATUS_OK;
+}
+
+/*
+ * if ((a = c) && (b = 1))
+ *
+ * a = c; if (a) { b = 1; if (b) }
+ */
+
+static ParseStatus
+parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement)
+{
+  int i, status;
+  ParseSymbol options[] = {
+    SYMBOL_BLOCK,
+    SYMBOL_VARIABLE_STATEMENT,
+    SYMBOL_EMPTY_STATEMENT,
+    SYMBOL_EXPRESSION_STATEMENT,
+    SYMBOL_IF_STATEMENT,
+    SYMBOL_ITERATION_STATEMENT,
+    SYMBOL_CONTINUE_STATEMENT,
+    SYMBOL_BREAK_STATEMENT,
+    SYMBOL_RETURN_STATEMENT,
+    SYMBOL_WITH_STATEMENT,
+    SYMBOL_LABELLED_STATEMENT,
+    SYMBOL_SWITCH_STATEMENT,
+    SYMBOL_THROW_STATEMENT,
+    SYMBOL_TRY_STATEMENT,
+    SYMBOL_NONE
+  };
+
+  *statement = NULL;
+
+  for (i = 0; options[i] != SYMBOL_NONE; i++) {
+    status = parse_statement (scanner, options[i], statement);
+    if (status != STATUS_CANCEL)
+      return status;
+  }
+
+  return STATUS_CANCEL;
 }
 
 // function
@@ -377,104 +494,37 @@ fail:
   return STATUS_FAIL;
 }
 
-// statement
-
-static ParseStatus
-parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement)
-{
-  int i, status;
-  ParseSymbol options[] = {
-    SYMBOL_BLOCK,
-    SYMBOL_VARIABLE_STATEMENT,
-    SYMBOL_EMPTY_STATEMENT,
-    SYMBOL_EXPRESSION_STATEMENT,
-    SYMBOL_IF_STATEMENT,
-    SYMBOL_ITERATION_STATEMENT,
-    SYMBOL_CONTINUE_STATEMENT,
-    SYMBOL_BREAK_STATEMENT,
-    SYMBOL_RETURN_STATEMENT,
-    SYMBOL_WITH_STATEMENT,
-    SYMBOL_LABELLED_STATEMENT,
-    SYMBOL_SWITCH_STATEMENT,
-    SYMBOL_THROW_STATEMENT,
-    SYMBOL_TRY_STATEMENT,
-    SYMBOL_NONE
-  };
-
-  *statement = NULL;
-
-  for (i = 0; options[i] != SYMBOL_NONE; i++) {
-    status = parse_statement (scanner, options[i], statement);
-    if (status != STATUS_CANCEL)
-      return status;
-  }
-
-  return STATUS_CANCEL;
-}
+// top
 
 static ParseStatus
-parse_block (GScanner *scanner, ViviCodeStatement **statement)
+parse_source_element (GScanner *scanner, ViviCodeStatement **statement)
 {
-  ViviCodeStatement **list;
-
-  *statement = NULL;
-
-  if (!check_token (scanner, '{'))
-    return STATUS_CANCEL;
-
-  g_scanner_peek_next_token (scanner);
-  if (scanner->next_token != '}') {
-    if (parse_statement_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
-	!= STATUS_OK)
-      return STATUS_FAIL;
-  } else {
-    list = g_new0 (ViviCodeStatement *, 1);
-  }
-
-  if (!check_token (scanner, '}')) {
-    free_statement_list (list);
-    return STATUS_FAIL;
-  }
-
-  *statement = create_block (list);
-  free_statement_list (list);
-
-  return STATUS_OK;
-}
+  ParseStatus status;
 
-static ParseStatus
-parse_empty_statement (GScanner *scanner, ViviCodeStatement **statement)
-{
   *statement = NULL;
 
-  if (!check_token (scanner, ';'))
-    return STATUS_CANCEL;
+  status = parse_statement (scanner, SYMBOL_FUNCTION_DECLARATION, statement);
 
-  *statement = vivi_compiler_empty_statement_new ();
+  if (status == STATUS_CANCEL)
+    status = parse_statement (scanner, SYMBOL_STATEMENT, statement);
 
-  return STATUS_OK;
+  return status;
 }
 
 static ParseStatus
-parse_expression_statement (GScanner *scanner, ViviCodeStatement **statement)
+parse_program (GScanner *scanner, ViviCodeStatement **statement)
 {
   ParseStatus status;
+  ViviCodeStatement **list;
 
   *statement = NULL;
 
-  g_scanner_peek_next_token (scanner);
-  if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
-    return STATUS_CANCEL;
-
-  status = parse_statement (scanner, SYMBOL_EXPRESSION, statement);
+  status = parse_statement_list (scanner, SYMBOL_SOURCE_ELEMENT, &list,
+      G_TOKEN_NONE);
   if (status != STATUS_OK)
     return status;
 
-  if (!check_token (scanner, ';')) {
-    g_object_unref (*statement);
-    *statement = NULL;
-    return STATUS_FAIL;
-  }
+  *statement = create_block (list);
 
   return STATUS_OK;
 }
@@ -740,50 +790,6 @@ parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
   return STATUS_CANCEL;
 }
 
-// values
-
-static ParseStatus
-parse_identifier (GScanner *scanner, ViviCodeValue **value)
-{
-  *value = NULL;
-
-  if (!check_token (scanner, G_TOKEN_IDENTIFIER))
-    return STATUS_CANCEL;
-
-  *value = vivi_code_get_new_name (scanner->value.v_identifier);
-
-  return STATUS_OK;
-}
-
-static ParseStatus
-parse_literal (GScanner *scanner, ViviCodeValue **value)
-{
-  *value = NULL;
-
-  if (check_token (scanner, G_TOKEN_STRING)) {
-    *value = vivi_code_constant_new_string (scanner->value.v_string);
-    return STATUS_OK;
-  } else if (check_token (scanner, G_TOKEN_FLOAT)) {
-    *value = vivi_code_constant_new_number (scanner->value.v_float);
-    return STATUS_OK;
-  } else if (check_token (scanner, TOKEN_TRUE)) {
-    *value = vivi_code_constant_new_boolean (TRUE);
-    return STATUS_OK;
-  } else if (check_token (scanner, TOKEN_FALSE)) {
-    *value = vivi_code_constant_new_boolean (FALSE);
-    return STATUS_OK;
-  } else if (check_token (scanner, TOKEN_NULL)) {
-    *value = vivi_code_constant_new_null ();
-    return STATUS_OK;
-  } else {
-    return STATUS_CANCEL;
-  }
-
-  *value = vivi_code_get_new_name (scanner->value.v_identifier);
-
-  return STATUS_OK;
-}
-
 // parsing
 
 typedef struct {
@@ -802,9 +808,21 @@ static const SymbolStatementFunctionList statement_symbols[] = {
   // statement
   { SYMBOL_STATEMENT, "Statement", parse_statement_symbol },
   { SYMBOL_BLOCK, "Block", parse_block },
+  //{ SYMBOL_VARIABLE_STATEMENT, "VariableStatement", parse_variable_statement },
   { SYMBOL_EMPTY_STATEMENT, "EmptyStatement", parse_empty_statement },
   { SYMBOL_EXPRESSION_STATEMENT, "ExpressionStatement",
     parse_expression_statement },
+  /*{ SYMBOL_IF_STATEMENT, "IfStatement", parse_if_statement },
+  { SYMBOL_ITERATION_STATEMENT, "IterationStatement",
+    parse_iteration_statement },
+  { SYMBOL_CONTINUE_STATEMENT, "ContinueStatement", parse_continue_statement },
+  { SYMBOL_BREAK_STATEMENT, "BreakStatement", parse_break_statement },
+  { SYMBOL_RETURN_STATEMENT, "ReturnStatement", parse_return_statement },
+  { SYMBOL_WITH_STATEMENT, "WithStatement", parse_with_statement },
+  { SYMBOL_LABELLED_STATEMENT, "LabelledStatement", parse_labelled_statement },
+  { SYMBOL_SWITCH_STATEMENT, "SwitchStatement", parse_switch_statement },
+  { SYMBOL_THROW_STATEMENT, "ThrowStatement", parse_throw_statement },
+  { SYMBOL_TRY_STATEMENT, "TryStatement", parse_try_statement },*/
   // expression
   { SYMBOL_EXPRESSION, "Expression", parse_expression },
   { SYMBOL_ASSIGNMENT_EXPRESSION, "AssigmentExpression",
commit dccab3b02d3b2835862c0044e8b27edf9018bad1
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sat Mar 29 00:40:04 2008 +0200

    Add Ecma-262 keywords and reserved keywords

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 7e9e745..c9baced 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -54,14 +54,113 @@ typedef enum {
 } ParseStatus;
 
 enum {
-  TOKEN_FUNCTION = G_TOKEN_LAST + 1,
-  TOKEN_PLUSPLUS = G_TOKEN_LAST + 2,
-  TOKEN_MINUSMINUS = G_TOKEN_LAST + 3,
-  TOKEN_NEW = G_TOKEN_LAST + 4,
-  TOKEN_TRUE = G_TOKEN_LAST + 5,
-  TOKEN_FALSE = G_TOKEN_LAST + 6,
-  TOKEN_NULL = G_TOKEN_LAST + 7,
-  TOKEN_THIS = G_TOKEN_LAST + 8
+  // keywords
+  TOKEN_BREAK = G_TOKEN_LAST + 1,
+  TOKEN_CASE,
+  TOKEN_CATCH,
+  TOKEN_CONTINUE,
+  TOKEN_DEFAULT,
+  TOKEN_DELETE,
+  TOKEN_DO,
+  TOKEN_ELSE,
+  TOKEN_FINALLY,
+  TOKEN_FOR,
+  TOKEN_FUNCTION,
+  TOKEN_IF,
+  TOKEN_IN,
+  TOKEN_INSTANCEOF,
+  TOKEN_NEW,
+  TOKEN_RETURN,
+  TOKEN_SWITCH,
+  TOKEN_THIS,
+  TOKEN_THROW,
+  TOKEN_TRY,
+  TOKEN_TYPEOF,
+  TOKEN_VAR,
+  TOKEN_VOID,
+  TOKEN_WITH,
+  // reserved keywords
+  TOKEN_FUTURE,
+  // values
+  TOKEN_TRUE,
+  TOKEN_FALSE,
+  TOKEN_NULL,
+  // misc
+  TOKEN_PLUSPLUS,
+  TOKEN_MINUSMINUS
+};
+
+typedef struct {
+  guint		token;
+  const char *	symbol;
+} TokenDescription;
+
+static const TokenDescription custom_tokens[] = {
+  // keywords
+  { TOKEN_BREAK, "break" },
+  { TOKEN_CASE, "case" },
+  { TOKEN_CATCH, "catch" },
+  { TOKEN_CONTINUE, "continue" },
+  { TOKEN_DEFAULT, "default" },
+  { TOKEN_DELETE, "delete" },
+  { TOKEN_DO, "do" },
+  { TOKEN_ELSE, "else" },
+  { TOKEN_FINALLY, "finally" },
+  { TOKEN_FOR, "for" },
+  { TOKEN_FUNCTION, "function" },
+  { TOKEN_IF, "if" },
+  { TOKEN_IN, "in" },
+  { TOKEN_INSTANCEOF, "instanceof" },
+  { TOKEN_NEW, "new" },
+  { TOKEN_RETURN, "return" },
+  { TOKEN_SWITCH, "switch" },
+  { TOKEN_THIS, "this" },
+  { TOKEN_THROW, "throw" },
+  { TOKEN_TRY, "try" },
+  { TOKEN_TYPEOF, "typeof" },
+  { TOKEN_VAR, "var" },
+  { TOKEN_VOID, "while" },
+  { TOKEN_WITH, "with" },
+  // reserved keywords
+  { TOKEN_FUTURE, "abstract" },
+  { TOKEN_FUTURE, "boolean" },
+  { TOKEN_FUTURE, "byte" },
+  { TOKEN_FUTURE, "char" },
+  { TOKEN_FUTURE, "class" },
+  { TOKEN_FUTURE, "const" },
+  { TOKEN_FUTURE, "debugger" },
+  { TOKEN_FUTURE, "double" },
+  { TOKEN_FUTURE, "enum" },
+  { TOKEN_FUTURE, "export" },
+  { TOKEN_FUTURE, "extends" },
+  { TOKEN_FUTURE, "final" },
+  { TOKEN_FUTURE, "float" },
+  { TOKEN_FUTURE, "goto" },
+  { TOKEN_FUTURE, "implements" },
+  { TOKEN_FUTURE, "import" },
+  { TOKEN_FUTURE, "int" },
+  { TOKEN_FUTURE, "interface" },
+  { TOKEN_FUTURE, "long" },
+  { TOKEN_FUTURE, "native" },
+  { TOKEN_FUTURE, "package" },
+  { TOKEN_FUTURE, "private" },
+  { TOKEN_FUTURE, "protected" },
+  { TOKEN_FUTURE, "public" },
+  { TOKEN_FUTURE, "short" },
+  { TOKEN_FUTURE, "static" },
+  { TOKEN_FUTURE, "super" },
+  { TOKEN_FUTURE, "synchronized" },
+  { TOKEN_FUTURE, "throws" },
+  { TOKEN_FUTURE, "transient" },
+  { TOKEN_FUTURE, "volatile" },
+  // values
+  { TOKEN_TRUE, "true" },
+  { TOKEN_FALSE, "false" },
+  { TOKEN_NULL, "null" },
+  // misc
+  { TOKEN_PLUSPLUS, "++" },
+  { TOKEN_MINUSMINUS, "--" },
+  { G_TOKEN_NONE, NULL }
 };
 
 typedef enum {
@@ -861,6 +960,7 @@ vivi_compile_text (const char *text, gsize len, const char *input_name)
   GScanner *scanner;
   ViviCodeStatement *statement;
   ParseStatus status;
+  int i;
 
   g_return_val_if_fail (text != NULL, NULL);
 
@@ -877,13 +977,10 @@ vivi_compile_text (const char *text, gsize len, const char *input_name)
   scanner->config->scan_identifier_1char = TRUE;
 
   g_scanner_set_scope (scanner, 0);
-  g_scanner_scope_add_symbol (scanner, 0, "function",
-      GINT_TO_POINTER (TOKEN_FUNCTION));
-  g_scanner_scope_add_symbol (scanner, 0, "++",
-      GINT_TO_POINTER (TOKEN_PLUSPLUS));
-  g_scanner_scope_add_symbol (scanner, 0, "--",
-      GINT_TO_POINTER (TOKEN_MINUSMINUS));
-  g_scanner_scope_add_symbol (scanner, 0, "new", GINT_TO_POINTER (TOKEN_NEW));
+  for (i = 0; custom_tokens[i].token != G_TOKEN_NONE; i++) {
+    g_scanner_scope_add_symbol (scanner, 0, custom_tokens[i].symbol,
+	GINT_TO_POINTER (custom_tokens[i].token));
+  }
 
   scanner->input_name = input_name;
   g_scanner_input_text (scanner, text, len);
commit 07687ebc5f3266e1e1a8928d4696db8ac0ddda2c
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sat Mar 29 00:13:12 2008 +0200

    No more secrets!

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index 2d40e3c..a0d2807 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -90,16 +90,3 @@ vivi_compile_SOURCES = \
 vivi_compile_CFLAGS =  $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS)
 vivi_compile_LDFLAGS = $(SWFDEC_LIBS)
 vivi_compile_LDADD = libvivified-compiler.la
-
-if SECRET_TEST_CODE
-noinst_PROGRAMS += vivi-decompile-gtk
-
-vivi_decompile_gtk_SOURCES = \
-	vivi_code_gtk_printer.c \
-	vivi_code_gtk_printer.h \
-	gtk_decompiler.c
-
-vivi_decompile_gtk_CFLAGS =  $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(GTK_CFLAGS)
-vivi_decompile_gtk_LDFLAGS = $(SWFDEC_LIBS) $(GTK_LIBS)
-vivi_decompile_gtk_LDADD = libvivified-compiler.la
-endif
commit e54d550771c400bafa53a84d08aa1b6eb0d037b7
Merge: 9af10b3... 31434d2...
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sat Mar 29 00:04:01 2008 +0200

    Merge branch 'master' of ssh://medar@git.freedesktop.org/git/swfdec/swfdec
    
    Conflicts:
    
    	vivified/code/Makefile.am

diff --cc vivified/code/Makefile.am
index a0d2807,57a7b4c..2d40e3c
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@@ -84,9 -80,15 +84,22 @@@ vivi_decompile_CFLAGS =  $(GLOBAL_CFLAG
  vivi_decompile_LDFLAGS = $(SWFDEC_LIBS)
  vivi_decompile_LDADD = libvivified-compiler.la
  
 +vivi_compile_SOURCES = \
 +	compiler.c
 +
 +vivi_compile_CFLAGS =  $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS)
 +vivi_compile_LDFLAGS = $(SWFDEC_LIBS)
 +vivi_compile_LDADD = libvivified-compiler.la
++
+ if SECRET_TEST_CODE
+ noinst_PROGRAMS += vivi-decompile-gtk
+ 
+ vivi_decompile_gtk_SOURCES = \
+ 	vivi_code_gtk_printer.c \
+ 	vivi_code_gtk_printer.h \
+ 	gtk_decompiler.c
+ 
+ vivi_decompile_gtk_CFLAGS =  $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(GTK_CFLAGS)
+ vivi_decompile_gtk_LDFLAGS = $(SWFDEC_LIBS) $(GTK_LIBS)
+ vivi_decompile_gtk_LDADD = libvivified-compiler.la
+ endif
commit 9af10b3fcd7589d54eba2b1960793c9a50c5580d
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Sat Mar 29 00:00:45 2008 +0200

    Parse simple literals and conditional expressions. Allow 1char identifiers

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index e8ef2fa..7e9e745 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -57,7 +57,11 @@ enum {
   TOKEN_FUNCTION = G_TOKEN_LAST + 1,
   TOKEN_PLUSPLUS = G_TOKEN_LAST + 2,
   TOKEN_MINUSMINUS = G_TOKEN_LAST + 3,
-  TOKEN_NEW = G_TOKEN_LAST + 4
+  TOKEN_NEW = G_TOKEN_LAST + 4,
+  TOKEN_TRUE = G_TOKEN_LAST + 5,
+  TOKEN_FALSE = G_TOKEN_LAST + 6,
+  TOKEN_NULL = G_TOKEN_LAST + 7,
+  TOKEN_THIS = G_TOKEN_LAST + 8
 };
 
 typedef enum {
@@ -96,8 +100,12 @@ typedef enum {
   SYMBOL_MEMBER_EXPRESSION,
   SYMBOL_FUNCTION_EXPRESSION,
   SYMBOL_PRIMARY_EXPRESSION,
-  // misc
+  // values
   SYMBOL_IDENTIFIER,
+  SYMBOL_LITERAL,
+  SYMBOL_ARRAY_LITERAL,
+  SYMBOL_OBJECT_LITERAL,
+  // misc
   SYMBOL_ASSIGNMENT_OPERATOR,
   SYMBOL_ARGUMENTS,
 } ParseSymbol;
@@ -408,10 +416,10 @@ parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
 {
   ParseStatus status;
   ViviCodeValue *value;
-  ViviCodeStatement *first, *second;
+  ViviCodeStatement *if_statement, *else_statement;
 
   *statement = NULL;
-  first = NULL;
+  if_statement = NULL;
 
   status = parse_value (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
   if (status != STATUS_OK)
@@ -423,31 +431,32 @@ parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
     return STATUS_OK;
   }
 
-  if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &first) !=
+  if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &if_statement) !=
       STATUS_OK)
     goto fail;
 
   if (!check_token (scanner, ':'))
     goto fail;
 
-  if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &second) !=
-      STATUS_OK)
+  if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION,
+	&else_statement) != STATUS_OK)
     goto fail;
 
-  //*statement = vivi_code_condional_new (VIVI_CODE_VALUE (value),
-  //    VIVI_CODE_STATEMENT (first), VIVI_CODE_STATEMENT (second));
+  *statement = vivi_code_if_new (value);
+  vivi_code_if_set_if (VIVI_CODE_IF (*statement), if_statement);
+  vivi_code_if_set_else (VIVI_CODE_IF (*statement), else_statement);
 
   g_object_unref (value);
-  g_object_unref (first);
-  g_object_unref (second);
+  g_object_unref (if_statement);
+  g_object_unref (else_statement);
 
   return STATUS_OK;
 
 fail:
 
   g_object_unref (value);
-  if (first != NULL)
-    g_object_unref (first);
+  if (if_statement != NULL)
+    g_object_unref (if_statement);
 
   return STATUS_FAIL;
 }
@@ -603,11 +612,36 @@ parse_member_expression (GScanner *scanner, ViviCodeValue **value)
 static ParseStatus
 parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
 {
-  // TODO
-  return parse_value (scanner, SYMBOL_IDENTIFIER, value);
+  int i, status;
+  ParseSymbol options[] = {
+    SYMBOL_IDENTIFIER,
+    SYMBOL_LITERAL,
+    SYMBOL_ARRAY_LITERAL,
+    SYMBOL_OBJECT_LITERAL,
+    SYMBOL_NONE
+  };
+
+  *value = NULL;
+
+  if (check_token (scanner, TOKEN_THIS)) {
+    *value = vivi_code_get_new_name ("this");
+    return STATUS_OK;
+  }
+
+  /*if (check_token (scanner, '(')) {
+    return STATUS_OK;
+  }*/
+
+  for (i = 0; options[i] != SYMBOL_NONE; i++) {
+    status = parse_value (scanner, options[i], value);
+    if (status != STATUS_CANCEL)
+      return status;
+  }
+
+  return STATUS_CANCEL;
 }
 
-// misc.
+// values
 
 static ParseStatus
 parse_identifier (GScanner *scanner, ViviCodeValue **value)
@@ -622,6 +656,35 @@ parse_identifier (GScanner *scanner, ViviCodeValue **value)
   return STATUS_OK;
 }
 
+static ParseStatus
+parse_literal (GScanner *scanner, ViviCodeValue **value)
+{
+  *value = NULL;
+
+  if (check_token (scanner, G_TOKEN_STRING)) {
+    *value = vivi_code_constant_new_string (scanner->value.v_string);
+    return STATUS_OK;
+  } else if (check_token (scanner, G_TOKEN_FLOAT)) {
+    *value = vivi_code_constant_new_number (scanner->value.v_float);
+    return STATUS_OK;
+  } else if (check_token (scanner, TOKEN_TRUE)) {
+    *value = vivi_code_constant_new_boolean (TRUE);
+    return STATUS_OK;
+  } else if (check_token (scanner, TOKEN_FALSE)) {
+    *value = vivi_code_constant_new_boolean (FALSE);
+    return STATUS_OK;
+  } else if (check_token (scanner, TOKEN_NULL)) {
+    *value = vivi_code_constant_new_null ();
+    return STATUS_OK;
+  } else {
+    return STATUS_CANCEL;
+  }
+
+  *value = vivi_code_get_new_name (scanner->value.v_identifier);
+
+  return STATUS_OK;
+}
+
 // parsing
 
 typedef struct {
@@ -669,8 +732,9 @@ static const SymbolValueFunctionList value_symbols[] = {
   { SYMBOL_NEW_EXPRESSION, "NewExpression", parse_new_expression },
   { SYMBOL_MEMBER_EXPRESSION, "MemberExpression", parse_member_expression },
   { SYMBOL_PRIMARY_EXPRESSION, "PrimaryExpression", parse_primary_expression },
-  // misc
+  // value
   { SYMBOL_IDENTIFIER, "Identifier", parse_identifier },
+  { SYMBOL_LITERAL, "Literal", parse_literal },
   { SYMBOL_NONE, NULL, NULL }
 };
 
@@ -805,6 +869,12 @@ vivi_compile_text (const char *text, gsize len, const char *input_name)
   scanner->config->numbers_2_int = TRUE;
   scanner->config->int_2_float = TRUE;
   scanner->config->symbol_2_token = TRUE;
+  // FIXME: Should allow other Unicode characters
+  scanner->config->cset_identifier_first =
+    g_strdup (G_CSET_A_2_Z G_CSET_a_2_z G_CSET_LATINS G_CSET_LATINC "_$");
+  scanner->config->cset_identifier_nth = g_strdup (G_CSET_A_2_Z G_CSET_a_2_z
+      G_CSET_LATINS G_CSET_LATINC "_$" G_CSET_DIGITS);
+  scanner->config->scan_identifier_1char = TRUE;
 
   g_scanner_set_scope (scanner, 0);
   g_scanner_scope_add_symbol (scanner, 0, "function",
commit 0b76dda301be3f1acda0d70d203e1ab8be58c8fc
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Mar 28 19:59:48 2008 +0200

    Optimize empty statement and remove the useless need_braces function

diff --git a/vivified/code/vivi_compiler_empty_statement.c b/vivified/code/vivi_compiler_empty_statement.c
index 1cabdfd..568da2d 100644
--- a/vivified/code/vivi_compiler_empty_statement.c
+++ b/vivified/code/vivi_compiler_empty_statement.c
@@ -30,14 +30,7 @@ G_DEFINE_TYPE (ViviCompilerEmptyStatement, vivi_compiler_empty_statement, VIVI_T
 static ViviCodeStatement *
 vivi_compiler_empty_statement_optimize (ViviCodeStatement *statement)
 {
-  // FIXME
-  return statement;
-}
-
-static gboolean
-vivi_compiler_empty_statement_needs_braces (ViviCodeStatement *stmt)
-{
-  return FALSE;
+  return NULL;
 }
 
 static void
@@ -58,7 +51,6 @@ vivi_compiler_empty_statement_class_init (
   token_class->print = vivi_compiler_empty_statement_print;
 
   statement_class->optimize = vivi_compiler_empty_statement_optimize;
-  statement_class->needs_braces = vivi_compiler_empty_statement_needs_braces;
 }
 
 static void
commit 60171ab83143fc6849bdefee240219cfd7bd7db7
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Mar 28 19:59:06 2008 +0200

    Rename CodeEmpty to CompilerEmptyStatement

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index fc3cfd7..a0d2807 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -13,7 +13,6 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_comment.c \
 	vivi_code_constant.c \
 	vivi_code_continue.c \
-	vivi_code_empty.c \
 	vivi_code_function.c \
 	vivi_code_function_call.c \
 	vivi_code_get.c \
@@ -33,6 +32,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_value.c \
 	vivi_code_value_statement.c \
 	vivi_compiler.c \
+	vivi_compiler_empty_statement.c \
 	vivi_decompiler_block.c \
 	vivi_decompiler_duplicate.c \
 	vivi_decompiler_state.c \
@@ -47,7 +47,6 @@ noinst_HEADERS = \
 	vivi_code_comment.h \
 	vivi_code_constant.h \
 	vivi_code_continue.h \
-	vivi_code_empty.h \
 	vivi_code_function.h \
 	vivi_code_function_call.h \
 	vivi_code_get.h \
@@ -67,6 +66,7 @@ noinst_HEADERS = \
 	vivi_code_value.h \
 	vivi_code_value_statement.h \
 	vivi_compiler.h \
+	vivi_compiler_empty_statement.h \
 	vivi_decompiler.h \
 	vivi_decompiler_block.h \
 	vivi_decompiler_duplicate.h \
diff --git a/vivified/code/vivi_code_empty.c b/vivified/code/vivi_code_empty.c
deleted file mode 100644
index cf56456..0000000
--- a/vivified/code/vivi_code_empty.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/* Vivified
- * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
- *               2008 Pekka Lampila <pekka.lampila at iki.fi>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "vivi_code_empty.h"
-#include "vivi_code_printer.h"
-
-G_DEFINE_TYPE (ViviCodeEmpty, vivi_code_empty, VIVI_TYPE_CODE_STATEMENT)
-
-static ViviCodeStatement *
-vivi_code_empty_optimize (ViviCodeStatement *statement)
-{
-  // FIXME
-  return statement;
-}
-
-static gboolean
-vivi_code_empty_needs_braces (ViviCodeStatement *stmt)
-{
-  return FALSE;
-}
-
-static void
-vivi_code_empty_print (ViviCodeToken *token, ViviCodePrinter *printer)
-{
-  vivi_code_printer_print (printer, ";");
-  vivi_code_printer_new_line (printer, FALSE);
-}
-
-static void
-vivi_code_empty_class_init (ViviCodeEmptyClass *klass)
-{
-  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
-  ViviCodeStatementClass *statement_class = VIVI_CODE_STATEMENT_CLASS (klass);
-
-  token_class->print = vivi_code_empty_print;
-
-  statement_class->optimize = vivi_code_empty_optimize;
-  statement_class->needs_braces = vivi_code_empty_needs_braces;
-}
-
-static void
-vivi_code_empty_init (ViviCodeEmpty *token)
-{
-}
-
-ViviCodeStatement *
-vivi_code_empty_new (void)
-{
-  ViviCodeEmpty *stmt;
-
-  stmt = g_object_new (VIVI_TYPE_CODE_EMPTY, NULL);
-
-  return VIVI_CODE_STATEMENT (stmt);
-}
diff --git a/vivified/code/vivi_code_empty.h b/vivified/code/vivi_code_empty.h
deleted file mode 100644
index 48dc126..0000000
--- a/vivified/code/vivi_code_empty.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Vivified
- * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
- *               2008 Pekka Lampila <pekka.lampila at iki.fi>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifndef _VIVI_CODE_EMPTY_H_
-#define _VIVI_CODE_EMPTY_H_
-
-#include <vivified/code/vivi_code_statement.h>
-#include <vivified/code/vivi_code_value.h>
-
-G_BEGIN_DECLS
-
-
-typedef struct _ViviCodeEmpty ViviCodeEmpty;
-typedef struct _ViviCodeEmptyClass ViviCodeEmptyClass;
-
-#define VIVI_TYPE_CODE_EMPTY                    (vivi_code_empty_get_type())
-#define VIVI_IS_CODE_EMPTY(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_EMPTY))
-#define VIVI_IS_CODE_EMPTY_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_EMPTY))
-#define VIVI_CODE_EMPTY(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_EMPTY, ViviCodeEmpty))
-#define VIVI_CODE_EMPTY_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_EMPTY, ViviCodeEmptyClass))
-#define VIVI_CODE_EMPTY_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_EMPTY, ViviCodeEmptyClass))
-
-struct _ViviCodeEmpty
-{
-  ViviCodeStatement	statement;
-};
-
-struct _ViviCodeEmptyClass
-{
-  ViviCodeStatementClass	statement_class;
-};
-
-GType			vivi_code_empty_get_type	(void);
-
-ViviCodeStatement *	vivi_code_empty_new		(void);
-
-
-G_END_DECLS
-#endif
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index dae6046..e8ef2fa 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -31,7 +31,6 @@
 #include "vivi_code_break.h"
 #include "vivi_code_constant.h"
 #include "vivi_code_continue.h"
-#include "vivi_code_empty.h"
 #include "vivi_code_function.h"
 #include "vivi_code_function_call.h"
 #include "vivi_code_get.h"
@@ -44,6 +43,7 @@
 #include "vivi_code_trace.h"
 #include "vivi_code_unary.h"
 #include "vivi_code_value_statement.h"
+#include "vivi_compiler_empty_statement.h"
 
 #include "vivi_code_text_printer.h"
 
@@ -249,7 +249,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
   /*function = vivi_code_function_new (arguments, body);
   *statement = vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
       VIVI_CODE_VALUE (function));*/
-  *statement = vivi_code_empty_new ();
+  *statement = vivi_compiler_empty_statement_new ();
 
   g_object_unref (identifier);
   if (arguments != NULL)
@@ -343,7 +343,7 @@ parse_empty_statement (GScanner *scanner, ViviCodeStatement **statement)
   if (!check_token (scanner, ';'))
     return STATUS_CANCEL;
 
-  *statement = vivi_code_empty_new ();
+  *statement = vivi_compiler_empty_statement_new ();
 
   return STATUS_OK;
 }
@@ -603,6 +603,7 @@ parse_member_expression (GScanner *scanner, ViviCodeValue **value)
 static ParseStatus
 parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
 {
+  // TODO
   return parse_value (scanner, SYMBOL_IDENTIFIER, value);
 }
 
diff --git a/vivified/code/vivi_compiler_empty_statement.c b/vivified/code/vivi_compiler_empty_statement.c
new file mode 100644
index 0000000..1cabdfd
--- /dev/null
+++ b/vivified/code/vivi_compiler_empty_statement.c
@@ -0,0 +1,77 @@
+/* Vivified
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ *               2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "vivi_compiler_empty_statement.h"
+#include "vivi_code_printer.h"
+
+G_DEFINE_TYPE (ViviCompilerEmptyStatement, vivi_compiler_empty_statement, VIVI_TYPE_CODE_STATEMENT)
+
+static ViviCodeStatement *
+vivi_compiler_empty_statement_optimize (ViviCodeStatement *statement)
+{
+  // FIXME
+  return statement;
+}
+
+static gboolean
+vivi_compiler_empty_statement_needs_braces (ViviCodeStatement *stmt)
+{
+  return FALSE;
+}
+
+static void
+vivi_compiler_empty_statement_print (ViviCodeToken *token,
+    ViviCodePrinter *printer)
+{
+  vivi_code_printer_print (printer, ";");
+  vivi_code_printer_new_line (printer, FALSE);
+}
+
+static void
+vivi_compiler_empty_statement_class_init (
+    ViviCompilerEmptyStatementClass *klass)
+{
+  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeStatementClass *statement_class = VIVI_CODE_STATEMENT_CLASS (klass);
+
+  token_class->print = vivi_compiler_empty_statement_print;
+
+  statement_class->optimize = vivi_compiler_empty_statement_optimize;
+  statement_class->needs_braces = vivi_compiler_empty_statement_needs_braces;
+}
+
+static void
+vivi_compiler_empty_statement_init (ViviCompilerEmptyStatement *token)
+{
+}
+
+ViviCodeStatement *
+vivi_compiler_empty_statement_new (void)
+{
+  ViviCompilerEmptyStatement *stmt;
+
+  stmt = g_object_new (VIVI_TYPE_COMPILER_EMPTY, NULL);
+
+  return VIVI_CODE_STATEMENT (stmt);
+}
diff --git a/vivified/code/vivi_compiler_empty_statement.h b/vivified/code/vivi_compiler_empty_statement.h
new file mode 100644
index 0000000..ede1fa5
--- /dev/null
+++ b/vivified/code/vivi_compiler_empty_statement.h
@@ -0,0 +1,56 @@
+/* Vivified
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ *               2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _VIVI_COMPILER_EMPTY_H_
+#define _VIVI_COMPILER_EMPTY_H_
+
+#include <vivified/code/vivi_code_statement.h>
+#include <vivified/code/vivi_code_value.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCompilerEmptyStatement ViviCompilerEmptyStatement;
+typedef struct _ViviCompilerEmptyStatementClass ViviCompilerEmptyStatementClass;
+
+#define VIVI_TYPE_COMPILER_EMPTY                    (vivi_compiler_empty_statement_get_type())
+#define VIVI_IS_COMPILER_EMPTY(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_COMPILER_EMPTY))
+#define VIVI_IS_COMPILER_EMPTY_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_COMPILER_EMPTY))
+#define VIVI_COMPILER_EMPTY(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_COMPILER_EMPTY, ViviCompilerEmptyStatement))
+#define VIVI_COMPILER_EMPTY_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_COMPILER_EMPTY, ViviCompilerEmptyStatementClass))
+#define VIVI_COMPILER_EMPTY_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_COMPILER_EMPTY, ViviCompilerEmptyStatementClass))
+
+struct _ViviCompilerEmptyStatement
+{
+  ViviCodeStatement	statement;
+};
+
+struct _ViviCompilerEmptyStatementClass
+{
+  ViviCodeStatementClass	statement_class;
+};
+
+GType			vivi_compiler_empty_statement_get_type		(void);
+
+ViviCodeStatement *	vivi_compiler_empty_statement_new		(void);
+
+
+G_END_DECLS
+#endif
commit f183b6a6523b0102671ae057d3ab7e51a5bb694a
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Mar 28 18:56:01 2008 +0200

    Few cleanups to the compiler code

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 17fcd2b..dae6046 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -179,7 +179,8 @@ parse_program (GScanner *scanner, ViviCodeStatement **statement)
 
   *statement = NULL;
 
-  status = parse_statement_list (scanner, SYMBOL_SOURCE_ELEMENT, &list, G_TOKEN_NONE);
+  status = parse_statement_list (scanner, SYMBOL_SOURCE_ELEMENT, &list,
+      G_TOKEN_NONE);
   if (status != STATUS_OK)
     return status;
 
@@ -228,7 +229,8 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
   if (!check_token (scanner, '('))
     goto fail;
 
-  if (parse_value_list (scanner, SYMBOL_IDENTIFIER, &arguments, ',') == STATUS_FAIL)
+  if (parse_value_list (scanner, SYMBOL_IDENTIFIER, &arguments, ',') ==
+      STATUS_FAIL)
     goto fail;
 
   if (!check_token (scanner, ')'))
@@ -313,18 +315,17 @@ parse_block (GScanner *scanner, ViviCodeStatement **statement)
   if (!check_token (scanner, '{'))
     return STATUS_CANCEL;
 
-  list = NULL;
-
   g_scanner_peek_next_token (scanner);
   if (scanner->next_token != '}') {
     if (parse_statement_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
 	!= STATUS_OK)
       return STATUS_FAIL;
+  } else {
+    list = g_new0 (ViviCodeStatement *, 1);
   }
 
   if (!check_token (scanner, '}')) {
-    if (list != NULL)
-      free_statement_list (list);
+    free_statement_list (list);
     return STATUS_FAIL;
   }
 
@@ -386,12 +387,7 @@ parse_expression (GScanner *scanner, ViviCodeStatement **statement)
   if (status != STATUS_OK)
     return status;
 
-  if (list[1] == NULL) {
-    *statement = g_object_ref (list[0]);
-  } else {
-    *statement = create_block (list);
-  }
-
+  *statement = create_block (list);
   free_statement_list (list);
 
   return STATUS_OK;
commit 59cd72f052fa595bd816907c5fa8953a589278b8
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Mar 28 18:43:28 2008 +0200

    Split compiler's parsing functions to Statement and Value categories

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 53d873c..17fcd2b 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -102,14 +102,23 @@ typedef enum {
   SYMBOL_ARGUMENTS,
 } ParseSymbol;
 
-typedef ParseStatus (*ParseFunction) (GScanner *scanner, ViviCodeToken **token);
+typedef ParseStatus (*ParseStatementFunction) (GScanner *scanner, ViviCodeStatement **statement);
+typedef ParseStatus (*ParseValueFunction) (GScanner *scanner, ViviCodeValue **value);
 
 static ParseStatus
-parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token);
+parse_statement (GScanner *scanner, ParseSymbol symbol,
+    ViviCodeStatement **statement);
 
 static ParseStatus
-parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
-    guint separator);
+parse_value (GScanner *scanner, ParseSymbol symbol, ViviCodeValue **value);
+
+static ParseStatus
+parse_statement_list (GScanner *scanner, ParseSymbol symbol,
+    ViviCodeStatement ***list, guint separator);
+
+static ParseStatus
+parse_value_list (GScanner *scanner, ParseSymbol symbol,
+    ViviCodeValue ***list, guint separator);
 
 // helpers
 
@@ -124,7 +133,7 @@ check_token (GScanner *scanner, guint token)
 }
 
 static void
-free_list (ViviCodeToken **list)
+free_statement_list (ViviCodeStatement **list)
 {
   int i;
 
@@ -134,8 +143,19 @@ free_list (ViviCodeToken **list)
   g_free (list);
 }
 
-static ViviCodeBlock *
-create_block (ViviCodeToken **list)
+static void
+free_value_list (ViviCodeValue **list)
+{
+  int i;
+
+  for (i = 0; list[i] != NULL; i++) {
+    g_object_unref (list[i]);
+  }
+  g_free (list);
+}
+
+static ViviCodeStatement *
+create_block (ViviCodeStatement **list)
 {
   ViviCodeBlock *block;
   int i;
@@ -143,42 +163,42 @@ create_block (ViviCodeToken **list)
   block = VIVI_CODE_BLOCK (vivi_code_block_new ());
 
   for (i = 0; list[i] != NULL; i++) {
-    vivi_code_block_add_statement (block, VIVI_CODE_STATEMENT (list[i]));
+    vivi_code_block_add_statement (block, list[i]);
   }
 
-  return block;
+  return VIVI_CODE_STATEMENT (block);
 }
 
 // top
 
 static ParseStatus
-parse_program (GScanner *scanner, ViviCodeToken **token)
+parse_program (GScanner *scanner, ViviCodeStatement **statement)
 {
   ParseStatus status;
-  ViviCodeToken **list;
+  ViviCodeStatement **list;
 
-  *token = NULL;
+  *statement = NULL;
 
-  status = parse_list (scanner, SYMBOL_SOURCE_ELEMENT, &list, G_TOKEN_NONE);
+  status = parse_statement_list (scanner, SYMBOL_SOURCE_ELEMENT, &list, G_TOKEN_NONE);
   if (status != STATUS_OK)
     return status;
 
-  *token = VIVI_CODE_TOKEN (create_block (list));
+  *statement = create_block (list);
 
   return STATUS_OK;
 }
 
 static ParseStatus
-parse_source_element (GScanner *scanner, ViviCodeToken **token)
+parse_source_element (GScanner *scanner, ViviCodeStatement **statement)
 {
   ParseStatus status;
 
-  *token = NULL;
+  *statement = NULL;
 
-  status = parse (scanner, SYMBOL_FUNCTION_DECLARATION, token);
+  status = parse_statement (scanner, SYMBOL_FUNCTION_DECLARATION, statement);
 
   if (status == STATUS_CANCEL)
-    status = parse (scanner, SYMBOL_STATEMENT, token);
+    status = parse_statement (scanner, SYMBOL_STATEMENT, statement);
 
   return status;
 }
@@ -186,13 +206,14 @@ parse_source_element (GScanner *scanner, ViviCodeToken **token)
 // function
 
 static ParseStatus
-parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
+parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
 {
-  //ViviCodeToken *function;
-  ViviCodeToken *identifier;
-  ViviCodeToken **arguments, **body;
+  //ViviCodeStatement *function;
+  ViviCodeValue *identifier;
+  ViviCodeValue **arguments;
+  ViviCodeStatement **body;
 
-  *token = NULL;
+  *statement = NULL;
 
   identifier = NULL;
   arguments = NULL;
@@ -201,13 +222,13 @@ parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
   if (!check_token (scanner, TOKEN_FUNCTION))
     return STATUS_CANCEL;
 
-  if (parse (scanner, SYMBOL_IDENTIFIER, &identifier) != STATUS_OK)
+  if (parse_value (scanner, SYMBOL_IDENTIFIER, &identifier) != STATUS_OK)
     return STATUS_FAIL;
 
   if (!check_token (scanner, '('))
     goto fail;
 
-  if (parse_list (scanner, SYMBOL_IDENTIFIER, &arguments, ',') == STATUS_FAIL)
+  if (parse_value_list (scanner, SYMBOL_IDENTIFIER, &arguments, ',') == STATUS_FAIL)
     goto fail;
 
   if (!check_token (scanner, ')'))
@@ -216,7 +237,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
   if (!check_token (scanner, '{'))
     goto fail;
 
-  if (parse_list (scanner, SYMBOL_SOURCE_ELEMENT, &body, G_TOKEN_NONE)
+  if (parse_statement_list (scanner, SYMBOL_SOURCE_ELEMENT, &body, G_TOKEN_NONE)
       == STATUS_FAIL)
     goto fail;
 
@@ -224,16 +245,15 @@ parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
     goto fail;
 
   /*function = vivi_code_function_new (arguments, body);
-  *token = VIVI_CODE_TOKEN (
-      vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
-      VIVI_CODE_VALUE (function)));*/
-  *token = VIVI_CODE_TOKEN (vivi_code_empty_new ());
+  *statement = vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
+      VIVI_CODE_VALUE (function));*/
+  *statement = vivi_code_empty_new ();
 
   g_object_unref (identifier);
   if (arguments != NULL)
-    free_list (arguments);
+    free_value_list (arguments);
   if (body != NULL)
-    free_list (body);
+    free_statement_list (body);
 
   return STATUS_OK;
 
@@ -241,9 +261,9 @@ fail:
   if (identifier != NULL)
     g_object_unref (identifier);
   if (arguments != NULL)
-    free_list (arguments);
+    free_value_list (arguments);
   if (body != NULL)
-    free_list (body);
+    free_statement_list (body);
 
   return STATUS_FAIL;
 }
@@ -251,7 +271,7 @@ fail:
 // statement
 
 static ParseStatus
-parse_statement (GScanner *scanner, ViviCodeToken **token)
+parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement)
 {
   int i, status;
   ParseSymbol options[] = {
@@ -272,10 +292,10 @@ parse_statement (GScanner *scanner, ViviCodeToken **token)
     SYMBOL_NONE
   };
 
-  *token = NULL;
+  *statement = NULL;
 
   for (i = 0; options[i] != SYMBOL_NONE; i++) {
-    status = parse (scanner, options[i], token);
+    status = parse_statement (scanner, options[i], statement);
     if (status != STATUS_CANCEL)
       return status;
   }
@@ -284,11 +304,11 @@ parse_statement (GScanner *scanner, ViviCodeToken **token)
 }
 
 static ParseStatus
-parse_block (GScanner *scanner, ViviCodeToken **token)
+parse_block (GScanner *scanner, ViviCodeStatement **statement)
 {
-  ViviCodeToken **list;
+  ViviCodeStatement **list;
 
-  *token = NULL;
+  *statement = NULL;
 
   if (!check_token (scanner, '{'))
     return STATUS_CANCEL;
@@ -297,54 +317,54 @@ parse_block (GScanner *scanner, ViviCodeToken **token)
 
   g_scanner_peek_next_token (scanner);
   if (scanner->next_token != '}') {
-    if (parse_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
+    if (parse_statement_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
 	!= STATUS_OK)
       return STATUS_FAIL;
   }
 
   if (!check_token (scanner, '}')) {
     if (list != NULL)
-      free_list (list);
+      free_statement_list (list);
     return STATUS_FAIL;
   }
 
-  *token = VIVI_CODE_TOKEN (create_block (list));
-  free_list (list);
+  *statement = create_block (list);
+  free_statement_list (list);
 
   return STATUS_OK;
 }
 
 static ParseStatus
-parse_empty_statement (GScanner *scanner, ViviCodeToken **token)
+parse_empty_statement (GScanner *scanner, ViviCodeStatement **statement)
 {
-  *token = NULL;
+  *statement = NULL;
 
   if (!check_token (scanner, ';'))
     return STATUS_CANCEL;
 
-  *token = VIVI_CODE_TOKEN (vivi_code_empty_new ());
+  *statement = vivi_code_empty_new ();
 
   return STATUS_OK;
 }
 
 static ParseStatus
-parse_expression_statement (GScanner *scanner, ViviCodeToken **token)
+parse_expression_statement (GScanner *scanner, ViviCodeStatement **statement)
 {
   ParseStatus status;
 
-  *token = NULL;
+  *statement = NULL;
 
   g_scanner_peek_next_token (scanner);
   if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
     return STATUS_CANCEL;
 
-  status = parse (scanner, SYMBOL_EXPRESSION, token);
+  status = parse_statement (scanner, SYMBOL_EXPRESSION, statement);
   if (status != STATUS_OK)
     return status;
 
   if (!check_token (scanner, ';')) {
-    g_object_unref (*token);
-    *token = NULL;
+    g_object_unref (*statement);
+    *statement = NULL;
     return STATUS_FAIL;
   }
 
@@ -354,69 +374,71 @@ parse_expression_statement (GScanner *scanner, ViviCodeToken **token)
 // expression
 
 static ParseStatus
-parse_expression (GScanner *scanner, ViviCodeToken **token)
+parse_expression (GScanner *scanner, ViviCodeStatement **statement)
 {
-  ViviCodeToken **list;
+  ViviCodeStatement **list;
   ParseStatus status;
 
-  *token = NULL;
+  *statement = NULL;
 
-  status = parse_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
+  status =
+    parse_statement_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
   if (status != STATUS_OK)
     return status;
 
   if (list[1] == NULL) {
-    *token = g_object_ref (list[0]);
+    *statement = g_object_ref (list[0]);
   } else {
-    *token = VIVI_CODE_TOKEN (create_block (list));
+    *statement = create_block (list);
   }
 
-  free_list (list);
+  free_statement_list (list);
 
   return STATUS_OK;
 }
 
 static ParseStatus
-parse_assignment_expression (GScanner *scanner, ViviCodeToken **token)
+parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement)
 {
-  *token = NULL;
+  *statement = NULL;
 
   // TODO
 
-  return parse (scanner, SYMBOL_CONDITIONAL_EXPRESSION, token);
+  return parse_statement (scanner, SYMBOL_CONDITIONAL_EXPRESSION, statement);
 }
 
 static ParseStatus
-parse_conditional_expression (GScanner *scanner, ViviCodeToken **token)
+parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
 {
   ParseStatus status;
-  ViviCodeToken *value;
-  ViviCodeToken *first, *second;
+  ViviCodeValue *value;
+  ViviCodeStatement *first, *second;
 
-  *token = NULL;
+  *statement = NULL;
   first = NULL;
 
-  status = parse (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
+  status = parse_value (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
   if (status != STATUS_OK)
     return status;
 
   if (!check_token (scanner, '?')) {
-    *token = VIVI_CODE_TOKEN (
-	vivi_code_value_statement_new (VIVI_CODE_VALUE (value)));
+    *statement = vivi_code_value_statement_new (VIVI_CODE_VALUE (value));
     g_object_unref (value);
     return STATUS_OK;
   }
 
-  if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &first) != STATUS_OK)
+  if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &first) !=
+      STATUS_OK)
     goto fail;
 
   if (!check_token (scanner, ':'))
     goto fail;
 
-  if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &second) != STATUS_OK)
+  if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &second) !=
+      STATUS_OK)
     goto fail;
 
-  //*token = vivi_code_condional_new (VIVI_CODE_VALUE (value),
+  //*statement = vivi_code_condional_new (VIVI_CODE_VALUE (value),
   //    VIVI_CODE_STATEMENT (first), VIVI_CODE_STATEMENT (second));
 
   g_object_unref (value);
@@ -435,15 +457,15 @@ fail:
 }
 
 static ParseStatus
-parse_operator_expression (GScanner *scanner, ViviCodeToken **token)
+parse_operator_expression (GScanner *scanner, ViviCodeValue **value)
 {
   ParseStatus status;
   ViviCodeValue *left;
-  ViviCodeToken *right;
+  ViviCodeValue *right;
 
-  *token = NULL;
+  *value = NULL;
 
-  status = parse (scanner, SYMBOL_UNARY_EXPRESSION, token);
+  status = parse_value (scanner, SYMBOL_UNARY_EXPRESSION, value);
   if (status != STATUS_OK)
     return status;
 
@@ -451,132 +473,130 @@ parse_operator_expression (GScanner *scanner, ViviCodeToken **token)
     if (!check_token (scanner, '+'))
       return STATUS_OK;
 
-    if (parse (scanner, SYMBOL_UNARY_EXPRESSION, &right) != STATUS_OK) {
-      g_object_unref (*token);
-      *token = NULL;
+    if (parse_value (scanner, SYMBOL_UNARY_EXPRESSION, &right) != STATUS_OK) {
+      g_object_unref (*value);
+      *value = NULL;
       return STATUS_FAIL;
     }
 
-    left = VIVI_CODE_VALUE (*token);
-    *token = VIVI_CODE_TOKEN (vivi_code_binary_new_name (left,
-	  VIVI_CODE_VALUE (right), "+"));
+    left = VIVI_CODE_VALUE (*value);
+    *value = vivi_code_binary_new_name (left, VIVI_CODE_VALUE (right), "+");
     g_object_unref (left);
     g_object_unref (right);
   } while (TRUE);
 
-  g_object_unref (*token);
-  *token = NULL;
+  g_object_unref (*value);
+  *value = NULL;
 
   return STATUS_FAIL;
 }
 
 static ParseStatus
-parse_unary_expression (GScanner *scanner, ViviCodeToken **token)
+parse_unary_expression (GScanner *scanner, ViviCodeValue **value)
 {
-  ViviCodeValue *value;
+  ViviCodeValue *tmp;
 
-  *token = NULL;
+  *value = NULL;
 
   if (check_token (scanner, '!')) {
-    parse (scanner, SYMBOL_UNARY_EXPRESSION, token);
-    value = VIVI_CODE_VALUE (*token);
-    *token = VIVI_CODE_TOKEN (vivi_code_unary_new (value, '!'));
-    g_object_unref (value);
+    parse_value (scanner, SYMBOL_UNARY_EXPRESSION, value);
+    tmp = VIVI_CODE_VALUE (*value);
+    *value = vivi_code_unary_new (tmp, '!');
+    g_object_unref (tmp);
     return STATUS_OK;
   } else {
-    return parse (scanner, SYMBOL_POSTFIX_EXPRESSION, token);
+    return parse_value (scanner, SYMBOL_POSTFIX_EXPRESSION, value);
   }
 }
 
 static ParseStatus
-parse_postfix_expression (GScanner *scanner, ViviCodeToken **token)
+parse_postfix_expression (GScanner *scanner, ViviCodeValue **value)
 {
-  //ViviCodeValue *value;
   ParseStatus status;
 
-  status = parse (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION, token);
+  status = parse_value (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION, value);
   if (status != STATUS_OK)
     return status;
 
   // FIXME: Don't allow new line here
 
   /*if (check_token (scanner, TOKEN_PLUSPLUS)) {
-    value = VIVI_CODE_VALUE (*token);
-    *token = VIVI_CODE_TOKEN (vivi_code_postfix_new (value, "++"));
-    g_object_unref (value);
+    ViviCodeValue *tmp = *value;
+    *value = vivi_code_postfix_new (tmp, "++");
+    g_object_unref (tmp);
   } else {*/
     return STATUS_OK;
   //}
 }
 
 static ParseStatus
-parse_left_hand_side_expression (GScanner *scanner, ViviCodeToken **token)
+parse_left_hand_side_expression (GScanner *scanner, ViviCodeValue **value)
 {
   ParseStatus status;
 
-  *token = NULL;
+  *value = NULL;
 
-  status = parse (scanner, SYMBOL_NEW_EXPRESSION, token);
+  status = parse_value (scanner, SYMBOL_NEW_EXPRESSION, value);
   if (status == STATUS_CANCEL)
-    status = parse (scanner, SYMBOL_CALL_EXPRESSION, token);
+    status = parse_value (scanner, SYMBOL_CALL_EXPRESSION, value);
 
   return status;
 }
 
 static ParseStatus
-parse_new_expression (GScanner *scanner, ViviCodeToken **token)
+parse_new_expression (GScanner *scanner, ViviCodeValue **value)
 {
-  *token = NULL;
+  *value = NULL;
 
   if (check_token (scanner, TOKEN_NEW)) {
-    if (parse (scanner, SYMBOL_NEW_EXPRESSION, token) != STATUS_OK)
+    if (parse_value (scanner, SYMBOL_NEW_EXPRESSION, value) != STATUS_OK)
       return STATUS_FAIL;
-    if (!VIVI_IS_CODE_FUNCTION_CALL (*token)) {
-      ViviCodeValue *value = VIVI_CODE_VALUE (*token);
-      *token = VIVI_CODE_TOKEN (vivi_code_function_call_new (NULL, value));
-      g_object_unref (value);
+    if (!VIVI_IS_CODE_FUNCTION_CALL (*value)) {
+      ViviCodeValue *tmp = VIVI_CODE_VALUE (*value);
+      *value = vivi_code_function_call_new (NULL, tmp);
+      g_object_unref (tmp);
     }
-    vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*token),
+    vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*value),
 	TRUE);
     return STATUS_OK;
   } else {
-    return parse (scanner, SYMBOL_MEMBER_EXPRESSION, token);
+    return parse_value (scanner, SYMBOL_MEMBER_EXPRESSION, value);
   }
 }
 
 static ParseStatus
-parse_member_expression (GScanner *scanner, ViviCodeToken **token)
+parse_member_expression (GScanner *scanner, ViviCodeValue **value)
 {
   ParseStatus status;
-  ViviCodeValue *value;
-  ViviCodeToken *member;
+  ViviCodeValue *member;
 
   // TODO: new MemberExpression Arguments
 
-  status = parse (scanner, SYMBOL_PRIMARY_EXPRESSION, token);
+  status = parse_value (scanner, SYMBOL_PRIMARY_EXPRESSION, value);
   if (status == STATUS_CANCEL)
-    status = parse (scanner, SYMBOL_FUNCTION_EXPRESSION, token);
+    status = parse_value (scanner, SYMBOL_FUNCTION_EXPRESSION, value);
 
   if (status != 0)
     return status;
 
   do {
+    ViviCodeValue *tmp;
+
     if (check_token (scanner, '[')) {
-      if (parse (scanner, SYMBOL_EXPRESSION, &member) != STATUS_OK)
+      if (parse_value (scanner, SYMBOL_EXPRESSION, &member) != STATUS_OK)
 	return STATUS_FAIL;
       if (!check_token (scanner, ']'))
 	return STATUS_FAIL;
     } else if (check_token (scanner, '.')) {
-      if (parse (scanner, SYMBOL_IDENTIFIER, &member) != STATUS_OK)
+      if (parse_value (scanner, SYMBOL_IDENTIFIER, &member) != STATUS_OK)
 	return STATUS_FAIL;
     } else {
       return STATUS_OK;
     }
 
-    value = VIVI_CODE_VALUE (token);
-    *token = VIVI_CODE_TOKEN (
-	vivi_code_get_new (value, VIVI_CODE_VALUE (member)));
-    g_object_unref (value);
+    tmp = *value;
+    *value = vivi_code_get_new (tmp, VIVI_CODE_VALUE (member));
+    g_object_unref (tmp);
     g_object_unref (member);
   } while (TRUE);
 
@@ -585,34 +605,35 @@ parse_member_expression (GScanner *scanner, ViviCodeToken **token)
 }
 
 static ParseStatus
-parse_primary_expression (GScanner *scanner, ViviCodeToken **token)
+parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
 {
-  return parse (scanner, SYMBOL_IDENTIFIER, token);
+  return parse_value (scanner, SYMBOL_IDENTIFIER, value);
 }
 
 // misc.
 
 static ParseStatus
-parse_identifier (GScanner *scanner, ViviCodeToken **token)
+parse_identifier (GScanner *scanner, ViviCodeValue **value)
 {
-  *token = NULL;
+  *value = NULL;
 
   if (!check_token (scanner, G_TOKEN_IDENTIFIER))
     return STATUS_CANCEL;
 
-  *token =
-    VIVI_CODE_TOKEN (vivi_code_get_new_name (scanner->value.v_identifier));
+  *value = vivi_code_get_new_name (scanner->value.v_identifier);
 
   return STATUS_OK;
 }
 
 // parsing
 
-static const struct {
-  ParseSymbol		id;
-  const char *		name;
-  ParseFunction		parse;
-} symbols[] = {
+typedef struct {
+  ParseSymbol			id;
+  const char *			name;
+  ParseStatementFunction	parse;
+} SymbolStatementFunctionList;
+
+static const SymbolStatementFunctionList statement_symbols[] = {
   // top
   { SYMBOL_PROGRAM, "Program", parse_program },
   { SYMBOL_SOURCE_ELEMENT, "SourceElement", parse_source_element },
@@ -620,7 +641,7 @@ static const struct {
   { SYMBOL_FUNCTION_DECLARATION, "FunctionDeclaration",
     parse_function_declaration },
   // statement
-  { SYMBOL_STATEMENT, "Statement", parse_statement },
+  { SYMBOL_STATEMENT, "Statement", parse_statement_symbol },
   { SYMBOL_BLOCK, "Block", parse_block },
   { SYMBOL_EMPTY_STATEMENT, "EmptyStatement", parse_empty_statement },
   { SYMBOL_EXPRESSION_STATEMENT, "ExpressionStatement",
@@ -631,6 +652,17 @@ static const struct {
     parse_assignment_expression },
   { SYMBOL_CONDITIONAL_EXPRESSION, "ConditionalExpression",
     parse_conditional_expression },
+  { SYMBOL_NONE, NULL, NULL }
+};
+
+typedef struct {
+  ParseSymbol			id;
+  const char *			name;
+  ParseValueFunction		parse;
+} SymbolValueFunctionList;
+
+static const SymbolValueFunctionList value_symbols[] = {
+  // expression
   { SYMBOL_OPERATOR_EXPRESSION, "OperatorExpression",
     parse_operator_expression },
   { SYMBOL_UNARY_EXPRESSION, "UnaryExpression", parse_unary_expression },
@@ -646,19 +678,42 @@ static const struct {
 };
 
 static ParseStatus
-parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token)
+parse_statement (GScanner *scanner, ParseSymbol symbol,
+    ViviCodeStatement **statement)
+{
+  int i;
+
+  g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
+  g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
+  g_return_val_if_fail (statement != NULL, STATUS_FAIL);
+
+  for (i = 0; statement_symbols[i].id != SYMBOL_NONE; i++) {
+    if (statement_symbols[i].id == symbol) {
+      ParseStatus status = statement_symbols[i].parse (scanner, statement);
+      g_assert ((status == STATUS_OK && VIVI_IS_CODE_TOKEN (*statement)) ||
+	  (status != STATUS_OK && *statement == NULL));
+      return status;
+    }
+  }
+
+  //g_assert_not_reached ();
+  return STATUS_CANCEL;
+}
+
+static ParseStatus
+parse_value (GScanner *scanner, ParseSymbol symbol, ViviCodeValue **value)
 {
   int i;
 
   g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
   g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
-  g_return_val_if_fail (token != NULL, STATUS_FAIL);
+  g_return_val_if_fail (value != NULL, STATUS_FAIL);
 
-  for (i = 0; symbols[i].id != SYMBOL_NONE; i++) {
-    if (symbols[i].id == symbol) {
-      ParseStatus status = symbols[i].parse (scanner, token);
-      g_assert ((status == STATUS_OK && VIVI_IS_CODE_TOKEN (*token)) ||
-	  (status != STATUS_OK && *token == NULL));
+  for (i = 0; value_symbols[i].id != SYMBOL_NONE; i++) {
+    if (value_symbols[i].id == symbol) {
+      ParseStatus status = value_symbols[i].parse (scanner, value);
+      g_assert ((status == STATUS_OK && VIVI_IS_CODE_TOKEN (*value)) ||
+	  (status != STATUS_OK && *value == NULL));
       return status;
     }
   }
@@ -668,36 +723,71 @@ parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token)
 }
 
 static ParseStatus
-parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
+parse_statement_list (GScanner *scanner, ParseSymbol symbol,
+    ViviCodeStatement ***list, guint separator)
+{
+  GPtrArray *array;
+  ViviCodeStatement *statement;
+  ParseStatus status;
+
+  g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
+  g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
+  g_return_val_if_fail (list != NULL, STATUS_FAIL);
+
+  status = parse_statement (scanner, symbol, &statement);
+  if (status != STATUS_OK)
+    return status;
+
+  array = g_ptr_array_new ();
+
+  do {
+    g_ptr_array_add (array, statement);
+
+    if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
+      break;
+
+    status = parse_statement (scanner, symbol, &statement);
+    if (status == STATUS_FAIL)
+      return STATUS_FAIL;
+  } while (status == STATUS_OK);
+  g_ptr_array_add (array, NULL);
+
+  *list = (ViviCodeStatement **)g_ptr_array_free (array, FALSE);
+
+  return STATUS_OK;
+}
+
+static ParseStatus
+parse_value_list (GScanner *scanner, ParseSymbol symbol, ViviCodeValue ***list,
     guint separator)
 {
   GPtrArray *array;
-  ViviCodeToken *token;
-  ParseStatus ret;
+  ViviCodeValue *value;
+  ParseStatus status;
 
   g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
   g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
   g_return_val_if_fail (list != NULL, STATUS_FAIL);
 
-  ret = parse (scanner, symbol, &token);
-  if (ret != STATUS_OK)
-    return ret;
+  status = parse_value (scanner, symbol, &value);
+  if (status != STATUS_OK)
+    return status;
 
   array = g_ptr_array_new ();
 
   do {
-    g_ptr_array_add (array, token);
+    g_ptr_array_add (array, value);
 
     if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
       break;
 
-    ret = parse (scanner, symbol, &token);
-    if (ret == STATUS_FAIL)
+    status = parse_value (scanner, symbol, &value);
+    if (status == STATUS_FAIL)
       return STATUS_FAIL;
-  } while (ret == STATUS_OK);
+  } while (status == STATUS_OK);
   g_ptr_array_add (array, NULL);
 
-  *list = (ViviCodeToken **)g_ptr_array_free (array, FALSE);
+  *list = (ViviCodeValue **)g_ptr_array_free (array, FALSE);
 
   return STATUS_OK;
 }
@@ -708,7 +798,7 @@ ViviCodeStatement *
 vivi_compile_text (const char *text, gsize len, const char *input_name)
 {
   GScanner *scanner;
-  ViviCodeToken *token;
+  ViviCodeStatement *statement;
   ParseStatus status;
 
   g_return_val_if_fail (text != NULL, NULL);
@@ -721,23 +811,21 @@ vivi_compile_text (const char *text, gsize len, const char *input_name)
 
   g_scanner_set_scope (scanner, 0);
   g_scanner_scope_add_symbol (scanner, 0, "function",
-      GINT_TO_POINTER(TOKEN_FUNCTION));
+      GINT_TO_POINTER (TOKEN_FUNCTION));
   g_scanner_scope_add_symbol (scanner, 0, "++",
-      GINT_TO_POINTER(TOKEN_PLUSPLUS));
+      GINT_TO_POINTER (TOKEN_PLUSPLUS));
   g_scanner_scope_add_symbol (scanner, 0, "--",
-      GINT_TO_POINTER(TOKEN_MINUSMINUS));
-  g_scanner_scope_add_symbol (scanner, 0, "new", GINT_TO_POINTER(TOKEN_NEW));
+      GINT_TO_POINTER (TOKEN_MINUSMINUS));
+  g_scanner_scope_add_symbol (scanner, 0, "new", GINT_TO_POINTER (TOKEN_NEW));
 
   scanner->input_name = input_name;
   g_scanner_input_text (scanner, text, len);
 
-  status = parse (scanner, SYMBOL_PROGRAM, &token);
+  status = parse_statement (scanner, SYMBOL_PROGRAM, &statement);
+  g_assert ((status == STATUS_OK && VIVI_IS_CODE_STATEMENT (statement)) ||
+	(status != STATUS_OK && statement == NULL));
 
   g_scanner_destroy (scanner);
 
-  if (status == STATUS_OK) {
-    return VIVI_CODE_STATEMENT (token);
-  } else {
-    return NULL;
-  }
+  return statement;
 }
commit 2eb1fb3580b4abd7c80b64d62c51aed4d31268fb
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Mar 28 18:10:06 2008 +0200

    Add vivi-compiler to .gitignore

diff --git a/vivified/code/.gitignore b/vivified/code/.gitignore
index 8761c5f..b85daef 100644
--- a/vivified/code/.gitignore
+++ b/vivified/code/.gitignore
@@ -12,3 +12,4 @@ Makefile.in
 *.loT
 
 vivi-decompile
+vivi-compile
commit ce82ff6d58d7d8afd7b8bbc9057b1745a1f26c9c
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Mar 28 18:09:42 2008 +0200

    Re-organize and clean up the compiler code

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index a731138..fc3cfd7 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -32,6 +32,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_unary.c \
 	vivi_code_value.c \
 	vivi_code_value_statement.c \
+	vivi_compiler.c \
 	vivi_decompiler_block.c \
 	vivi_decompiler_duplicate.c \
 	vivi_decompiler_state.c \
@@ -65,6 +66,7 @@ noinst_HEADERS = \
 	vivi_code_unary.h \
 	vivi_code_value.h \
 	vivi_code_value_statement.h \
+	vivi_compiler.h \
 	vivi_decompiler.h \
 	vivi_decompiler_block.h \
 	vivi_decompiler_duplicate.h \
diff --git a/vivified/code/compiler.c b/vivified/code/compiler.c
index f550b1e..1e5cd3a 100644
--- a/vivified/code/compiler.c
+++ b/vivified/code/compiler.c
@@ -21,749 +21,39 @@
 #include "config.h"
 #endif
 
-#include <string.h>
 #include <swfdec/swfdec.h>
 
-#include "vivi_code_assignment.h"
-#include "vivi_code_binary.h"
-#include "vivi_code_block.h"
-#include "vivi_code_break.h"
-#include "vivi_code_constant.h"
-#include "vivi_code_continue.h"
-#include "vivi_code_empty.h"
-#include "vivi_code_function.h"
-#include "vivi_code_function_call.h"
-#include "vivi_code_get.h"
-#include "vivi_code_get_url.h"
-#include "vivi_code_goto.h"
-#include "vivi_code_if.h"
-#include "vivi_code_init_object.h"
-#include "vivi_code_loop.h"
-#include "vivi_code_return.h"
-#include "vivi_code_trace.h"
-#include "vivi_code_unary.h"
-#include "vivi_code_value_statement.h"
-
-typedef enum {
-  STATUS_FAIL = -1,
-  STATUS_OK = 0,
-  STATUS_CANCEL = 1
-} ParseStatus;
-
-enum {
-  TOKEN_FUNCTION = G_TOKEN_LAST + 1,
-  TOKEN_PLUSPLUS = G_TOKEN_LAST + 2,
-  TOKEN_MINUSMINUS = G_TOKEN_LAST + 3,
-  TOKEN_NEW = G_TOKEN_LAST + 4
-};
-
-typedef enum {
-  SYMBOL_NONE,
-  // top
-  SYMBOL_SOURCE_ELEMENT,
-  // function
-  SYMBOL_FUNCTION_DECLARATION,
-  // statement
-  SYMBOL_STATEMENT,
-  SYMBOL_BLOCK,
-  SYMBOL_VARIABLE_STATEMENT,
-  SYMBOL_EMPTY_STATEMENT,
-  SYMBOL_EXPRESSION_STATEMENT,
-  SYMBOL_IF_STATEMENT,
-  SYMBOL_ITERATION_STATEMENT,
-  SYMBOL_CONTINUE_STATEMENT,
-  SYMBOL_BREAK_STATEMENT,
-  SYMBOL_RETURN_STATEMENT,
-  SYMBOL_WITH_STATEMENT,
-  SYMBOL_LABELLED_STATEMENT,
-  SYMBOL_SWITCH_STATEMENT,
-  SYMBOL_THROW_STATEMENT,
-  SYMBOL_TRY_STATEMENT,
-  // expression
-  SYMBOL_EXPRESSION,
-  SYMBOL_ASSIGNMENT_EXPRESSION,
-  SYMBOL_CONDITIONAL_EXPRESSION,
-  SYMBOL_LEFT_HAND_SIDE_EXPRESSION,
-  SYMBOL_OPERATOR_EXPRESSION,
-  SYMBOL_UNARY_EXPRESSION,
-  SYMBOL_POSTFIX_EXPRESSION,
-  SYMBOL_NEW_EXPRESSION,
-  SYMBOL_CALL_EXPRESSION,
-  SYMBOL_MEMBER_EXPRESSION,
-  SYMBOL_FUNCTION_EXPRESSION,
-  SYMBOL_PRIMARY_EXPRESSION,
-  // misc
-  SYMBOL_IDENTIFIER,
-  SYMBOL_ASSIGNMENT_OPERATOR,
-  SYMBOL_ARGUMENTS,
-} ParseSymbol;
-
-typedef ParseStatus (*ParseFunction) (GScanner *scanner, ViviCodeToken **token);
-
-static ParseStatus
-parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token);
-
-static ParseStatus
-parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
-    guint separator);
-
-// helpers
-
-static gboolean
-check_token (GScanner *scanner, guint token)
-{
-  g_scanner_peek_next_token (scanner);
-  if (scanner->next_token != token)
-    return FALSE;
-  g_scanner_get_next_token (scanner);
-  return TRUE;
-}
-
-static void
-free_list (ViviCodeToken **list)
-{
-  int i;
-
-  for (i = 0; list[i] != NULL; i++) {
-    g_object_unref (list[i]);
-  }
-  g_free (list);
-}
-
-static ViviCodeBlock *
-create_block (ViviCodeToken **list)
-{
-  ViviCodeBlock *block;
-  int i;
-
-  block = VIVI_CODE_BLOCK (vivi_code_block_new ());
-
-  for (i = 0; list[i] != NULL; i++) {
-    vivi_code_block_add_statement (block, VIVI_CODE_STATEMENT (list[i]));
-  }
-
-  return block;
-}
-
-// top
-
-static ParseStatus
-parse_source_element (GScanner *scanner, ViviCodeToken **token)
-{
-  ParseStatus status;
-
-  *token = NULL;
-
-  status = parse (scanner, SYMBOL_FUNCTION_DECLARATION, token);
-
-  if (status == STATUS_CANCEL)
-    status = parse (scanner, SYMBOL_STATEMENT, token);
-
-  return status;
-}
-
-// function
-
-static ParseStatus
-parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
-{
-  //ViviCodeToken *function;
-  ViviCodeToken *identifier;
-  ViviCodeToken **arguments, **body;
-
-  *token = NULL;
-
-  identifier = NULL;
-  arguments = NULL;
-  body = NULL;
-
-  if (!check_token (scanner, TOKEN_FUNCTION))
-    return STATUS_CANCEL;
-
-  if (parse (scanner, SYMBOL_IDENTIFIER, &identifier) != STATUS_OK)
-    return STATUS_FAIL;
-
-  if (!check_token (scanner, '('))
-    goto fail;
-
-  if (parse_list (scanner, SYMBOL_IDENTIFIER, &arguments, ',') == STATUS_FAIL)
-    goto fail;
-
-  if (!check_token (scanner, ')'))
-    goto fail;
-
-  if (!check_token (scanner, '{'))
-    goto fail;
-
-  if (parse_list (scanner, SYMBOL_SOURCE_ELEMENT, &body, G_TOKEN_NONE)
-      == STATUS_FAIL)
-    goto fail;
-
-  if (!check_token (scanner, '}'))
-    goto fail;
-
-  /*function = vivi_code_function_new (arguments, body);
-  *token = VIVI_CODE_TOKEN (
-      vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
-      VIVI_CODE_VALUE (function)));*/
-  *token = VIVI_CODE_TOKEN (vivi_code_empty_new ());
-
-  g_object_unref (identifier);
-  if (arguments != NULL)
-    free_list (arguments);
-  if (body != NULL)
-    free_list (body);
-
-  return STATUS_OK;
-
-fail:
-  if (identifier != NULL)
-    g_object_unref (identifier);
-  if (arguments != NULL)
-    free_list (arguments);
-  if (body != NULL)
-    free_list (body);
-
-  return STATUS_FAIL;
-}
-
-// statement
-
-static ParseStatus
-parse_statement (GScanner *scanner, ViviCodeToken **token)
-{
-  int i, status;
-  ParseSymbol options[] = {
-    SYMBOL_BLOCK,
-    SYMBOL_VARIABLE_STATEMENT,
-    SYMBOL_EMPTY_STATEMENT,
-    SYMBOL_EXPRESSION_STATEMENT,
-    SYMBOL_IF_STATEMENT,
-    SYMBOL_ITERATION_STATEMENT,
-    SYMBOL_CONTINUE_STATEMENT,
-    SYMBOL_BREAK_STATEMENT,
-    SYMBOL_RETURN_STATEMENT,
-    SYMBOL_WITH_STATEMENT,
-    SYMBOL_LABELLED_STATEMENT,
-    SYMBOL_SWITCH_STATEMENT,
-    SYMBOL_THROW_STATEMENT,
-    SYMBOL_TRY_STATEMENT,
-    SYMBOL_NONE
-  };
-
-  *token = NULL;
-
-  for (i = 0; options[i] != SYMBOL_NONE; i++) {
-    status = parse (scanner, options[i], token);
-    if (status != STATUS_CANCEL)
-      return status;
-  }
-
-  return STATUS_CANCEL;
-}
-
-static ParseStatus
-parse_block (GScanner *scanner, ViviCodeToken **token)
-{
-  ViviCodeToken **list;
-
-  *token = NULL;
-
-  if (!check_token (scanner, '{'))
-    return STATUS_CANCEL;
-
-  list = NULL;
-
-  g_scanner_peek_next_token (scanner);
-  if (scanner->next_token != '}') {
-    if (parse_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
-	!= STATUS_OK)
-      return STATUS_FAIL;
-  }
-
-  if (!check_token (scanner, '}')) {
-    if (list != NULL)
-      free_list (list);
-    return STATUS_FAIL;
-  }
-
-  *token = VIVI_CODE_TOKEN (create_block (list));
-  free_list (list);
-
-  return STATUS_OK;
-}
-
-static ParseStatus
-parse_empty_statement (GScanner *scanner, ViviCodeToken **token)
-{
-  *token = NULL;
-
-  if (!check_token (scanner, ';'))
-    return STATUS_CANCEL;
-
-  *token = VIVI_CODE_TOKEN (vivi_code_empty_new ());
-
-  return STATUS_OK;
-}
-
-static ParseStatus
-parse_expression_statement (GScanner *scanner, ViviCodeToken **token)
-{
-  ParseStatus status;
-
-  *token = NULL;
-
-  g_scanner_peek_next_token (scanner);
-  if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
-    return STATUS_CANCEL;
-
-  status = parse (scanner, SYMBOL_EXPRESSION, token);
-  if (status != STATUS_OK)
-    return status;
-
-  if (!check_token (scanner, ';')) {
-    g_object_unref (*token);
-    *token = NULL;
-    return STATUS_FAIL;
-  }
-
-  return STATUS_OK;
-}
-
-// expression
-
-static ParseStatus
-parse_expression (GScanner *scanner, ViviCodeToken **token)
-{
-  ViviCodeToken **list;
-  ParseStatus status;
-
-  *token = NULL;
-
-  status = parse_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
-  if (status != STATUS_OK)
-    return status;
-
-  if (list[1] == NULL) {
-    *token = g_object_ref (list[0]);
-  } else {
-    *token = VIVI_CODE_TOKEN (create_block (list));
-  }
-
-  free_list (list);
-
-  return STATUS_OK;
-}
-
-static ParseStatus
-parse_assignment_expression (GScanner *scanner, ViviCodeToken **token)
-{
-  *token = NULL;
-
-  // TODO
-
-  return parse (scanner, SYMBOL_CONDITIONAL_EXPRESSION, token);
-}
-
-static ParseStatus
-parse_conditional_expression (GScanner *scanner, ViviCodeToken **token)
-{
-  ParseStatus status;
-  ViviCodeToken *value;
-  ViviCodeToken *first, *second;
-
-  *token = NULL;
-  first = NULL;
-
-  status = parse (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
-  if (status != STATUS_OK)
-    return status;
-
-  if (!check_token (scanner, '?')) {
-    *token = VIVI_CODE_TOKEN (
-	vivi_code_value_statement_new (VIVI_CODE_VALUE (value)));
-    g_object_unref (value);
-    return STATUS_OK;
-  }
-
-  if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &first) != STATUS_OK)
-    goto fail;
-
-  if (!check_token (scanner, ':'))
-    goto fail;
-
-  if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &second) != STATUS_OK)
-    goto fail;
-
-  //*token = vivi_code_condional_new (VIVI_CODE_VALUE (value),
-  //    VIVI_CODE_STATEMENT (first), VIVI_CODE_STATEMENT (second));
-
-  g_object_unref (value);
-  g_object_unref (first);
-  g_object_unref (second);
-
-  return STATUS_OK;
-
-fail:
-
-  g_object_unref (value);
-  if (first != NULL)
-    g_object_unref (first);
-
-  return STATUS_FAIL;
-}
-
-static ParseStatus
-parse_operator_expression (GScanner *scanner, ViviCodeToken **token)
-{
-  ParseStatus status;
-  ViviCodeValue *left;
-  ViviCodeToken *right;
-
-  *token = NULL;
-
-  status = parse (scanner, SYMBOL_UNARY_EXPRESSION, token);
-  if (status != STATUS_OK)
-    return status;
-
-  do {
-    if (!check_token (scanner, '+'))
-      return STATUS_OK;
-
-    if (parse (scanner, SYMBOL_UNARY_EXPRESSION, &right) != STATUS_OK) {
-      g_object_unref (*token);
-      *token = NULL;
-      return STATUS_FAIL;
-    }
-
-    left = VIVI_CODE_VALUE (token);
-    *token = VIVI_CODE_TOKEN (vivi_code_binary_new_name (left,
-	  VIVI_CODE_VALUE (right), "+"));
-    g_object_unref (left);
-    g_object_unref (right);
-  } while (TRUE);
-
-  g_object_unref (*token);
-  *token = NULL;
-
-  return STATUS_FAIL;
-}
-
-static ParseStatus
-parse_unary_expression (GScanner *scanner, ViviCodeToken **token)
-{
-  ViviCodeValue *value;
-
-  *token = NULL;
-
-  if (check_token (scanner, '!')) {
-    parse (scanner, SYMBOL_UNARY_EXPRESSION, token);
-    value = VIVI_CODE_VALUE (*token);
-    *token = VIVI_CODE_TOKEN (vivi_code_unary_new (value, '!'));
-    g_object_unref (value);
-    return STATUS_OK;
-  } else {
-    return parse (scanner, SYMBOL_POSTFIX_EXPRESSION, token);
-  }
-}
-
-static ParseStatus
-parse_postfix_expression (GScanner *scanner, ViviCodeToken **token)
-{
-  //ViviCodeValue *value;
-  ParseStatus status;
-
-  status = parse (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION, token);
-  if (status != STATUS_OK)
-    return status;
-
-  // FIXME: Don't allow new line here
-
-  /*if (check_token (scanner, TOKEN_PLUSPLUS)) {
-    value = VIVI_CODE_VALUE (*token);
-    *token = VIVI_CODE_TOKEN (vivi_code_postfix_new (value, "++"));
-    g_object_unref (value);
-  } else {*/
-    return STATUS_OK;
-  //}
-}
-
-static ParseStatus
-parse_left_hand_side_expression (GScanner *scanner, ViviCodeToken **token)
-{
-  ParseStatus status;
-
-  *token = NULL;
-
-  status = parse (scanner, SYMBOL_NEW_EXPRESSION, token);
-  if (status == STATUS_CANCEL)
-    status = parse (scanner, SYMBOL_CALL_EXPRESSION, token);
-
-  return status;
-}
-
-static ParseStatus
-parse_new_expression (GScanner *scanner, ViviCodeToken **token)
-{
-  *token = NULL;
-
-  if (check_token (scanner, TOKEN_NEW)) {
-    if (parse (scanner, SYMBOL_NEW_EXPRESSION, token) != STATUS_OK)
-      return STATUS_FAIL;
-    if (!VIVI_IS_CODE_FUNCTION_CALL (*token)) {
-      ViviCodeValue *value = VIVI_CODE_VALUE (*token);
-      *token = VIVI_CODE_TOKEN (vivi_code_function_call_new (NULL, value));
-      g_object_unref (value);
-    }
-    vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*token),
-	TRUE);
-    return STATUS_OK;
-  } else {
-    return parse (scanner, SYMBOL_MEMBER_EXPRESSION, token);
-  }
-}
-
-static ParseStatus
-parse_member_expression (GScanner *scanner, ViviCodeToken **token)
-{
-  ParseStatus status;
-  ViviCodeValue *value;
-  ViviCodeToken *member;
-
-  // TODO: new MemberExpression Arguments
-
-  status = parse (scanner, SYMBOL_PRIMARY_EXPRESSION, token);
-  if (status == STATUS_CANCEL)
-    status = parse (scanner, SYMBOL_FUNCTION_EXPRESSION, token);
-
-  if (status != 0)
-    return status;
-
-  do {
-    if (check_token (scanner, '[')) {
-      if (parse (scanner, SYMBOL_EXPRESSION, &member) != STATUS_OK)
-	return STATUS_FAIL;
-      if (!check_token (scanner, ']'))
-	return STATUS_FAIL;
-    } else if (check_token (scanner, '.')) {
-      if (parse (scanner, SYMBOL_IDENTIFIER, &member) != STATUS_OK)
-	return STATUS_FAIL;
-    } else {
-      return STATUS_OK;
-    }
-
-    value = VIVI_CODE_VALUE (token);
-    *token = VIVI_CODE_TOKEN (
-	vivi_code_get_new (value, VIVI_CODE_VALUE (member)));
-    g_object_unref (value);
-    g_object_unref (member);
-  } while (TRUE);
-
-  g_assert_not_reached ();
-  return STATUS_FAIL;
-}
-
-static ParseStatus
-parse_primary_expression (GScanner *scanner, ViviCodeToken **token)
-{
-  return parse (scanner, SYMBOL_IDENTIFIER, token);
-}
-
-// misc.
-
-static ParseStatus
-parse_identifier (GScanner *scanner, ViviCodeToken **token)
-{
-  *token = NULL;
-
-  if (!check_token (scanner, G_TOKEN_IDENTIFIER))
-    return STATUS_CANCEL;
-
-  *token =
-    VIVI_CODE_TOKEN (vivi_code_get_new_name (scanner->value.v_identifier));
-
-  return STATUS_OK;
-}
-
-// parsing
-
-static const struct {
-  ParseSymbol		id;
-  const char *		name;
-  ParseFunction		parse;
-} symbols[] = {
-  // top
-  { SYMBOL_SOURCE_ELEMENT, "SourceElement", parse_source_element },
-  // function
-  { SYMBOL_FUNCTION_DECLARATION, "FunctionDeclaration",
-    parse_function_declaration },
-  // statement
-  { SYMBOL_STATEMENT, "Statement", parse_statement },
-  { SYMBOL_BLOCK, "Block", parse_block },
-  { SYMBOL_EMPTY_STATEMENT, "EmptyStatement", parse_empty_statement },
-  { SYMBOL_EXPRESSION_STATEMENT, "ExpressionStatement",
-    parse_expression_statement },
-  // expression
-  { SYMBOL_EXPRESSION, "Expression", parse_expression },
-  { SYMBOL_ASSIGNMENT_EXPRESSION, "AssigmentExpression",
-    parse_assignment_expression },
-  { SYMBOL_CONDITIONAL_EXPRESSION, "ConditionalExpression",
-    parse_conditional_expression },
-  { SYMBOL_OPERATOR_EXPRESSION, "OperatorExpression",
-    parse_operator_expression },
-  { SYMBOL_UNARY_EXPRESSION, "UnaryExpression", parse_unary_expression },
-  { SYMBOL_POSTFIX_EXPRESSION, "PostfixExpression", parse_postfix_expression },
-  { SYMBOL_LEFT_HAND_SIDE_EXPRESSION, "LeftHandSideExpression",
-    parse_left_hand_side_expression },
-  { SYMBOL_NEW_EXPRESSION, "NewExpression", parse_new_expression },
-  { SYMBOL_MEMBER_EXPRESSION, "MemberExpression", parse_member_expression },
-  { SYMBOL_PRIMARY_EXPRESSION, "PrimaryExpression", parse_primary_expression },
-  // misc
-  { SYMBOL_IDENTIFIER, "Identifier", parse_identifier },
-  { SYMBOL_NONE, NULL, NULL }
-};
-
-static ParseStatus
-parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token)
-{
-  int i;
-
-  g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
-  g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
-  g_return_val_if_fail (token != NULL, STATUS_FAIL);
-
-  for (i = 0; symbols[i].id != SYMBOL_NONE; i++) {
-    if (symbols[i].id == symbol) {
-      ParseStatus status = symbols[i].parse (scanner, token);
-      g_assert ((status == STATUS_OK && VIVI_IS_CODE_TOKEN (*token)) ||
-	  (status != STATUS_OK && *token == NULL));
-      if (status != STATUS_CANCEL)
-	g_print (":%i: %s\n", status, symbols[i].name);
-      return status;
-    }
-  }
-
-  //g_assert_not_reached ();
-  return STATUS_CANCEL;
-}
-
-static ParseStatus
-parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
-    guint separator)
-{
-  GPtrArray *array;
-  ViviCodeToken *token;
-  ParseStatus ret;
-
-  g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
-  g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
-  g_return_val_if_fail (list != NULL, STATUS_FAIL);
-
-  ret = parse (scanner, symbol, &token);
-  if (ret != STATUS_OK)
-    return ret;
-
-  array = g_ptr_array_new ();
-
-  do {
-    g_ptr_array_add (array, token);
-
-    if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
-      break;
-
-    ret = parse (scanner, symbol, &token);
-    if (ret == STATUS_FAIL)
-      return STATUS_FAIL;
-  } while (ret == STATUS_OK);
-  g_ptr_array_add (array, NULL);
-
-  *list = (ViviCodeToken **)g_ptr_array_free (array, FALSE);
-
-  return STATUS_OK;
-}
-
-// main
+#include "vivi_compiler.h"
+#include "vivi_code_text_printer.h"
 
 int
 main (int argc, char *argv[])
 {
-  GScanner *scanner;
-  char *test_text;
-  gsize test_text_len;
-  int ret;
-  ViviCodeToken **list;
   SwfdecPlayer *player;
+  char *text;
+  gsize text_len;
+  ViviCodeStatement *statement;
 
   player = swfdec_player_new (NULL);
 
-  if (argc < 2) {
-    g_print ("Usage!\n");
+  if (argc != 2) {
+    g_printerr ("Usage: %s <filename>\n", argv[0]);
     return 1;
   }
 
-  if (!g_file_get_contents (argv[1], &test_text, &test_text_len, NULL)) {
+  if (!g_file_get_contents (argv[1], &text, &text_len, NULL)) {
     g_printerr ("Couldn't open file %s", argv[1]);
     return -1;
   }
 
-  scanner = g_scanner_new (NULL);
-
-  scanner->config->numbers_2_int = TRUE;
-  scanner->config->int_2_float = TRUE;
-  scanner->config->symbol_2_token = TRUE;
-
-  g_scanner_set_scope (scanner, 0);
-  g_scanner_scope_add_symbol (scanner, 0, "function",
-      GINT_TO_POINTER(TOKEN_FUNCTION));
-  g_scanner_scope_add_symbol (scanner, 0, "++",
-      GINT_TO_POINTER(TOKEN_PLUSPLUS));
-  g_scanner_scope_add_symbol (scanner, 0, "--",
-      GINT_TO_POINTER(TOKEN_MINUSMINUS));
-  g_scanner_scope_add_symbol (scanner, 0, "new", GINT_TO_POINTER(TOKEN_NEW));
-
-  scanner->input_name = argv[1];
-  g_scanner_input_text (scanner, test_text, test_text_len);
-
-
-  ret = parse_list (scanner, SYMBOL_SOURCE_ELEMENT, &list, G_TOKEN_NONE);
-  g_print ("%i: %i, %i\n", ret,
-      g_scanner_cur_line (scanner), g_scanner_cur_position (scanner));
-
-  g_scanner_peek_next_token (scanner);
-  while (scanner->next_token != G_TOKEN_EOF &&
-      scanner->next_token != G_TOKEN_ERROR)
-  {
-    g_scanner_get_next_token (scanner);
-    g_print (":: %i, %i :: ", g_scanner_cur_line (scanner),
-	g_scanner_cur_position (scanner));
-    switch ((int)scanner->token) {
-      case G_TOKEN_SYMBOL:
-	g_print ("SYMBOL\n");
-	break;
-      case G_TOKEN_FLOAT:
-	g_print ("Primitive: %f\n", scanner->value.v_float);
-	break;
-      case G_TOKEN_STRING:
-	g_print ("Primitive: \"%s\"\n", scanner->value.v_string);
-	break;
-      case G_TOKEN_NONE:
-	g_print ("NONE\n");
-	break;
-      case G_TOKEN_IDENTIFIER:
-	g_print ("Identifier: %s\n", scanner->value.v_identifier);
-	break;
-      default:
-	if (scanner->token > 0 && scanner->token < 256) {
-	  g_print ("%c\n", scanner->token);
-	} else {
-	  g_print ("TOKEN %i\n", scanner->token);
-	}
-	break;
-    }
-    g_scanner_peek_next_token (scanner);
+  statement = vivi_compile_text (text, text_len, argv[1]);
+  if (statement == NULL) {
+    g_printerr ("Compilation failed\n");
+    return -1;
+  } else {
+    ViviCodePrinter *printer = vivi_code_text_printer_new ();
+    vivi_code_printer_print_token (printer, VIVI_CODE_TOKEN (statement));
+    g_object_unref (printer);
+    return 0;
   }
-
-  g_scanner_destroy (scanner);
-
-  return 0;
 }
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
new file mode 100644
index 0000000..53d873c
--- /dev/null
+++ b/vivified/code/vivi_compiler.c
@@ -0,0 +1,743 @@
+/* Vivified
+ * Copyright (C) 2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "vivi_compiler.h"
+
+#include "vivi_code_assignment.h"
+#include "vivi_code_binary.h"
+#include "vivi_code_block.h"
+#include "vivi_code_break.h"
+#include "vivi_code_constant.h"
+#include "vivi_code_continue.h"
+#include "vivi_code_empty.h"
+#include "vivi_code_function.h"
+#include "vivi_code_function_call.h"
+#include "vivi_code_get.h"
+#include "vivi_code_get_url.h"
+#include "vivi_code_goto.h"
+#include "vivi_code_if.h"
+#include "vivi_code_init_object.h"
+#include "vivi_code_loop.h"
+#include "vivi_code_return.h"
+#include "vivi_code_trace.h"
+#include "vivi_code_unary.h"
+#include "vivi_code_value_statement.h"
+
+#include "vivi_code_text_printer.h"
+
+typedef enum {
+  STATUS_FAIL = -1,
+  STATUS_OK = 0,
+  STATUS_CANCEL = 1
+} ParseStatus;
+
+enum {
+  TOKEN_FUNCTION = G_TOKEN_LAST + 1,
+  TOKEN_PLUSPLUS = G_TOKEN_LAST + 2,
+  TOKEN_MINUSMINUS = G_TOKEN_LAST + 3,
+  TOKEN_NEW = G_TOKEN_LAST + 4
+};
+
+typedef enum {
+  SYMBOL_NONE,
+  // top
+  SYMBOL_PROGRAM,
+  SYMBOL_SOURCE_ELEMENT,
+  // function
+  SYMBOL_FUNCTION_DECLARATION,
+  // statement
+  SYMBOL_STATEMENT,
+  SYMBOL_BLOCK,
+  SYMBOL_VARIABLE_STATEMENT,
+  SYMBOL_EMPTY_STATEMENT,
+  SYMBOL_EXPRESSION_STATEMENT,
+  SYMBOL_IF_STATEMENT,
+  SYMBOL_ITERATION_STATEMENT,
+  SYMBOL_CONTINUE_STATEMENT,
+  SYMBOL_BREAK_STATEMENT,
+  SYMBOL_RETURN_STATEMENT,
+  SYMBOL_WITH_STATEMENT,
+  SYMBOL_LABELLED_STATEMENT,
+  SYMBOL_SWITCH_STATEMENT,
+  SYMBOL_THROW_STATEMENT,
+  SYMBOL_TRY_STATEMENT,
+  // expression
+  SYMBOL_EXPRESSION,
+  SYMBOL_ASSIGNMENT_EXPRESSION,
+  SYMBOL_CONDITIONAL_EXPRESSION,
+  SYMBOL_LEFT_HAND_SIDE_EXPRESSION,
+  SYMBOL_OPERATOR_EXPRESSION,
+  SYMBOL_UNARY_EXPRESSION,
+  SYMBOL_POSTFIX_EXPRESSION,
+  SYMBOL_NEW_EXPRESSION,
+  SYMBOL_CALL_EXPRESSION,
+  SYMBOL_MEMBER_EXPRESSION,
+  SYMBOL_FUNCTION_EXPRESSION,
+  SYMBOL_PRIMARY_EXPRESSION,
+  // misc
+  SYMBOL_IDENTIFIER,
+  SYMBOL_ASSIGNMENT_OPERATOR,
+  SYMBOL_ARGUMENTS,
+} ParseSymbol;
+
+typedef ParseStatus (*ParseFunction) (GScanner *scanner, ViviCodeToken **token);
+
+static ParseStatus
+parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token);
+
+static ParseStatus
+parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
+    guint separator);
+
+// helpers
+
+static gboolean
+check_token (GScanner *scanner, guint token)
+{
+  g_scanner_peek_next_token (scanner);
+  if (scanner->next_token != token)
+    return FALSE;
+  g_scanner_get_next_token (scanner);
+  return TRUE;
+}
+
+static void
+free_list (ViviCodeToken **list)
+{
+  int i;
+
+  for (i = 0; list[i] != NULL; i++) {
+    g_object_unref (list[i]);
+  }
+  g_free (list);
+}
+
+static ViviCodeBlock *
+create_block (ViviCodeToken **list)
+{
+  ViviCodeBlock *block;
+  int i;
+
+  block = VIVI_CODE_BLOCK (vivi_code_block_new ());
+
+  for (i = 0; list[i] != NULL; i++) {
+    vivi_code_block_add_statement (block, VIVI_CODE_STATEMENT (list[i]));
+  }
+
+  return block;
+}
+
+// top
+
+static ParseStatus
+parse_program (GScanner *scanner, ViviCodeToken **token)
+{
+  ParseStatus status;
+  ViviCodeToken **list;
+
+  *token = NULL;
+
+  status = parse_list (scanner, SYMBOL_SOURCE_ELEMENT, &list, G_TOKEN_NONE);
+  if (status != STATUS_OK)
+    return status;
+
+  *token = VIVI_CODE_TOKEN (create_block (list));
+
+  return STATUS_OK;
+}
+
+static ParseStatus
+parse_source_element (GScanner *scanner, ViviCodeToken **token)
+{
+  ParseStatus status;
+
+  *token = NULL;
+
+  status = parse (scanner, SYMBOL_FUNCTION_DECLARATION, token);
+
+  if (status == STATUS_CANCEL)
+    status = parse (scanner, SYMBOL_STATEMENT, token);
+
+  return status;
+}
+
+// function
+
+static ParseStatus
+parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
+{
+  //ViviCodeToken *function;
+  ViviCodeToken *identifier;
+  ViviCodeToken **arguments, **body;
+
+  *token = NULL;
+
+  identifier = NULL;
+  arguments = NULL;
+  body = NULL;
+
+  if (!check_token (scanner, TOKEN_FUNCTION))
+    return STATUS_CANCEL;
+
+  if (parse (scanner, SYMBOL_IDENTIFIER, &identifier) != STATUS_OK)
+    return STATUS_FAIL;
+
+  if (!check_token (scanner, '('))
+    goto fail;
+
+  if (parse_list (scanner, SYMBOL_IDENTIFIER, &arguments, ',') == STATUS_FAIL)
+    goto fail;
+
+  if (!check_token (scanner, ')'))
+    goto fail;
+
+  if (!check_token (scanner, '{'))
+    goto fail;
+
+  if (parse_list (scanner, SYMBOL_SOURCE_ELEMENT, &body, G_TOKEN_NONE)
+      == STATUS_FAIL)
+    goto fail;
+
+  if (!check_token (scanner, '}'))
+    goto fail;
+
+  /*function = vivi_code_function_new (arguments, body);
+  *token = VIVI_CODE_TOKEN (
+      vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
+      VIVI_CODE_VALUE (function)));*/
+  *token = VIVI_CODE_TOKEN (vivi_code_empty_new ());
+
+  g_object_unref (identifier);
+  if (arguments != NULL)
+    free_list (arguments);
+  if (body != NULL)
+    free_list (body);
+
+  return STATUS_OK;
+
+fail:
+  if (identifier != NULL)
+    g_object_unref (identifier);
+  if (arguments != NULL)
+    free_list (arguments);
+  if (body != NULL)
+    free_list (body);
+
+  return STATUS_FAIL;
+}
+
+// statement
+
+static ParseStatus
+parse_statement (GScanner *scanner, ViviCodeToken **token)
+{
+  int i, status;
+  ParseSymbol options[] = {
+    SYMBOL_BLOCK,
+    SYMBOL_VARIABLE_STATEMENT,
+    SYMBOL_EMPTY_STATEMENT,
+    SYMBOL_EXPRESSION_STATEMENT,
+    SYMBOL_IF_STATEMENT,
+    SYMBOL_ITERATION_STATEMENT,
+    SYMBOL_CONTINUE_STATEMENT,
+    SYMBOL_BREAK_STATEMENT,
+    SYMBOL_RETURN_STATEMENT,
+    SYMBOL_WITH_STATEMENT,
+    SYMBOL_LABELLED_STATEMENT,
+    SYMBOL_SWITCH_STATEMENT,
+    SYMBOL_THROW_STATEMENT,
+    SYMBOL_TRY_STATEMENT,
+    SYMBOL_NONE
+  };
+
+  *token = NULL;
+
+  for (i = 0; options[i] != SYMBOL_NONE; i++) {
+    status = parse (scanner, options[i], token);
+    if (status != STATUS_CANCEL)
+      return status;
+  }
+
+  return STATUS_CANCEL;
+}
+
+static ParseStatus
+parse_block (GScanner *scanner, ViviCodeToken **token)
+{
+  ViviCodeToken **list;
+
+  *token = NULL;
+
+  if (!check_token (scanner, '{'))
+    return STATUS_CANCEL;
+
+  list = NULL;
+
+  g_scanner_peek_next_token (scanner);
+  if (scanner->next_token != '}') {
+    if (parse_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
+	!= STATUS_OK)
+      return STATUS_FAIL;
+  }
+
+  if (!check_token (scanner, '}')) {
+    if (list != NULL)
+      free_list (list);
+    return STATUS_FAIL;
+  }
+
+  *token = VIVI_CODE_TOKEN (create_block (list));
+  free_list (list);
+
+  return STATUS_OK;
+}
+
+static ParseStatus
+parse_empty_statement (GScanner *scanner, ViviCodeToken **token)
+{
+  *token = NULL;
+
+  if (!check_token (scanner, ';'))
+    return STATUS_CANCEL;
+
+  *token = VIVI_CODE_TOKEN (vivi_code_empty_new ());
+
+  return STATUS_OK;
+}
+
+static ParseStatus
+parse_expression_statement (GScanner *scanner, ViviCodeToken **token)
+{
+  ParseStatus status;
+
+  *token = NULL;
+
+  g_scanner_peek_next_token (scanner);
+  if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
+    return STATUS_CANCEL;
+
+  status = parse (scanner, SYMBOL_EXPRESSION, token);
+  if (status != STATUS_OK)
+    return status;
+
+  if (!check_token (scanner, ';')) {
+    g_object_unref (*token);
+    *token = NULL;
+    return STATUS_FAIL;
+  }
+
+  return STATUS_OK;
+}
+
+// expression
+
+static ParseStatus
+parse_expression (GScanner *scanner, ViviCodeToken **token)
+{
+  ViviCodeToken **list;
+  ParseStatus status;
+
+  *token = NULL;
+
+  status = parse_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
+  if (status != STATUS_OK)
+    return status;
+
+  if (list[1] == NULL) {
+    *token = g_object_ref (list[0]);
+  } else {
+    *token = VIVI_CODE_TOKEN (create_block (list));
+  }
+
+  free_list (list);
+
+  return STATUS_OK;
+}
+
+static ParseStatus
+parse_assignment_expression (GScanner *scanner, ViviCodeToken **token)
+{
+  *token = NULL;
+
+  // TODO
+
+  return parse (scanner, SYMBOL_CONDITIONAL_EXPRESSION, token);
+}
+
+static ParseStatus
+parse_conditional_expression (GScanner *scanner, ViviCodeToken **token)
+{
+  ParseStatus status;
+  ViviCodeToken *value;
+  ViviCodeToken *first, *second;
+
+  *token = NULL;
+  first = NULL;
+
+  status = parse (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
+  if (status != STATUS_OK)
+    return status;
+
+  if (!check_token (scanner, '?')) {
+    *token = VIVI_CODE_TOKEN (
+	vivi_code_value_statement_new (VIVI_CODE_VALUE (value)));
+    g_object_unref (value);
+    return STATUS_OK;
+  }
+
+  if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &first) != STATUS_OK)
+    goto fail;
+
+  if (!check_token (scanner, ':'))
+    goto fail;
+
+  if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &second) != STATUS_OK)
+    goto fail;
+
+  //*token = vivi_code_condional_new (VIVI_CODE_VALUE (value),
+  //    VIVI_CODE_STATEMENT (first), VIVI_CODE_STATEMENT (second));
+
+  g_object_unref (value);
+  g_object_unref (first);
+  g_object_unref (second);
+
+  return STATUS_OK;
+
+fail:
+
+  g_object_unref (value);
+  if (first != NULL)
+    g_object_unref (first);
+
+  return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_operator_expression (GScanner *scanner, ViviCodeToken **token)
+{
+  ParseStatus status;
+  ViviCodeValue *left;
+  ViviCodeToken *right;
+
+  *token = NULL;
+
+  status = parse (scanner, SYMBOL_UNARY_EXPRESSION, token);
+  if (status != STATUS_OK)
+    return status;
+
+  do {
+    if (!check_token (scanner, '+'))
+      return STATUS_OK;
+
+    if (parse (scanner, SYMBOL_UNARY_EXPRESSION, &right) != STATUS_OK) {
+      g_object_unref (*token);
+      *token = NULL;
+      return STATUS_FAIL;
+    }
+
+    left = VIVI_CODE_VALUE (*token);
+    *token = VIVI_CODE_TOKEN (vivi_code_binary_new_name (left,
+	  VIVI_CODE_VALUE (right), "+"));
+    g_object_unref (left);
+    g_object_unref (right);
+  } while (TRUE);
+
+  g_object_unref (*token);
+  *token = NULL;
+
+  return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_unary_expression (GScanner *scanner, ViviCodeToken **token)
+{
+  ViviCodeValue *value;
+
+  *token = NULL;
+
+  if (check_token (scanner, '!')) {
+    parse (scanner, SYMBOL_UNARY_EXPRESSION, token);
+    value = VIVI_CODE_VALUE (*token);
+    *token = VIVI_CODE_TOKEN (vivi_code_unary_new (value, '!'));
+    g_object_unref (value);
+    return STATUS_OK;
+  } else {
+    return parse (scanner, SYMBOL_POSTFIX_EXPRESSION, token);
+  }
+}
+
+static ParseStatus
+parse_postfix_expression (GScanner *scanner, ViviCodeToken **token)
+{
+  //ViviCodeValue *value;
+  ParseStatus status;
+
+  status = parse (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION, token);
+  if (status != STATUS_OK)
+    return status;
+
+  // FIXME: Don't allow new line here
+
+  /*if (check_token (scanner, TOKEN_PLUSPLUS)) {
+    value = VIVI_CODE_VALUE (*token);
+    *token = VIVI_CODE_TOKEN (vivi_code_postfix_new (value, "++"));
+    g_object_unref (value);
+  } else {*/
+    return STATUS_OK;
+  //}
+}
+
+static ParseStatus
+parse_left_hand_side_expression (GScanner *scanner, ViviCodeToken **token)
+{
+  ParseStatus status;
+
+  *token = NULL;
+
+  status = parse (scanner, SYMBOL_NEW_EXPRESSION, token);
+  if (status == STATUS_CANCEL)
+    status = parse (scanner, SYMBOL_CALL_EXPRESSION, token);
+
+  return status;
+}
+
+static ParseStatus
+parse_new_expression (GScanner *scanner, ViviCodeToken **token)
+{
+  *token = NULL;
+
+  if (check_token (scanner, TOKEN_NEW)) {
+    if (parse (scanner, SYMBOL_NEW_EXPRESSION, token) != STATUS_OK)
+      return STATUS_FAIL;
+    if (!VIVI_IS_CODE_FUNCTION_CALL (*token)) {
+      ViviCodeValue *value = VIVI_CODE_VALUE (*token);
+      *token = VIVI_CODE_TOKEN (vivi_code_function_call_new (NULL, value));
+      g_object_unref (value);
+    }
+    vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*token),
+	TRUE);
+    return STATUS_OK;
+  } else {
+    return parse (scanner, SYMBOL_MEMBER_EXPRESSION, token);
+  }
+}
+
+static ParseStatus
+parse_member_expression (GScanner *scanner, ViviCodeToken **token)
+{
+  ParseStatus status;
+  ViviCodeValue *value;
+  ViviCodeToken *member;
+
+  // TODO: new MemberExpression Arguments
+
+  status = parse (scanner, SYMBOL_PRIMARY_EXPRESSION, token);
+  if (status == STATUS_CANCEL)
+    status = parse (scanner, SYMBOL_FUNCTION_EXPRESSION, token);
+
+  if (status != 0)
+    return status;
+
+  do {
+    if (check_token (scanner, '[')) {
+      if (parse (scanner, SYMBOL_EXPRESSION, &member) != STATUS_OK)
+	return STATUS_FAIL;
+      if (!check_token (scanner, ']'))
+	return STATUS_FAIL;
+    } else if (check_token (scanner, '.')) {
+      if (parse (scanner, SYMBOL_IDENTIFIER, &member) != STATUS_OK)
+	return STATUS_FAIL;
+    } else {
+      return STATUS_OK;
+    }
+
+    value = VIVI_CODE_VALUE (token);
+    *token = VIVI_CODE_TOKEN (
+	vivi_code_get_new (value, VIVI_CODE_VALUE (member)));
+    g_object_unref (value);
+    g_object_unref (member);
+  } while (TRUE);
+
+  g_assert_not_reached ();
+  return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_primary_expression (GScanner *scanner, ViviCodeToken **token)
+{
+  return parse (scanner, SYMBOL_IDENTIFIER, token);
+}
+
+// misc.
+
+static ParseStatus
+parse_identifier (GScanner *scanner, ViviCodeToken **token)
+{
+  *token = NULL;
+
+  if (!check_token (scanner, G_TOKEN_IDENTIFIER))
+    return STATUS_CANCEL;
+
+  *token =
+    VIVI_CODE_TOKEN (vivi_code_get_new_name (scanner->value.v_identifier));
+
+  return STATUS_OK;
+}
+
+// parsing
+
+static const struct {
+  ParseSymbol		id;
+  const char *		name;
+  ParseFunction		parse;
+} symbols[] = {
+  // top
+  { SYMBOL_PROGRAM, "Program", parse_program },
+  { SYMBOL_SOURCE_ELEMENT, "SourceElement", parse_source_element },
+  // function
+  { SYMBOL_FUNCTION_DECLARATION, "FunctionDeclaration",
+    parse_function_declaration },
+  // statement
+  { SYMBOL_STATEMENT, "Statement", parse_statement },
+  { SYMBOL_BLOCK, "Block", parse_block },
+  { SYMBOL_EMPTY_STATEMENT, "EmptyStatement", parse_empty_statement },
+  { SYMBOL_EXPRESSION_STATEMENT, "ExpressionStatement",
+    parse_expression_statement },
+  // expression
+  { SYMBOL_EXPRESSION, "Expression", parse_expression },
+  { SYMBOL_ASSIGNMENT_EXPRESSION, "AssigmentExpression",
+    parse_assignment_expression },
+  { SYMBOL_CONDITIONAL_EXPRESSION, "ConditionalExpression",
+    parse_conditional_expression },
+  { SYMBOL_OPERATOR_EXPRESSION, "OperatorExpression",
+    parse_operator_expression },
+  { SYMBOL_UNARY_EXPRESSION, "UnaryExpression", parse_unary_expression },
+  { SYMBOL_POSTFIX_EXPRESSION, "PostfixExpression", parse_postfix_expression },
+  { SYMBOL_LEFT_HAND_SIDE_EXPRESSION, "LeftHandSideExpression",
+    parse_left_hand_side_expression },
+  { SYMBOL_NEW_EXPRESSION, "NewExpression", parse_new_expression },
+  { SYMBOL_MEMBER_EXPRESSION, "MemberExpression", parse_member_expression },
+  { SYMBOL_PRIMARY_EXPRESSION, "PrimaryExpression", parse_primary_expression },
+  // misc
+  { SYMBOL_IDENTIFIER, "Identifier", parse_identifier },
+  { SYMBOL_NONE, NULL, NULL }
+};
+
+static ParseStatus
+parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token)
+{
+  int i;
+
+  g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
+  g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
+  g_return_val_if_fail (token != NULL, STATUS_FAIL);
+
+  for (i = 0; symbols[i].id != SYMBOL_NONE; i++) {
+    if (symbols[i].id == symbol) {
+      ParseStatus status = symbols[i].parse (scanner, token);
+      g_assert ((status == STATUS_OK && VIVI_IS_CODE_TOKEN (*token)) ||
+	  (status != STATUS_OK && *token == NULL));
+      return status;
+    }
+  }
+
+  //g_assert_not_reached ();
+  return STATUS_CANCEL;
+}
+
+static ParseStatus
+parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
+    guint separator)
+{
+  GPtrArray *array;
+  ViviCodeToken *token;
+  ParseStatus ret;
+
+  g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
+  g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
+  g_return_val_if_fail (list != NULL, STATUS_FAIL);
+
+  ret = parse (scanner, symbol, &token);
+  if (ret != STATUS_OK)
+    return ret;
+
+  array = g_ptr_array_new ();
+
+  do {
+    g_ptr_array_add (array, token);
+
+    if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
+      break;
+
+    ret = parse (scanner, symbol, &token);
+    if (ret == STATUS_FAIL)
+      return STATUS_FAIL;
+  } while (ret == STATUS_OK);
+  g_ptr_array_add (array, NULL);
+
+  *list = (ViviCodeToken **)g_ptr_array_free (array, FALSE);
+
+  return STATUS_OK;
+}
+
+// public
+
+ViviCodeStatement *
+vivi_compile_text (const char *text, gsize len, const char *input_name)
+{
+  GScanner *scanner;
+  ViviCodeToken *token;
+  ParseStatus status;
+
+  g_return_val_if_fail (text != NULL, NULL);
+
+  scanner = g_scanner_new (NULL);
+
+  scanner->config->numbers_2_int = TRUE;
+  scanner->config->int_2_float = TRUE;
+  scanner->config->symbol_2_token = TRUE;
+
+  g_scanner_set_scope (scanner, 0);
+  g_scanner_scope_add_symbol (scanner, 0, "function",
+      GINT_TO_POINTER(TOKEN_FUNCTION));
+  g_scanner_scope_add_symbol (scanner, 0, "++",
+      GINT_TO_POINTER(TOKEN_PLUSPLUS));
+  g_scanner_scope_add_symbol (scanner, 0, "--",
+      GINT_TO_POINTER(TOKEN_MINUSMINUS));
+  g_scanner_scope_add_symbol (scanner, 0, "new", GINT_TO_POINTER(TOKEN_NEW));
+
+  scanner->input_name = input_name;
+  g_scanner_input_text (scanner, text, len);
+
+  status = parse (scanner, SYMBOL_PROGRAM, &token);
+
+  g_scanner_destroy (scanner);
+
+  if (status == STATUS_OK) {
+    return VIVI_CODE_STATEMENT (token);
+  } else {
+    return NULL;
+  }
+}
diff --git a/vivified/code/vivi_compiler.h b/vivified/code/vivi_compiler.h
new file mode 100644
index 0000000..f15108a
--- /dev/null
+++ b/vivified/code/vivi_compiler.h
@@ -0,0 +1,35 @@
+/* Vivified
+ * Copyright (C) 2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _VIVI_DECOMPILER_H_
+#define _VIVI_DECOMPILER_H_
+
+#include <swfdec/swfdec.h>
+#include <vivified/code/vivi_code_statement.h>
+
+G_BEGIN_DECLS
+
+
+ViviCodeStatement *	vivi_compile_text		(const char *	text,
+							 gsize		len,
+							 const char *	input_name);
+
+
+G_END_DECLS
+#endif
commit 547fc557d07560337cdeabd5ed63bb7e943a792c
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Mar 28 17:40:29 2008 +0200

    Fix few bugs in the compiler code

diff --git a/vivified/code/compiler.c b/vivified/code/compiler.c
index 12d8495..f550b1e 100644
--- a/vivified/code/compiler.c
+++ b/vivified/code/compiler.c
@@ -167,7 +167,8 @@ parse_source_element (GScanner *scanner, ViviCodeToken **token)
 static ParseStatus
 parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
 {
-  ViviCodeToken *function, *identifier;
+  //ViviCodeToken *function;
+  ViviCodeToken *identifier;
   ViviCodeToken **arguments, **body;
 
   *token = NULL;
@@ -201,16 +202,17 @@ parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
   if (!check_token (scanner, '}'))
     goto fail;
 
-  //function = vivi_code_function_new (arguments, body);
-  function = NULL;
+  /*function = vivi_code_function_new (arguments, body);
   *token = VIVI_CODE_TOKEN (
       vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
-      VIVI_CODE_VALUE (function)));
+      VIVI_CODE_VALUE (function)));*/
+  *token = VIVI_CODE_TOKEN (vivi_code_empty_new ());
 
   g_object_unref (identifier);
   if (arguments != NULL)
     free_list (arguments);
-  free_list (body);
+  if (body != NULL)
+    free_list (body);
 
   return STATUS_OK;
 
@@ -336,12 +338,14 @@ parse_expression (GScanner *scanner, ViviCodeToken **token)
   ViviCodeToken **list;
   ParseStatus status;
 
+  *token = NULL;
+
   status = parse_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
   if (status != STATUS_OK)
     return status;
 
   if (list[1] == NULL) {
-    *token = list[0];
+    *token = g_object_ref (list[0]);
   } else {
     *token = VIVI_CODE_TOKEN (create_block (list));
   }
@@ -624,12 +628,18 @@ parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token)
 {
   int i;
 
+  g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
+  g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
+  g_return_val_if_fail (token != NULL, STATUS_FAIL);
+
   for (i = 0; symbols[i].id != SYMBOL_NONE; i++) {
     if (symbols[i].id == symbol) {
-      ParseStatus ret = symbols[i].parse (scanner, token);
-      if (ret != STATUS_CANCEL)
-	g_print (":%i: %s\n", ret, symbols[i].name);
-      return ret;
+      ParseStatus status = symbols[i].parse (scanner, token);
+      g_assert ((status == STATUS_OK && VIVI_IS_CODE_TOKEN (*token)) ||
+	  (status != STATUS_OK && *token == NULL));
+      if (status != STATUS_CANCEL)
+	g_print (":%i: %s\n", status, symbols[i].name);
+      return status;
     }
   }
 
@@ -645,6 +655,10 @@ parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
   ViviCodeToken *token;
   ParseStatus ret;
 
+  g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
+  g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
+  g_return_val_if_fail (list != NULL, STATUS_FAIL);
+
   ret = parse (scanner, symbol, &token);
   if (ret != STATUS_OK)
     return ret;
@@ -678,6 +692,9 @@ main (int argc, char *argv[])
   gsize test_text_len;
   int ret;
   ViviCodeToken **list;
+  SwfdecPlayer *player;
+
+  player = swfdec_player_new (NULL);
 
   if (argc < 2) {
     g_print ("Usage!\n");
commit a320e121301b8d41b6f33e0076f54f0b1c5bde09
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Mar 28 17:24:09 2008 +0200

    More work on the compiler

diff --git a/vivified/code/compiler.c b/vivified/code/compiler.c
index 2df22bf..12d8495 100644
--- a/vivified/code/compiler.c
+++ b/vivified/code/compiler.c
@@ -80,6 +80,7 @@ typedef enum {
   SYMBOL_THROW_STATEMENT,
   SYMBOL_TRY_STATEMENT,
   // expression
+  SYMBOL_EXPRESSION,
   SYMBOL_ASSIGNMENT_EXPRESSION,
   SYMBOL_CONDITIONAL_EXPRESSION,
   SYMBOL_LEFT_HAND_SIDE_EXPRESSION,
@@ -201,6 +202,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
     goto fail;
 
   //function = vivi_code_function_new (arguments, body);
+  function = NULL;
   *token = VIVI_CODE_TOKEN (
       vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
       VIVI_CODE_VALUE (function)));
@@ -305,7 +307,6 @@ parse_empty_statement (GScanner *scanner, ViviCodeToken **token)
 static ParseStatus
 parse_expression_statement (GScanner *scanner, ViviCodeToken **token)
 {
-  ViviCodeToken **list;
   ParseStatus status;
 
   *token = NULL;
@@ -314,22 +315,43 @@ parse_expression_statement (GScanner *scanner, ViviCodeToken **token)
   if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
     return STATUS_CANCEL;
 
-  status = parse_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
+  status = parse (scanner, SYMBOL_EXPRESSION, token);
+  if (status != STATUS_OK)
+    return status;
 
-  if (status == STATUS_OK) {
-    if (list[1] == NULL) {
-      *token = list[0];
-    } else {
-      *token = VIVI_CODE_TOKEN (create_block (list));
-    }
+  if (!check_token (scanner, ';')) {
+    g_object_unref (*token);
+    *token = NULL;
+    return STATUS_FAIL;
   }
 
-  return status;
+  return STATUS_OK;
 }
 
 // expression
 
 static ParseStatus
+parse_expression (GScanner *scanner, ViviCodeToken **token)
+{
+  ViviCodeToken **list;
+  ParseStatus status;
+
+  status = parse_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
+  if (status != STATUS_OK)
+    return status;
+
+  if (list[1] == NULL) {
+    *token = list[0];
+  } else {
+    *token = VIVI_CODE_TOKEN (create_block (list));
+  }
+
+  free_list (list);
+
+  return STATUS_OK;
+}
+
+static ParseStatus
 parse_assignment_expression (GScanner *scanner, ViviCodeToken **token)
 {
   *token = NULL;
@@ -526,7 +548,7 @@ parse_member_expression (GScanner *scanner, ViviCodeToken **token)
       return STATUS_OK;
     }
 
-    value = VIVI_CODE_VALUE (token)
+    value = VIVI_CODE_VALUE (token);
     *token = VIVI_CODE_TOKEN (
 	vivi_code_get_new (value, VIVI_CODE_VALUE (member)));
     g_object_unref (value);
@@ -553,16 +575,8 @@ parse_identifier (GScanner *scanner, ViviCodeToken **token)
   if (!check_token (scanner, G_TOKEN_IDENTIFIER))
     return STATUS_CANCEL;
 
-  *token = VIVI_CODE_TOKEN (vivi_code_get_new_name (scanner->value));
-
-  return STATUS_OK;
-}
-
-static ParseStatus
-parse_assignment_operator (GScanner *scanner)
-{
-  if (!check_token (scanner, '='))
-    return STATUS_CANCEL;
+  *token =
+    VIVI_CODE_TOKEN (vivi_code_get_new_name (scanner->value.v_identifier));
 
   return STATUS_OK;
 }
@@ -602,19 +616,17 @@ static const struct {
   { SYMBOL_PRIMARY_EXPRESSION, "PrimaryExpression", parse_primary_expression },
   // misc
   { SYMBOL_IDENTIFIER, "Identifier", parse_identifier },
-  { SYMBOL_ASSIGNMENT_OPERATOR, "AssignmentOperator",
-    parse_assignment_operator },
   { SYMBOL_NONE, NULL, NULL }
 };
 
-static ParseSymbol
-parse (GScanner *scanner, ParseSymbol symbol)
+static ParseStatus
+parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token)
 {
   int i;
 
   for (i = 0; symbols[i].id != SYMBOL_NONE; i++) {
     if (symbols[i].id == symbol) {
-      ParseSymbol ret = symbols[i].parse (scanner);
+      ParseStatus ret = symbols[i].parse (scanner, token);
       if (ret != STATUS_CANCEL)
 	g_print (":%i: %s\n", ret, symbols[i].name);
       return ret;
@@ -625,13 +637,13 @@ parse (GScanner *scanner, ParseSymbol symbol)
   return STATUS_CANCEL;
 }
 
-static ParseSymbol
+static ParseStatus
 parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
     guint separator)
 {
   GPtrArray *array;
   ViviCodeToken *token;
-  ParseSymbol ret;
+  ParseStatus ret;
 
   ret = parse (scanner, symbol, &token);
   if (ret != STATUS_OK)
@@ -651,7 +663,7 @@ parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
   } while (ret == STATUS_OK);
   g_ptr_array_add (array, NULL);
 
-  *list = g_ptr_array_free (array, FALSE);
+  *list = (ViviCodeToken **)g_ptr_array_free (array, FALSE);
 
   return STATUS_OK;
 }
@@ -665,6 +677,7 @@ main (int argc, char *argv[])
   char *test_text;
   gsize test_text_len;
   int ret;
+  ViviCodeToken **list;
 
   if (argc < 2) {
     g_print ("Usage!\n");
@@ -695,7 +708,7 @@ main (int argc, char *argv[])
   g_scanner_input_text (scanner, test_text, test_text_len);
 
 
-  ret = parse_list (scanner, SYMBOL_SOURCE_ELEMENT);
+  ret = parse_list (scanner, SYMBOL_SOURCE_ELEMENT, &list, G_TOKEN_NONE);
   g_print ("%i: %i, %i\n", ret,
       g_scanner_cur_line (scanner), g_scanner_cur_position (scanner));
 
commit 3e62fcd8d682d5764135acba972b10baa3622b8a
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Mar 28 16:38:35 2008 +0200

    Start creating ViviCode elements in complier code

diff --git a/vivified/code/compiler.c b/vivified/code/compiler.c
index 45e1af0..2df22bf 100644
--- a/vivified/code/compiler.c
+++ b/vivified/code/compiler.c
@@ -24,6 +24,26 @@
 #include <string.h>
 #include <swfdec/swfdec.h>
 
+#include "vivi_code_assignment.h"
+#include "vivi_code_binary.h"
+#include "vivi_code_block.h"
+#include "vivi_code_break.h"
+#include "vivi_code_constant.h"
+#include "vivi_code_continue.h"
+#include "vivi_code_empty.h"
+#include "vivi_code_function.h"
+#include "vivi_code_function_call.h"
+#include "vivi_code_get.h"
+#include "vivi_code_get_url.h"
+#include "vivi_code_goto.h"
+#include "vivi_code_if.h"
+#include "vivi_code_init_object.h"
+#include "vivi_code_loop.h"
+#include "vivi_code_return.h"
+#include "vivi_code_trace.h"
+#include "vivi_code_unary.h"
+#include "vivi_code_value_statement.h"
+
 typedef enum {
   STATUS_FAIL = -1,
   STATUS_OK = 0,
@@ -60,7 +80,6 @@ typedef enum {
   SYMBOL_THROW_STATEMENT,
   SYMBOL_TRY_STATEMENT,
   // expression
-  SYMBOL_EXPRESSION,
   SYMBOL_ASSIGNMENT_EXPRESSION,
   SYMBOL_CONDITIONAL_EXPRESSION,
   SYMBOL_LEFT_HAND_SIDE_EXPRESSION,
@@ -78,10 +97,14 @@ typedef enum {
   SYMBOL_ARGUMENTS,
 } ParseSymbol;
 
-typedef ParseStatus (*ParseFunction) (GScanner *scanner);
+typedef ParseStatus (*ParseFunction) (GScanner *scanner, ViviCodeToken **token);
 
-static ParseStatus parse (GScanner *scanner, ParseSymbol symbol);
-static ParseStatus parse_list (GScanner *scanner, ParseSymbol symbol);
+static ParseStatus
+parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token);
+
+static ParseStatus
+parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
+    guint separator);
 
 // helpers
 
@@ -95,17 +118,45 @@ check_token (GScanner *scanner, guint token)
   return TRUE;
 }
 
+static void
+free_list (ViviCodeToken **list)
+{
+  int i;
+
+  for (i = 0; list[i] != NULL; i++) {
+    g_object_unref (list[i]);
+  }
+  g_free (list);
+}
+
+static ViviCodeBlock *
+create_block (ViviCodeToken **list)
+{
+  ViviCodeBlock *block;
+  int i;
+
+  block = VIVI_CODE_BLOCK (vivi_code_block_new ());
+
+  for (i = 0; list[i] != NULL; i++) {
+    vivi_code_block_add_statement (block, VIVI_CODE_STATEMENT (list[i]));
+  }
+
+  return block;
+}
+
 // top
 
 static ParseStatus
-parse_source_element (GScanner *scanner)
+parse_source_element (GScanner *scanner, ViviCodeToken **token)
 {
   ParseStatus status;
 
-  status = parse (scanner, SYMBOL_FUNCTION_DECLARATION);
+  *token = NULL;
+
+  status = parse (scanner, SYMBOL_FUNCTION_DECLARATION, token);
 
   if (status == STATUS_CANCEL)
-    status = parse (scanner, SYMBOL_STATEMENT);
+    status = parse (scanner, SYMBOL_STATEMENT, token);
 
   return status;
 }
@@ -113,39 +164,69 @@ parse_source_element (GScanner *scanner)
 // function
 
 static ParseStatus
-parse_function_declaration (GScanner *scanner)
+parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
 {
+  ViviCodeToken *function, *identifier;
+  ViviCodeToken **arguments, **body;
+
+  *token = NULL;
+
+  identifier = NULL;
+  arguments = NULL;
+  body = NULL;
+
   if (!check_token (scanner, TOKEN_FUNCTION))
     return STATUS_CANCEL;
 
-  if (parse (scanner, SYMBOL_IDENTIFIER) != STATUS_OK)
+  if (parse (scanner, SYMBOL_IDENTIFIER, &identifier) != STATUS_OK)
     return STATUS_FAIL;
 
   if (!check_token (scanner, '('))
-    return STATUS_FAIL;
+    goto fail;
 
-  if (parse_list (scanner, SYMBOL_IDENTIFIER) == STATUS_FAIL)
-    return STATUS_FAIL;
+  if (parse_list (scanner, SYMBOL_IDENTIFIER, &arguments, ',') == STATUS_FAIL)
+    goto fail;
 
   if (!check_token (scanner, ')'))
-    return STATUS_FAIL;
+    goto fail;
 
   if (!check_token (scanner, '{'))
-    return STATUS_FAIL;
+    goto fail;
 
-  if (parse_list (scanner, SYMBOL_SOURCE_ELEMENT) == STATUS_FAIL)
-    return STATUS_FAIL;
+  if (parse_list (scanner, SYMBOL_SOURCE_ELEMENT, &body, G_TOKEN_NONE)
+      == STATUS_FAIL)
+    goto fail;
 
   if (!check_token (scanner, '}'))
-    return STATUS_FAIL;
+    goto fail;
+
+  //function = vivi_code_function_new (arguments, body);
+  *token = VIVI_CODE_TOKEN (
+      vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
+      VIVI_CODE_VALUE (function)));
+
+  g_object_unref (identifier);
+  if (arguments != NULL)
+    free_list (arguments);
+  free_list (body);
 
   return STATUS_OK;
+
+fail:
+  if (identifier != NULL)
+    g_object_unref (identifier);
+  if (arguments != NULL)
+    free_list (arguments);
+  if (body != NULL)
+    free_list (body);
+
+  return STATUS_FAIL;
 }
 
 // statement
 
 static ParseStatus
-parse_statement (GScanner *scanner)
+parse_statement (GScanner *scanner, ViviCodeToken **token)
 {
   int i, status;
   ParseSymbol options[] = {
@@ -166,8 +247,10 @@ parse_statement (GScanner *scanner)
     SYMBOL_NONE
   };
 
+  *token = NULL;
+
   for (i = 0; options[i] != SYMBOL_NONE; i++) {
-    status = parse (scanner, options[i]);
+    status = parse (scanner, options[i], token);
     if (status != STATUS_CANCEL)
       return status;
   }
@@ -176,225 +259,278 @@ parse_statement (GScanner *scanner)
 }
 
 static ParseStatus
-parse_block (GScanner *scanner)
+parse_block (GScanner *scanner, ViviCodeToken **token)
 {
+  ViviCodeToken **list;
+
+  *token = NULL;
+
   if (!check_token (scanner, '{'))
     return STATUS_CANCEL;
 
+  list = NULL;
+
   g_scanner_peek_next_token (scanner);
   if (scanner->next_token != '}') {
-    if (parse_list (scanner, SYMBOL_STATEMENT) != STATUS_OK)
+    if (parse_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
+	!= STATUS_OK)
       return STATUS_FAIL;
   }
 
-  if (!check_token (scanner, '}'))
+  if (!check_token (scanner, '}')) {
+    if (list != NULL)
+      free_list (list);
     return STATUS_FAIL;
+  }
+
+  *token = VIVI_CODE_TOKEN (create_block (list));
+  free_list (list);
 
   return STATUS_OK;
 }
 
 static ParseStatus
-parse_empty_statement (GScanner *scanner)
+parse_empty_statement (GScanner *scanner, ViviCodeToken **token)
 {
+  *token = NULL;
+
   if (!check_token (scanner, ';'))
     return STATUS_CANCEL;
 
+  *token = VIVI_CODE_TOKEN (vivi_code_empty_new ());
+
   return STATUS_OK;
 }
 
 static ParseStatus
-parse_expression_statement (GScanner *scanner)
+parse_expression_statement (GScanner *scanner, ViviCodeToken **token)
 {
+  ViviCodeToken **list;
+  ParseStatus status;
+
+  *token = NULL;
+
   g_scanner_peek_next_token (scanner);
   if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
     return STATUS_CANCEL;
 
-  return parse (scanner, SYMBOL_EXPRESSION);
+  status = parse_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
+
+  if (status == STATUS_OK) {
+    if (list[1] == NULL) {
+      *token = list[0];
+    } else {
+      *token = VIVI_CODE_TOKEN (create_block (list));
+    }
+  }
+
+  return status;
 }
 
 // expression
 
 static ParseStatus
-parse_expression (GScanner *scanner)
+parse_assignment_expression (GScanner *scanner, ViviCodeToken **token)
 {
-  ParseStatus status;
+  *token = NULL;
 
-  status = parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION);
-  if (status != STATUS_OK)
-    return status;
-
-  do {
-    if (!check_token (scanner, ','))
-      return STATUS_OK;
-  } while (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION) == STATUS_OK);
+  // TODO
 
-  return STATUS_FAIL;
+  return parse (scanner, SYMBOL_CONDITIONAL_EXPRESSION, token);
 }
 
 static ParseStatus
-parse_assignment_expression (GScanner *scanner)
+parse_conditional_expression (GScanner *scanner, ViviCodeToken **token)
 {
   ParseStatus status;
+  ViviCodeToken *value;
+  ViviCodeToken *first, *second;
 
-  status = parse (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION);
-  if (status == STATUS_OK) {
-    status = parse (scanner, SYMBOL_ASSIGNMENT_OPERATOR);
-    if (status == STATUS_CANCEL)
-      return STATUS_OK;
-    if (status == STATUS_FAIL)
-      return STATUS_FAIL;
-    if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION) != STATUS_OK)
-      return STATUS_FAIL;
-    return STATUS_OK;
-  } else if (status == STATUS_CANCEL) {
-    return parse (scanner, SYMBOL_CONDITIONAL_EXPRESSION);
-  } else {
-    return STATUS_FAIL;
-  }
-}
-
-static ParseStatus
-parse_conditional_expression (GScanner *scanner)
-{
-  ParseStatus status;
+  *token = NULL;
+  first = NULL;
 
-  status = parse (scanner, SYMBOL_OPERATOR_EXPRESSION);
+  status = parse (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
   if (status != STATUS_OK)
     return status;
 
-  if (!check_token (scanner, '?'))
+  if (!check_token (scanner, '?')) {
+    *token = VIVI_CODE_TOKEN (
+	vivi_code_value_statement_new (VIVI_CODE_VALUE (value)));
+    g_object_unref (value);
     return STATUS_OK;
+  }
 
-  if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION) != STATUS_OK)
-    return STATUS_FAIL;
+  if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &first) != STATUS_OK)
+    goto fail;
 
   if (!check_token (scanner, ':'))
-    return STATUS_FAIL;
+    goto fail;
 
-  if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION) != STATUS_OK)
-    return STATUS_FAIL;
+  if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &second) != STATUS_OK)
+    goto fail;
+
+  //*token = vivi_code_condional_new (VIVI_CODE_VALUE (value),
+  //    VIVI_CODE_STATEMENT (first), VIVI_CODE_STATEMENT (second));
+
+  g_object_unref (value);
+  g_object_unref (first);
+  g_object_unref (second);
 
   return STATUS_OK;
+
+fail:
+
+  g_object_unref (value);
+  if (first != NULL)
+    g_object_unref (first);
+
+  return STATUS_FAIL;
 }
 
 static ParseStatus
-parse_operator_expression (GScanner *scanner)
+parse_operator_expression (GScanner *scanner, ViviCodeToken **token)
 {
   ParseStatus status;
+  ViviCodeValue *left;
+  ViviCodeToken *right;
+
+  *token = NULL;
 
-  status = parse (scanner, SYMBOL_UNARY_EXPRESSION);
+  status = parse (scanner, SYMBOL_UNARY_EXPRESSION, token);
   if (status != STATUS_OK)
     return status;
 
   do {
     if (!check_token (scanner, '+'))
       return STATUS_OK;
-  } while (parse (scanner, SYMBOL_UNARY_EXPRESSION) == STATUS_OK);
+
+    if (parse (scanner, SYMBOL_UNARY_EXPRESSION, &right) != STATUS_OK) {
+      g_object_unref (*token);
+      *token = NULL;
+      return STATUS_FAIL;
+    }
+
+    left = VIVI_CODE_VALUE (token);
+    *token = VIVI_CODE_TOKEN (vivi_code_binary_new_name (left,
+	  VIVI_CODE_VALUE (right), "+"));
+    g_object_unref (left);
+    g_object_unref (right);
+  } while (TRUE);
+
+  g_object_unref (*token);
+  *token = NULL;
 
   return STATUS_FAIL;
 }
 
 static ParseStatus
-parse_unary_expression (GScanner *scanner)
+parse_unary_expression (GScanner *scanner, ViviCodeToken **token)
 {
-  ParseStatus status;
-
-  status = parse (scanner, SYMBOL_POSTFIX_EXPRESSION);
-  if (status != STATUS_OK)
-    return status;
+  ViviCodeValue *value;
 
-  do {
-    if (!check_token (scanner, '!'))
-      return STATUS_OK;
-  } while (parse (scanner, SYMBOL_POSTFIX_EXPRESSION) == STATUS_OK);
+  *token = NULL;
 
-  return STATUS_FAIL;
+  if (check_token (scanner, '!')) {
+    parse (scanner, SYMBOL_UNARY_EXPRESSION, token);
+    value = VIVI_CODE_VALUE (*token);
+    *token = VIVI_CODE_TOKEN (vivi_code_unary_new (value, '!'));
+    g_object_unref (value);
+    return STATUS_OK;
+  } else {
+    return parse (scanner, SYMBOL_POSTFIX_EXPRESSION, token);
+  }
 }
 
 static ParseStatus
-parse_postfix_expression (GScanner *scanner)
+parse_postfix_expression (GScanner *scanner, ViviCodeToken **token)
 {
+  //ViviCodeValue *value;
   ParseStatus status;
 
-  status = parse (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION);
+  status = parse (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION, token);
   if (status != STATUS_OK)
     return status;
 
-  // don't allow new line here
+  // FIXME: Don't allow new line here
 
-  g_scanner_peek_next_token (scanner);
-  if (scanner->next_token == TOKEN_PLUSPLUS ||
-      scanner->next_token == TOKEN_MINUSMINUS) {
-    g_scanner_get_next_token (scanner);
+  /*if (check_token (scanner, TOKEN_PLUSPLUS)) {
+    value = VIVI_CODE_VALUE (*token);
+    *token = VIVI_CODE_TOKEN (vivi_code_postfix_new (value, "++"));
+    g_object_unref (value);
+  } else {*/
     return STATUS_OK;
-  }
-
-  return STATUS_OK;
+  //}
 }
 
 static ParseStatus
-parse_left_hand_side_expression (GScanner *scanner)
+parse_left_hand_side_expression (GScanner *scanner, ViviCodeToken **token)
 {
   ParseStatus status;
 
-  status = parse (scanner, SYMBOL_NEW_EXPRESSION);
+  *token = NULL;
+
+  status = parse (scanner, SYMBOL_NEW_EXPRESSION, token);
   if (status == STATUS_CANCEL)
-    status = parse (scanner, SYMBOL_CALL_EXPRESSION);
+    status = parse (scanner, SYMBOL_CALL_EXPRESSION, token);
 
   return status;
 }
 
 static ParseStatus
-parse_new_expression (GScanner *scanner)
+parse_new_expression (GScanner *scanner, ViviCodeToken **token)
 {
-  g_scanner_peek_next_token (scanner);
-  if (scanner->next_token == TOKEN_NEW) {
-    g_scanner_get_next_token (scanner);
-    if (parse (scanner, SYMBOL_NEW_EXPRESSION) != STATUS_OK)
+  *token = NULL;
+
+  if (check_token (scanner, TOKEN_NEW)) {
+    if (parse (scanner, SYMBOL_NEW_EXPRESSION, token) != STATUS_OK)
       return STATUS_FAIL;
+    if (!VIVI_IS_CODE_FUNCTION_CALL (*token)) {
+      ViviCodeValue *value = VIVI_CODE_VALUE (*token);
+      *token = VIVI_CODE_TOKEN (vivi_code_function_call_new (NULL, value));
+      g_object_unref (value);
+    }
+    vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*token),
+	TRUE);
     return STATUS_OK;
   } else {
-    return parse (scanner, SYMBOL_MEMBER_EXPRESSION);
+    return parse (scanner, SYMBOL_MEMBER_EXPRESSION, token);
   }
 }
 
 static ParseStatus
-parse_member_expression (GScanner *scanner)
+parse_member_expression (GScanner *scanner, ViviCodeToken **token)
 {
   ParseStatus status;
+  ViviCodeValue *value;
+  ViviCodeToken *member;
 
-  g_scanner_peek_next_token (scanner);
-  if (scanner->next_token == TOKEN_NEW) {
-    g_scanner_get_next_token (scanner);
-    if (parse (scanner, SYMBOL_MEMBER_EXPRESSION) != STATUS_OK)
-      return STATUS_FAIL;
-    if (parse (scanner, SYMBOL_ARGUMENTS) != STATUS_OK)
-      return STATUS_FAIL;
-    return STATUS_OK;
-  }
+  // TODO: new MemberExpression Arguments
 
-  status = parse (scanner, SYMBOL_PRIMARY_EXPRESSION);
+  status = parse (scanner, SYMBOL_PRIMARY_EXPRESSION, token);
   if (status == STATUS_CANCEL)
-    status = parse (scanner, SYMBOL_FUNCTION_EXPRESSION);
+    status = parse (scanner, SYMBOL_FUNCTION_EXPRESSION, token);
 
   if (status != 0)
     return status;
 
   do {
-    g_scanner_peek_next_token (scanner);
-    if (scanner->next_token == '[') {
-      g_scanner_get_next_token (scanner);
-      if (parse (scanner, SYMBOL_EXPRESSION) != STATUS_OK)
+    if (check_token (scanner, '[')) {
+      if (parse (scanner, SYMBOL_EXPRESSION, &member) != STATUS_OK)
 	return STATUS_FAIL;
       if (!check_token (scanner, ']'))
 	return STATUS_FAIL;
-    } else if (scanner->next_token == '.') {
-      g_scanner_get_next_token (scanner);
-      if (parse (scanner, SYMBOL_IDENTIFIER) != STATUS_OK)
+    } else if (check_token (scanner, '.')) {
+      if (parse (scanner, SYMBOL_IDENTIFIER, &member) != STATUS_OK)
 	return STATUS_FAIL;
     } else {
       return STATUS_OK;
     }
+
+    value = VIVI_CODE_VALUE (token)
+    *token = VIVI_CODE_TOKEN (
+	vivi_code_get_new (value, VIVI_CODE_VALUE (member)));
+    g_object_unref (value);
+    g_object_unref (member);
   } while (TRUE);
 
   g_assert_not_reached ();
@@ -402,19 +538,23 @@ parse_member_expression (GScanner *scanner)
 }
 
 static ParseStatus
-parse_primary_expression (GScanner *scanner)
+parse_primary_expression (GScanner *scanner, ViviCodeToken **token)
 {
-  return parse (scanner, SYMBOL_IDENTIFIER);
+  return parse (scanner, SYMBOL_IDENTIFIER, token);
 }
 
 // misc.
 
 static ParseStatus
-parse_identifier (GScanner *scanner)
+parse_identifier (GScanner *scanner, ViviCodeToken **token)
 {
+  *token = NULL;
+
   if (!check_token (scanner, G_TOKEN_IDENTIFIER))
     return STATUS_CANCEL;
 
+  *token = VIVI_CODE_TOKEN (vivi_code_get_new_name (scanner->value));
+
   return STATUS_OK;
 }
 
@@ -467,40 +607,53 @@ static const struct {
   { SYMBOL_NONE, NULL, NULL }
 };
 
-static int
+static ParseSymbol
 parse (GScanner *scanner, ParseSymbol symbol)
 {
   int i;
 
   for (i = 0; symbols[i].id != SYMBOL_NONE; i++) {
     if (symbols[i].id == symbol) {
-      int ret = symbols[i].parse (scanner);
-      if (ret != 1)
+      ParseSymbol ret = symbols[i].parse (scanner);
+      if (ret != STATUS_CANCEL)
 	g_print (":%i: %s\n", ret, symbols[i].name);
       return ret;
     }
   }
 
   //g_assert_not_reached ();
-  return 1;
+  return STATUS_CANCEL;
 }
 
-static gboolean
-parse_list (GScanner *scanner, ParseSymbol symbol)
+static ParseSymbol
+parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
+    guint separator)
 {
-  int ret;
+  GPtrArray *array;
+  ViviCodeToken *token;
+  ParseSymbol ret;
 
-  ret = parse (scanner, symbol);
-  if (ret != 0)
+  ret = parse (scanner, symbol, &token);
+  if (ret != STATUS_OK)
     return ret;
 
+  array = g_ptr_array_new ();
+
   do {
-    ret = parse (scanner, symbol);
-    if (ret == -1)
-      return -1;
-  } while (ret == 0);
+    g_ptr_array_add (array, token);
 
-  return 0;
+    if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
+      break;
+
+    ret = parse (scanner, symbol, &token);
+    if (ret == STATUS_FAIL)
+      return STATUS_FAIL;
+  } while (ret == STATUS_OK);
+  g_ptr_array_add (array, NULL);
+
+  *list = g_ptr_array_free (array, FALSE);
+
+  return STATUS_OK;
 }
 
 // main
commit 20a1e8a41aa9bac648433bdbeeff093c62d02811
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Mar 28 14:23:10 2008 +0200

    Add a ViviCodeEmpty class for empty statements

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index 9185680..a731138 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -13,6 +13,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_comment.c \
 	vivi_code_constant.c \
 	vivi_code_continue.c \
+	vivi_code_empty.c \
 	vivi_code_function.c \
 	vivi_code_function_call.c \
 	vivi_code_get.c \
@@ -45,6 +46,7 @@ noinst_HEADERS = \
 	vivi_code_comment.h \
 	vivi_code_constant.h \
 	vivi_code_continue.h \
+	vivi_code_empty.h \
 	vivi_code_function.h \
 	vivi_code_function_call.h \
 	vivi_code_get.h \
diff --git a/vivified/code/vivi_code_empty.c b/vivified/code/vivi_code_empty.c
new file mode 100644
index 0000000..cf56456
--- /dev/null
+++ b/vivified/code/vivi_code_empty.c
@@ -0,0 +1,75 @@
+/* Vivified
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ *               2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "vivi_code_empty.h"
+#include "vivi_code_printer.h"
+
+G_DEFINE_TYPE (ViviCodeEmpty, vivi_code_empty, VIVI_TYPE_CODE_STATEMENT)
+
+static ViviCodeStatement *
+vivi_code_empty_optimize (ViviCodeStatement *statement)
+{
+  // FIXME
+  return statement;
+}
+
+static gboolean
+vivi_code_empty_needs_braces (ViviCodeStatement *stmt)
+{
+  return FALSE;
+}
+
+static void
+vivi_code_empty_print (ViviCodeToken *token, ViviCodePrinter *printer)
+{
+  vivi_code_printer_print (printer, ";");
+  vivi_code_printer_new_line (printer, FALSE);
+}
+
+static void
+vivi_code_empty_class_init (ViviCodeEmptyClass *klass)
+{
+  ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+  ViviCodeStatementClass *statement_class = VIVI_CODE_STATEMENT_CLASS (klass);
+
+  token_class->print = vivi_code_empty_print;
+
+  statement_class->optimize = vivi_code_empty_optimize;
+  statement_class->needs_braces = vivi_code_empty_needs_braces;
+}
+
+static void
+vivi_code_empty_init (ViviCodeEmpty *token)
+{
+}
+
+ViviCodeStatement *
+vivi_code_empty_new (void)
+{
+  ViviCodeEmpty *stmt;
+
+  stmt = g_object_new (VIVI_TYPE_CODE_EMPTY, NULL);
+
+  return VIVI_CODE_STATEMENT (stmt);
+}
diff --git a/vivified/code/vivi_code_empty.h b/vivified/code/vivi_code_empty.h
new file mode 100644
index 0000000..48dc126
--- /dev/null
+++ b/vivified/code/vivi_code_empty.h
@@ -0,0 +1,56 @@
+/* Vivified
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ *               2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifndef _VIVI_CODE_EMPTY_H_
+#define _VIVI_CODE_EMPTY_H_
+
+#include <vivified/code/vivi_code_statement.h>
+#include <vivified/code/vivi_code_value.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCodeEmpty ViviCodeEmpty;
+typedef struct _ViviCodeEmptyClass ViviCodeEmptyClass;
+
+#define VIVI_TYPE_CODE_EMPTY                    (vivi_code_empty_get_type())
+#define VIVI_IS_CODE_EMPTY(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_EMPTY))
+#define VIVI_IS_CODE_EMPTY_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_EMPTY))
+#define VIVI_CODE_EMPTY(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_EMPTY, ViviCodeEmpty))
+#define VIVI_CODE_EMPTY_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_EMPTY, ViviCodeEmptyClass))
+#define VIVI_CODE_EMPTY_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_EMPTY, ViviCodeEmptyClass))
+
+struct _ViviCodeEmpty
+{
+  ViviCodeStatement	statement;
+};
+
+struct _ViviCodeEmptyClass
+{
+  ViviCodeStatementClass	statement_class;
+};
+
+GType			vivi_code_empty_get_type	(void);
+
+ViviCodeStatement *	vivi_code_empty_new		(void);
+
+
+G_END_DECLS
+#endif
commit 552f3d6d72f093c3df56aa619e0745472b6097a2
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Mar 28 11:13:24 2008 +0200

    Make the compiler build and add a copyright header

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index 786c688..9185680 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -71,7 +71,7 @@ noinst_HEADERS = \
 	vivified-compiler.h
 
 
-noinst_PROGRAMS = vivi-decompile
+noinst_PROGRAMS = vivi-decompile vivi-compile
 
 vivi_decompile_SOURCES = \
 	decompiler.c
@@ -79,3 +79,10 @@ vivi_decompile_SOURCES = \
 vivi_decompile_CFLAGS =  $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS)
 vivi_decompile_LDFLAGS = $(SWFDEC_LIBS)
 vivi_decompile_LDADD = libvivified-compiler.la
+
+vivi_compile_SOURCES = \
+	compiler.c
+
+vivi_compile_CFLAGS =  $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS)
+vivi_compile_LDFLAGS = $(SWFDEC_LIBS)
+vivi_compile_LDADD = libvivified-compiler.la
diff --git a/vivified/code/compiler.c b/vivified/code/compiler.c
index 7e386ef..45e1af0 100644
--- a/vivified/code/compiler.c
+++ b/vivified/code/compiler.c
@@ -1,5 +1,28 @@
-#include <glib.h>
+/* Vivified
+ * Copyright (C) 2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
+ * Boston, MA  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <string.h>
+#include <swfdec/swfdec.h>
 
 typedef enum {
   STATUS_FAIL = -1,
@@ -530,7 +553,7 @@ main (int argc, char *argv[])
     g_scanner_get_next_token (scanner);
     g_print (":: %i, %i :: ", g_scanner_cur_line (scanner),
 	g_scanner_cur_position (scanner));
-    switch (scanner->token) {
+    switch ((int)scanner->token) {
       case G_TOKEN_SYMBOL:
 	g_print ("SYMBOL\n");
 	break;
commit 57039838368dd04377ca4dd14dbee5229d26b7b2
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Mar 28 11:06:48 2008 +0200

    Start work on a ActionScript compiler

diff --git a/vivified/code/compiler.c b/vivified/code/compiler.c
new file mode 100644
index 0000000..7e386ef
--- /dev/null
+++ b/vivified/code/compiler.c
@@ -0,0 +1,563 @@
+#include <glib.h>
+#include <string.h>
+
+typedef enum {
+  STATUS_FAIL = -1,
+  STATUS_OK = 0,
+  STATUS_CANCEL = 1
+} ParseStatus;
+
+enum {
+  TOKEN_FUNCTION = G_TOKEN_LAST + 1,
+  TOKEN_PLUSPLUS = G_TOKEN_LAST + 2,
+  TOKEN_MINUSMINUS = G_TOKEN_LAST + 3,
+  TOKEN_NEW = G_TOKEN_LAST + 4
+};
+
+typedef enum {
+  SYMBOL_NONE,
+  // top
+  SYMBOL_SOURCE_ELEMENT,
+  // function
+  SYMBOL_FUNCTION_DECLARATION,
+  // statement
+  SYMBOL_STATEMENT,
+  SYMBOL_BLOCK,
+  SYMBOL_VARIABLE_STATEMENT,
+  SYMBOL_EMPTY_STATEMENT,
+  SYMBOL_EXPRESSION_STATEMENT,
+  SYMBOL_IF_STATEMENT,
+  SYMBOL_ITERATION_STATEMENT,
+  SYMBOL_CONTINUE_STATEMENT,
+  SYMBOL_BREAK_STATEMENT,
+  SYMBOL_RETURN_STATEMENT,
+  SYMBOL_WITH_STATEMENT,
+  SYMBOL_LABELLED_STATEMENT,
+  SYMBOL_SWITCH_STATEMENT,
+  SYMBOL_THROW_STATEMENT,
+  SYMBOL_TRY_STATEMENT,
+  // expression
+  SYMBOL_EXPRESSION,
+  SYMBOL_ASSIGNMENT_EXPRESSION,
+  SYMBOL_CONDITIONAL_EXPRESSION,
+  SYMBOL_LEFT_HAND_SIDE_EXPRESSION,
+  SYMBOL_OPERATOR_EXPRESSION,
+  SYMBOL_UNARY_EXPRESSION,
+  SYMBOL_POSTFIX_EXPRESSION,
+  SYMBOL_NEW_EXPRESSION,
+  SYMBOL_CALL_EXPRESSION,
+  SYMBOL_MEMBER_EXPRESSION,
+  SYMBOL_FUNCTION_EXPRESSION,
+  SYMBOL_PRIMARY_EXPRESSION,
+  // misc
+  SYMBOL_IDENTIFIER,
+  SYMBOL_ASSIGNMENT_OPERATOR,
+  SYMBOL_ARGUMENTS,
+} ParseSymbol;
+
+typedef ParseStatus (*ParseFunction) (GScanner *scanner);
+
+static ParseStatus parse (GScanner *scanner, ParseSymbol symbol);
+static ParseStatus parse_list (GScanner *scanner, ParseSymbol symbol);
+
+// helpers
+
+static gboolean
+check_token (GScanner *scanner, guint token)
+{
+  g_scanner_peek_next_token (scanner);
+  if (scanner->next_token != token)
+    return FALSE;
+  g_scanner_get_next_token (scanner);
+  return TRUE;
+}
+
+// top
+
+static ParseStatus
+parse_source_element (GScanner *scanner)
+{
+  ParseStatus status;
+
+  status = parse (scanner, SYMBOL_FUNCTION_DECLARATION);
+
+  if (status == STATUS_CANCEL)
+    status = parse (scanner, SYMBOL_STATEMENT);
+
+  return status;
+}
+
+// function
+
+static ParseStatus
+parse_function_declaration (GScanner *scanner)
+{
+  if (!check_token (scanner, TOKEN_FUNCTION))
+    return STATUS_CANCEL;
+
+  if (parse (scanner, SYMBOL_IDENTIFIER) != STATUS_OK)
+    return STATUS_FAIL;
+
+  if (!check_token (scanner, '('))
+    return STATUS_FAIL;
+
+  if (parse_list (scanner, SYMBOL_IDENTIFIER) == STATUS_FAIL)
+    return STATUS_FAIL;
+
+  if (!check_token (scanner, ')'))
+    return STATUS_FAIL;
+
+  if (!check_token (scanner, '{'))
+    return STATUS_FAIL;
+
+  if (parse_list (scanner, SYMBOL_SOURCE_ELEMENT) == STATUS_FAIL)
+    return STATUS_FAIL;
+
+  if (!check_token (scanner, '}'))
+    return STATUS_FAIL;
+
+  return STATUS_OK;
+}
+
+// statement
+
+static ParseStatus
+parse_statement (GScanner *scanner)
+{
+  int i, status;
+  ParseSymbol options[] = {
+    SYMBOL_BLOCK,
+    SYMBOL_VARIABLE_STATEMENT,
+    SYMBOL_EMPTY_STATEMENT,
+    SYMBOL_EXPRESSION_STATEMENT,
+    SYMBOL_IF_STATEMENT,
+    SYMBOL_ITERATION_STATEMENT,
+    SYMBOL_CONTINUE_STATEMENT,
+    SYMBOL_BREAK_STATEMENT,
+    SYMBOL_RETURN_STATEMENT,
+    SYMBOL_WITH_STATEMENT,
+    SYMBOL_LABELLED_STATEMENT,
+    SYMBOL_SWITCH_STATEMENT,
+    SYMBOL_THROW_STATEMENT,
+    SYMBOL_TRY_STATEMENT,
+    SYMBOL_NONE
+  };
+
+  for (i = 0; options[i] != SYMBOL_NONE; i++) {
+    status = parse (scanner, options[i]);
+    if (status != STATUS_CANCEL)
+      return status;
+  }
+
+  return STATUS_CANCEL;
+}
+
+static ParseStatus
+parse_block (GScanner *scanner)
+{
+  if (!check_token (scanner, '{'))
+    return STATUS_CANCEL;
+
+  g_scanner_peek_next_token (scanner);
+  if (scanner->next_token != '}') {
+    if (parse_list (scanner, SYMBOL_STATEMENT) != STATUS_OK)
+      return STATUS_FAIL;
+  }
+
+  if (!check_token (scanner, '}'))
+    return STATUS_FAIL;
+
+  return STATUS_OK;
+}
+
+static ParseStatus
+parse_empty_statement (GScanner *scanner)
+{
+  if (!check_token (scanner, ';'))
+    return STATUS_CANCEL;
+
+  return STATUS_OK;
+}
+
+static ParseStatus
+parse_expression_statement (GScanner *scanner)
+{
+  g_scanner_peek_next_token (scanner);
+  if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
+    return STATUS_CANCEL;
+
+  return parse (scanner, SYMBOL_EXPRESSION);
+}
+
+// expression
+
+static ParseStatus
+parse_expression (GScanner *scanner)
+{
+  ParseStatus status;
+
+  status = parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION);
+  if (status != STATUS_OK)
+    return status;
+
+  do {
+    if (!check_token (scanner, ','))
+      return STATUS_OK;
+  } while (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION) == STATUS_OK);
+
+  return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_assignment_expression (GScanner *scanner)
+{
+  ParseStatus status;
+
+  status = parse (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION);
+  if (status == STATUS_OK) {
+    status = parse (scanner, SYMBOL_ASSIGNMENT_OPERATOR);
+    if (status == STATUS_CANCEL)
+      return STATUS_OK;
+    if (status == STATUS_FAIL)
+      return STATUS_FAIL;
+    if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION) != STATUS_OK)
+      return STATUS_FAIL;
+    return STATUS_OK;
+  } else if (status == STATUS_CANCEL) {
+    return parse (scanner, SYMBOL_CONDITIONAL_EXPRESSION);
+  } else {
+    return STATUS_FAIL;
+  }
+}
+
+static ParseStatus
+parse_conditional_expression (GScanner *scanner)
+{
+  ParseStatus status;
+
+  status = parse (scanner, SYMBOL_OPERATOR_EXPRESSION);
+  if (status != STATUS_OK)
+    return status;
+
+  if (!check_token (scanner, '?'))
+    return STATUS_OK;
+
+  if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION) != STATUS_OK)
+    return STATUS_FAIL;
+
+  if (!check_token (scanner, ':'))
+    return STATUS_FAIL;
+
+  if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION) != STATUS_OK)
+    return STATUS_FAIL;
+
+  return STATUS_OK;
+}
+
+static ParseStatus
+parse_operator_expression (GScanner *scanner)
+{
+  ParseStatus status;
+
+  status = parse (scanner, SYMBOL_UNARY_EXPRESSION);
+  if (status != STATUS_OK)
+    return status;
+
+  do {
+    if (!check_token (scanner, '+'))
+      return STATUS_OK;
+  } while (parse (scanner, SYMBOL_UNARY_EXPRESSION) == STATUS_OK);
+
+  return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_unary_expression (GScanner *scanner)
+{
+  ParseStatus status;
+
+  status = parse (scanner, SYMBOL_POSTFIX_EXPRESSION);
+  if (status != STATUS_OK)
+    return status;
+
+  do {
+    if (!check_token (scanner, '!'))
+      return STATUS_OK;
+  } while (parse (scanner, SYMBOL_POSTFIX_EXPRESSION) == STATUS_OK);
+
+  return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_postfix_expression (GScanner *scanner)
+{
+  ParseStatus status;
+
+  status = parse (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION);
+  if (status != STATUS_OK)
+    return status;
+
+  // don't allow new line here
+
+  g_scanner_peek_next_token (scanner);
+  if (scanner->next_token == TOKEN_PLUSPLUS ||
+      scanner->next_token == TOKEN_MINUSMINUS) {
+    g_scanner_get_next_token (scanner);
+    return STATUS_OK;
+  }
+
+  return STATUS_OK;
+}
+
+static ParseStatus
+parse_left_hand_side_expression (GScanner *scanner)
+{
+  ParseStatus status;
+
+  status = parse (scanner, SYMBOL_NEW_EXPRESSION);
+  if (status == STATUS_CANCEL)
+    status = parse (scanner, SYMBOL_CALL_EXPRESSION);
+
+  return status;
+}
+
+static ParseStatus
+parse_new_expression (GScanner *scanner)
+{
+  g_scanner_peek_next_token (scanner);
+  if (scanner->next_token == TOKEN_NEW) {
+    g_scanner_get_next_token (scanner);
+    if (parse (scanner, SYMBOL_NEW_EXPRESSION) != STATUS_OK)
+      return STATUS_FAIL;
+    return STATUS_OK;
+  } else {
+    return parse (scanner, SYMBOL_MEMBER_EXPRESSION);
+  }
+}
+
+static ParseStatus
+parse_member_expression (GScanner *scanner)
+{
+  ParseStatus status;
+
+  g_scanner_peek_next_token (scanner);
+  if (scanner->next_token == TOKEN_NEW) {
+    g_scanner_get_next_token (scanner);
+    if (parse (scanner, SYMBOL_MEMBER_EXPRESSION) != STATUS_OK)
+      return STATUS_FAIL;
+    if (parse (scanner, SYMBOL_ARGUMENTS) != STATUS_OK)
+      return STATUS_FAIL;
+    return STATUS_OK;
+  }
+
+  status = parse (scanner, SYMBOL_PRIMARY_EXPRESSION);
+  if (status == STATUS_CANCEL)
+    status = parse (scanner, SYMBOL_FUNCTION_EXPRESSION);
+
+  if (status != 0)
+    return status;
+
+  do {
+    g_scanner_peek_next_token (scanner);
+    if (scanner->next_token == '[') {
+      g_scanner_get_next_token (scanner);
+      if (parse (scanner, SYMBOL_EXPRESSION) != STATUS_OK)
+	return STATUS_FAIL;
+      if (!check_token (scanner, ']'))
+	return STATUS_FAIL;
+    } else if (scanner->next_token == '.') {
+      g_scanner_get_next_token (scanner);
+      if (parse (scanner, SYMBOL_IDENTIFIER) != STATUS_OK)
+	return STATUS_FAIL;
+    } else {
+      return STATUS_OK;
+    }
+  } while (TRUE);
+
+  g_assert_not_reached ();
+  return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_primary_expression (GScanner *scanner)
+{
+  return parse (scanner, SYMBOL_IDENTIFIER);
+}
+
+// misc.
+
+static ParseStatus
+parse_identifier (GScanner *scanner)
+{
+  if (!check_token (scanner, G_TOKEN_IDENTIFIER))
+    return STATUS_CANCEL;
+
+  return STATUS_OK;
+}
+
+static ParseStatus
+parse_assignment_operator (GScanner *scanner)
+{
+  if (!check_token (scanner, '='))
+    return STATUS_CANCEL;
+
+  return STATUS_OK;
+}
+
+// parsing
+
+static const struct {
+  ParseSymbol		id;
+  const char *		name;
+  ParseFunction		parse;
+} symbols[] = {
+  // top
+  { SYMBOL_SOURCE_ELEMENT, "SourceElement", parse_source_element },
+  // function
+  { SYMBOL_FUNCTION_DECLARATION, "FunctionDeclaration",
+    parse_function_declaration },
+  // statement
+  { SYMBOL_STATEMENT, "Statement", parse_statement },
+  { SYMBOL_BLOCK, "Block", parse_block },
+  { SYMBOL_EMPTY_STATEMENT, "EmptyStatement", parse_empty_statement },
+  { SYMBOL_EXPRESSION_STATEMENT, "ExpressionStatement",
+    parse_expression_statement },
+  // expression
+  { SYMBOL_EXPRESSION, "Expression", parse_expression },
+  { SYMBOL_ASSIGNMENT_EXPRESSION, "AssigmentExpression",
+    parse_assignment_expression },
+  { SYMBOL_CONDITIONAL_EXPRESSION, "ConditionalExpression",
+    parse_conditional_expression },
+  { SYMBOL_OPERATOR_EXPRESSION, "OperatorExpression",
+    parse_operator_expression },
+  { SYMBOL_UNARY_EXPRESSION, "UnaryExpression", parse_unary_expression },
+  { SYMBOL_POSTFIX_EXPRESSION, "PostfixExpression", parse_postfix_expression },
+  { SYMBOL_LEFT_HAND_SIDE_EXPRESSION, "LeftHandSideExpression",
+    parse_left_hand_side_expression },
+  { SYMBOL_NEW_EXPRESSION, "NewExpression", parse_new_expression },
+  { SYMBOL_MEMBER_EXPRESSION, "MemberExpression", parse_member_expression },
+  { SYMBOL_PRIMARY_EXPRESSION, "PrimaryExpression", parse_primary_expression },
+  // misc
+  { SYMBOL_IDENTIFIER, "Identifier", parse_identifier },
+  { SYMBOL_ASSIGNMENT_OPERATOR, "AssignmentOperator",
+    parse_assignment_operator },
+  { SYMBOL_NONE, NULL, NULL }
+};
+
+static int
+parse (GScanner *scanner, ParseSymbol symbol)
+{
+  int i;
+
+  for (i = 0; symbols[i].id != SYMBOL_NONE; i++) {
+    if (symbols[i].id == symbol) {
+      int ret = symbols[i].parse (scanner);
+      if (ret != 1)
+	g_print (":%i: %s\n", ret, symbols[i].name);
+      return ret;
+    }
+  }
+
+  //g_assert_not_reached ();
+  return 1;
+}
+
+static gboolean
+parse_list (GScanner *scanner, ParseSymbol symbol)
+{
+  int ret;
+
+  ret = parse (scanner, symbol);
+  if (ret != 0)
+    return ret;
+
+  do {
+    ret = parse (scanner, symbol);
+    if (ret == -1)
+      return -1;
+  } while (ret == 0);
+
+  return 0;
+}
+
+// main
+
+int
+main (int argc, char *argv[])
+{
+  GScanner *scanner;
+  char *test_text;
+  gsize test_text_len;
+  int ret;
+
+  if (argc < 2) {
+    g_print ("Usage!\n");
+    return 1;
+  }
+
+  if (!g_file_get_contents (argv[1], &test_text, &test_text_len, NULL)) {
+    g_printerr ("Couldn't open file %s", argv[1]);
+    return -1;
+  }
+
+  scanner = g_scanner_new (NULL);
+
+  scanner->config->numbers_2_int = TRUE;
+  scanner->config->int_2_float = TRUE;
+  scanner->config->symbol_2_token = TRUE;
+
+  g_scanner_set_scope (scanner, 0);
+  g_scanner_scope_add_symbol (scanner, 0, "function",
+      GINT_TO_POINTER(TOKEN_FUNCTION));
+  g_scanner_scope_add_symbol (scanner, 0, "++",
+      GINT_TO_POINTER(TOKEN_PLUSPLUS));
+  g_scanner_scope_add_symbol (scanner, 0, "--",
+      GINT_TO_POINTER(TOKEN_MINUSMINUS));
+  g_scanner_scope_add_symbol (scanner, 0, "new", GINT_TO_POINTER(TOKEN_NEW));
+
+  scanner->input_name = argv[1];
+  g_scanner_input_text (scanner, test_text, test_text_len);
+
+
+  ret = parse_list (scanner, SYMBOL_SOURCE_ELEMENT);
+  g_print ("%i: %i, %i\n", ret,
+      g_scanner_cur_line (scanner), g_scanner_cur_position (scanner));
+
+  g_scanner_peek_next_token (scanner);
+  while (scanner->next_token != G_TOKEN_EOF &&
+      scanner->next_token != G_TOKEN_ERROR)
+  {
+    g_scanner_get_next_token (scanner);
+    g_print (":: %i, %i :: ", g_scanner_cur_line (scanner),
+	g_scanner_cur_position (scanner));
+    switch (scanner->token) {
+      case G_TOKEN_SYMBOL:
+	g_print ("SYMBOL\n");
+	break;
+      case G_TOKEN_FLOAT:
+	g_print ("Primitive: %f\n", scanner->value.v_float);
+	break;
+      case G_TOKEN_STRING:
+	g_print ("Primitive: \"%s\"\n", scanner->value.v_string);
+	break;
+      case G_TOKEN_NONE:
+	g_print ("NONE\n");
+	break;
+      case G_TOKEN_IDENTIFIER:
+	g_print ("Identifier: %s\n", scanner->value.v_identifier);
+	break;
+      default:
+	if (scanner->token > 0 && scanner->token < 256) {
+	  g_print ("%c\n", scanner->token);
+	} else {
+	  g_print ("TOKEN %i\n", scanner->token);
+	}
+	break;
+    }
+    g_scanner_peek_next_token (scanner);
+  }
+
+  g_scanner_destroy (scanner);
+
+  return 0;
+}


More information about the Swfdec-commits mailing list