[Swfdec-commits] 18 commits - configure.ac swfdec/swfdec_text_field_movie.c vivified/code

Pekka Lampila medar at kemper.freedesktop.org
Thu Apr 3 07:56:10 PDT 2008


 configure.ac                                      |    2 
 swfdec/swfdec_text_field_movie.c                  |    2 
 vivified/code/.gitignore                          |    3 
 vivified/code/Makefile.am                         |   13 
 vivified/code/compiler.c                          |   11 
 vivified/code/vivi_code_assignment.c              |    2 
 vivified/code/vivi_code_get.c                     |   13 
 vivified/code/vivi_code_get.h                     |    2 
 vivified/code/vivi_compiler.c                     | 1066 +++++++++++++---------
 vivified/code/vivi_compiler.h                     |    5 
 vivified/code/vivi_compiler_get_temporary.c       |   56 +
 vivified/code/vivi_compiler_get_temporary.h       |   54 +
 vivified/code/vivi_compiler_scanner.c             |  253 +++++
 vivified/code/vivi_compiler_scanner.h             |  193 +++
 vivified/code/vivi_compiler_scanner_lex.lex       |  147 +++
 vivified/code/vivi_compiler_scanner_lex_include.h |    8 
 16 files changed, 1431 insertions(+), 399 deletions(-)

New commits:
commit 5369653d8d00e6c99e910f3d64ff90754cdafd4a
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu Apr 3 17:55:52 2008 +0300

    Fix a compiler warning in swfdec_text_field_movie_mouse_press

diff --git a/swfdec/swfdec_text_field_movie.c b/swfdec/swfdec_text_field_movie.c
index 94babd7..e96d39e 100644
--- a/swfdec/swfdec_text_field_movie.c
+++ b/swfdec/swfdec_text_field_movie.c
@@ -1521,7 +1521,7 @@ swfdec_text_field_movie_mouse_press (SwfdecActor *actor, guint button)
 {
   SwfdecTextFieldMovie *text = SWFDEC_TEXT_FIELD_MOVIE (actor);
   double x, y;
-  gsize index_;
+  guint index_;
   gboolean direct, before;
 
   if (button != 0) {
commit e185365241707870d01a1322dc9bf5f4d26456ec
Merge: a8293a9... 1c356c4...
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu Apr 3 17:55:13 2008 +0300

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

commit a8293a963a39d2559afdeb485bbebc6ba2601ce2
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu Apr 3 17:50:16 2008 +0300

    Fix handling of assignment and get when compiling

diff --git a/vivified/code/vivi_code_assignment.c b/vivified/code/vivi_code_assignment.c
index 1bc2d29..eee40ee 100644
--- a/vivified/code/vivi_code_assignment.c
+++ b/vivified/code/vivi_code_assignment.c
@@ -49,8 +49,6 @@ vivi_code_assignment_print (ViviCodeToken *token, ViviCodePrinter*printer)
 
   if (VIVI_IS_CODE_CONSTANT (assignment->name)) {
     varname = vivi_code_constant_get_variable_name (VIVI_CODE_CONSTANT (assignment->name));
-  } else if (VIVI_IS_CODE_GET (assignment->name)) {
-    varname = vivi_code_get_get_variable_name (VIVI_CODE_GET (assignment->name));
   } else {
     varname = NULL;
   }
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index b4275fa..54027c9 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -131,6 +131,51 @@ vivi_compiler_combine_statements (guint count, ...)
   return VIVI_CODE_STATEMENT (block);
 }
 
+static ViviCodeStatement *
+vivi_compiler_assignment_new (ViviCodeValue *left, ViviCodeValue *right)
+{
+  ViviCodeValue *from;
+
+  g_return_val_if_fail (VIVI_IS_CODE_VALUE (left), NULL);
+  g_return_val_if_fail (VIVI_IS_CODE_VALUE (right), NULL);
+
+  from = NULL;
+
+  if (VIVI_IS_CODE_GET (left)) {
+    ViviCodeGet *get = VIVI_CODE_GET (left);
+
+    if (get->from != NULL) {
+      from = g_object_ref (get->from);
+      left = g_object_ref (get->name);
+    }
+  }
+
+  if (VIVI_IS_CODE_GET (left)) {
+    ViviCodeGet *get = VIVI_CODE_GET (left);
+
+    if (get->from == NULL)
+      left = g_object_ref (get->name);
+  }
+
+  return vivi_code_assignment_new (from, left, right);
+}
+
+static ViviCodeValue *
+vivi_compiler_get_new (ViviCodeValue *from, ViviCodeValue *name)
+{
+  g_return_val_if_fail (VIVI_IS_CODE_VALUE (from), NULL);
+  g_return_val_if_fail (VIVI_IS_CODE_VALUE (name), NULL);
+
+  if (VIVI_IS_CODE_GET (name)) {
+    ViviCodeGet *get = VIVI_CODE_GET (name);
+
+    if (get->from == NULL)
+      name = g_object_ref (get->name);
+  }
+
+  return vivi_code_get_new (from, name);
+}
+
 // values
 
 static int
@@ -460,7 +505,7 @@ parse_member_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
     }
 
     tmp = *value;
-    *value = vivi_code_get_new (tmp, VIVI_CODE_VALUE (member));
+    *value = vivi_compiler_get_new (tmp, member);
     g_object_unref (tmp);
     g_object_unref (member);
   } while (TRUE);
@@ -903,10 +948,10 @@ parse_assignment_expression (ViviCompilerScanner *scanner,
       }
 
       if (operator != NULL) {
-	assignment = vivi_code_assignment_new (NULL, *value,
+	assignment = vivi_compiler_assignment_new (*value,
 	    vivi_code_binary_new_name (*value, right, operator));
       } else {
-	assignment = vivi_code_assignment_new (NULL, *value, right);
+	assignment = vivi_compiler_assignment_new (*value, right);
       }
       g_object_unref (right);
 
@@ -930,6 +975,7 @@ parse_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
   int expected;
 
   *statement = NULL;
+  statement_one = NULL;
 
   expected = parse_assignment_expression (scanner, value, &statement_one);
   if (expected != TOKEN_NONE)
@@ -942,6 +988,7 @@ parse_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
     if (!check_token (scanner, TOKEN_COMMA))
       break;
 
+    statement_one = NULL;
     expected = parse_assignment_expression (scanner, value, &statement_one);
     if (expected != TOKEN_NONE && expected >= 0) {
       g_object_unref (*value);
commit a70ddc6c91d6662a855e8ed32e3030f5586ef5f4
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed Apr 2 16:04:33 2008 +0300

    Clean up compiler code with new vivi_compiler_combine_statements function

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 0403a67..b4275fa 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -94,6 +94,43 @@ free_value_list (ViviCodeValue **list)
   g_free (list);
 }
 
+static ViviCodeStatement *
+vivi_compiler_combine_statements (guint count, ...)
+{
+  va_list args;
+  ViviCodeBlock *block;
+  guint i;
+
+  if (count == 0)
+    return NULL;
+
+  va_start (args, count);
+  block = NULL;
+  for (i = 0; i < count; i++) {
+    ViviCodeStatement *statement = va_arg (args, ViviCodeStatement *);
+
+    if (statement == NULL)
+      continue;
+
+    g_assert (VIVI_IS_CODE_STATEMENT (statement));
+
+    if (block == NULL) {
+      if (VIVI_IS_CODE_BLOCK (statement)) {
+	block = VIVI_CODE_BLOCK (statement);
+	continue;
+      } else {
+	block = VIVI_CODE_BLOCK (vivi_code_block_new ());
+      }
+    }
+
+    vivi_code_block_add_statement (block, statement);
+    g_object_unref (statement);
+  }
+  va_end (args);
+
+  return VIVI_CODE_STATEMENT (block);
+}
+
 // values
 
 static int
@@ -258,13 +295,8 @@ parse_object_literal (ViviCompilerScanner *scanner, ViviCodeValue **value,
 	return FAIL (expected);
       }
 
-      if (statement_new != NULL) {
-	if (*statement == NULL)
-	  *statement = vivi_code_block_new ();
-	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
-	    statement_new);
-	g_object_unref (statement_new);
-      }
+      *statement =
+	vivi_compiler_combine_statements (2, *statement, statement_new);
 
       vivi_code_init_object_add_variable (VIVI_CODE_INIT_OBJECT (*value),
 	  property, initializer);
@@ -314,16 +346,8 @@ parse_variable_declaration (ViviCompilerScanner *scanner,
   assignment = vivi_code_assignment_new (NULL, identifier, value);
   vivi_code_assignment_set_local (VIVI_CODE_ASSIGNMENT (assignment), TRUE);
 
-  if (statement_right != NULL) {
-    *statement = vivi_code_block_new ();
-    vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
-	statement_right);
-    g_object_unref (statement_right);
-    vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement), assignment);
-    g_object_unref (assignment);
-  } else {
-    *statement = assignment;
-  }
+  *statement =
+    vivi_compiler_combine_statements (2, statement_right, assignment);
 
   return TOKEN_NONE;
 }
@@ -403,12 +427,29 @@ parse_member_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
     ViviCodeValue *tmp;
 
     if (check_token (scanner, TOKEN_BRACKET_LEFT)) {
-      // TODO: statement
       expected = parse_expression (scanner, &member, &statement_member);
-      if (expected != TOKEN_NONE)
+      if (expected != TOKEN_NONE) {
+	g_object_unref (*value);
+	*value = NULL;
+	if (*statement != NULL) {
+	  g_object_unref (*statement);
+	  *statement = NULL;
+	}
 	return FAIL (expected);
-      if (!check_token (scanner, TOKEN_BRACKET_RIGHT))
+      }
+
+      *statement = vivi_compiler_combine_statements (2, *statement,
+	  statement_member);
+
+      if (!check_token (scanner, TOKEN_BRACKET_RIGHT)) {
+	g_object_unref (*value);
+	*value = NULL;
+	if (*statement != NULL) {
+	  g_object_unref (*statement);
+	  *statement = NULL;
+	}
 	return TOKEN_BRACKET_RIGHT;
+      }
     } else if (check_token (scanner, TOKEN_DOT)) {
       expected = parse_identifier (scanner, &member);
       g_assert (statement_member == NULL);
@@ -502,14 +543,9 @@ parse_postfix_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
   operation = vivi_code_binary_new_name (*value, one, operator);
   g_object_unref (one);
 
-  g_assert (*statement == NULL);
-
-  *statement = vivi_code_block_new ();
-
   temporary = vivi_compiler_get_temporary_new ();
-  vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
-      vivi_code_assignment_new (NULL, temporary, *value));
-  vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
+  *statement = vivi_compiler_combine_statements (3, *statement,
+      vivi_code_assignment_new (NULL, temporary, *value),
       vivi_code_assignment_new (NULL, *value, operation));
   g_object_unref (operation);
 
@@ -556,9 +592,8 @@ parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
       tmp = vivi_code_binary_new_name (*value, one, operator);
       g_object_unref (one);
 
-      g_assert (*statement == NULL);
-
-      *statement = vivi_code_assignment_new (NULL, *value, tmp);
+      *statement = vivi_compiler_combine_statements (2, *statement,
+	  vivi_code_assignment_new (NULL, *value, tmp));
       g_object_unref (tmp);
 
       return TOKEN_NONE;
@@ -612,7 +647,7 @@ parse_operator_expression (ViviCompilerScanner *scanner,
       }
 
       if (statement_right != NULL) {
-	ViviCodeStatement *statement_left, *tmp;
+	ViviCodeStatement *tmp;
 
 	switch (pass) {
 	  case PASS_LOGICAL_OR:
@@ -634,12 +669,8 @@ parse_operator_expression (ViviCompilerScanner *scanner,
 	    g_assert_not_reached ();
 	}
 
-	statement_left = *statement;
-	*statement = vivi_code_block_new ();
-	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
-	    statement_left);
-	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
-	    statement_right);
+	*statement = vivi_compiler_combine_statements (2, *statement,
+	    *statement_right);
       }
 
       left = VIVI_CODE_VALUE (*value);
@@ -835,8 +866,6 @@ parse_assignment_expression (ViviCompilerScanner *scanner,
   if (!VIVI_IS_CODE_GET (*value))
     return TOKEN_NONE;
 
-  g_assert (*statement == NULL);
-
   operator = NULL;
 
   vivi_compiler_scanner_peek_next_token (scanner);
@@ -881,17 +910,8 @@ parse_assignment_expression (ViviCompilerScanner *scanner,
       }
       g_object_unref (right);
 
-      if (statement_right != NULL) {
-	*statement = vivi_code_block_new ();
-	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
-	    statement_right);
-	g_object_unref (statement_right);
-	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
-	    assignment);
-	g_object_unref (assignment);
-      } else {
-	*statement = assignment;
-      }
+      *statement = vivi_compiler_combine_statements (3, *statement,
+	  statement_right, assignment);
 
       break;
     default:
@@ -915,14 +935,9 @@ parse_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
   if (expected != TOKEN_NONE)
     return expected;
 
-  *statement = vivi_code_block_new ();
-
   do {
-    if (statement_one != NULL) {
-      vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
-	  statement_one);
-      g_object_unref (statement_one);
-    }
+    *statement =
+      vivi_compiler_combine_statements (2, *statement, statement_one);
 
     if (!check_token (scanner, TOKEN_COMMA))
       break;
commit 5035f25268eda1320dfb8b2fdd53e65bb6ba9850
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed Apr 2 16:04:02 2008 +0300

    Oops, brackets were reversed in the .lex file

diff --git a/vivified/code/vivi_compiler_scanner_lex.lex b/vivified/code/vivi_compiler_scanner_lex.lex
index 875bdb3..fdcf654 100644
--- a/vivified/code/vivi_compiler_scanner_lex.lex
+++ b/vivified/code/vivi_compiler_scanner_lex.lex
@@ -13,8 +13,8 @@ identifier_part		[$_a-zA-Z0-9]
 
 "{"			{ return TOKEN_BRACE_LEFT; }
 "}"			{ return TOKEN_BRACE_RIGHT; }
-"["			{ return TOKEN_BRACKET_RIGHT; }
-"]"			{ return TOKEN_BRACKET_LEFT; }
+"["			{ return TOKEN_BRACKET_LEFT; }
+"]"			{ return TOKEN_BRACKET_RIGHT; }
 "("			{ return TOKEN_PARENTHESIS_LEFT; }
 ")"			{ return TOKEN_PARENTHESIS_RIGHT; }
 
commit 4a1a4c10b1904998a5f90dccf9decc8f6ba3c7c6
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed Apr 2 16:03:29 2008 +0300

    Fixex to the variable name getting for ViviCodeGet

diff --git a/vivified/code/vivi_code_assignment.c b/vivified/code/vivi_code_assignment.c
index af4c909..1bc2d29 100644
--- a/vivified/code/vivi_code_assignment.c
+++ b/vivified/code/vivi_code_assignment.c
@@ -50,7 +50,7 @@ vivi_code_assignment_print (ViviCodeToken *token, ViviCodePrinter*printer)
   if (VIVI_IS_CODE_CONSTANT (assignment->name)) {
     varname = vivi_code_constant_get_variable_name (VIVI_CODE_CONSTANT (assignment->name));
   } else if (VIVI_IS_CODE_GET (assignment->name)) {
-    varname = vivi_code_constant_get_variable_name (VIVI_CODE_CONSTANT (VIVI_CODE_GET (assignment->name)->name));
+    varname = vivi_code_get_get_variable_name (VIVI_CODE_GET (assignment->name));
   } else {
     varname = NULL;
   }
diff --git a/vivified/code/vivi_code_get.c b/vivified/code/vivi_code_get.c
index edac7f9..d90731a 100644
--- a/vivified/code/vivi_code_get.c
+++ b/vivified/code/vivi_code_get.c
@@ -100,6 +100,19 @@ vivi_code_get_init (ViviCodeGet *get)
   vivi_code_value_set_precedence (value, VIVI_PRECEDENCE_MEMBER);
 }
 
+char *
+vivi_code_get_get_variable_name (ViviCodeGet *get)
+{
+  if (VIVI_IS_CODE_CONSTANT (get->name)) {
+    return
+      vivi_code_constant_get_variable_name (VIVI_CODE_CONSTANT (get->name));
+  } else if (VIVI_IS_CODE_GET (get->name)) {
+    return vivi_code_get_get_variable_name (VIVI_CODE_GET (get->name));
+  } else {
+    return NULL;
+  }
+}
+
 ViviCodeValue *
 vivi_code_get_new (ViviCodeValue *from, ViviCodeValue *name)
 {
diff --git a/vivified/code/vivi_code_get.h b/vivified/code/vivi_code_get.h
index fbdf13f..896c600 100644
--- a/vivified/code/vivi_code_get.h
+++ b/vivified/code/vivi_code_get.h
@@ -54,6 +54,8 @@ ViviCodeValue *		vivi_code_get_new		(ViviCodeValue *	from,
 							 ViviCodeValue *	name);
 ViviCodeValue *		vivi_code_get_new_name		(const char *		name);
 
+char *			vivi_code_get_get_variable_name	(ViviCodeGet *		get);
+
 
 G_END_DECLS
 #endif
commit 8dc7415a19d22ecd56d3c4e498b5c93a26484288
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed Apr 2 15:12:19 2008 +0300

    Clean up the compiler code

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 1513e0a..0403a67 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -61,19 +61,20 @@ enum {
 
 #define FAIL(x) ((x) < 0 ? -x : x)
 
+typedef int (*ParseValueFunction) (ViviCompilerScanner *scanner, ViviCodeValue **value);
+typedef int (*ParseValueStatementFunction) (ViviCompilerScanner *scanner, ViviCodeValue **value, ViviCodeStatement **statement);
 typedef int (*ParseStatementFunction) (ViviCompilerScanner *scanner, ViviCodeStatement **statement);
-typedef int (*ParseValueFunction) (ViviCompilerScanner *scanner, ViviCodeValue **value, ViviCodeStatement **pre_statement);
-typedef int (*ParseLiteralFunction) (ViviCompilerScanner *scanner, ViviCodeValue **value);
 
 static int
 parse_statement_list (ViviCompilerScanner *scanner, ParseStatementFunction function, ViviCodeStatement **statement, guint separator);
 static int
-parse_literal_list (ViviCompilerScanner *scanner, ParseLiteralFunction function, ViviCodeValue ***list, guint separator);
+parse_value_list (ViviCompilerScanner *scanner, ParseValueFunction function,
+    ViviCodeValue ***list, guint separator);
 
 // helpers
 
 static gboolean
-check_token (ViviCompilerScanner *scanner, guint token)
+check_token (ViviCompilerScanner *scanner, ViviCompilerScannerToken token)
 {
   vivi_compiler_scanner_peek_next_token (scanner);
   if (scanner->next_token != token)
@@ -147,7 +148,7 @@ static int
 parse_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   int i, expected;
-  ParseLiteralFunction functions[] = {
+  ParseValueFunction functions[] = {
     parse_null_literal,
     parse_boolean_literal,
     parse_numeric_literal,
@@ -183,7 +184,7 @@ static int
 parse_property_name (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   int i, expected;
-  ParseLiteralFunction functions[] = {
+  ParseValueFunction functions[] = {
     parse_identifier,
     parse_string_literal,
     parse_numeric_literal,
@@ -202,14 +203,17 @@ parse_property_name (ViviCompilerScanner *scanner, ViviCodeValue **value)
 }
 
 static int
-parse_logical_or_expression (ViviCompilerScanner *scanner, ViviCodeValue **value, ViviCodeStatement **pre_statement);
+parse_assignment_expression (ViviCompilerScanner *scanner,
+    ViviCodeValue **value, ViviCodeStatement **statement);
 
 static int
-parse_object_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
+parse_object_literal (ViviCompilerScanner *scanner, ViviCodeValue **value,
+    ViviCodeStatement **statement)
 {
   int expected;
 
   *value = NULL;
+  *statement = NULL;
 
   if (!check_token (scanner, TOKEN_BRACE_LEFT))
     return -TOKEN_BRACE_LEFT;
@@ -219,29 +223,49 @@ parse_object_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
   if (!check_token (scanner, TOKEN_BRACE_RIGHT)) {
     do {
       ViviCodeValue *property, *initializer;
-      ViviCodeStatement *pre_statement = NULL;
+      ViviCodeStatement *statement_new;
 
       expected = parse_property_name (scanner, &property);
       if (expected != TOKEN_NONE) {
 	g_object_unref (*value);
 	*value = NULL;
+	if (*statement != NULL) {
+	  g_object_unref (*statement);
+	  *statement = NULL;
+	}
 	return FAIL (expected);
       }
 
       if (!check_token (scanner, TOKEN_COLON)) {
 	g_object_unref (*value);
 	*value = NULL;
+	if (*statement != NULL) {
+	  g_object_unref (*statement);
+	  *statement = NULL;
+	}
 	return TOKEN_COLON;
       }
 
-      // FIXME: assignment expression
-      expected = parse_logical_or_expression (scanner, &initializer, &pre_statement);
+      expected = parse_assignment_expression (scanner, &initializer,
+	  &statement_new);
       if (expected != TOKEN_NONE) {
 	g_object_unref (*value);
 	*value = NULL;
+	if (*statement != NULL) {
+	  g_object_unref (*statement);
+	  *statement = NULL;
+	}
 	return FAIL (expected);
       }
 
+      if (statement_new != NULL) {
+	if (*statement == NULL)
+	  *statement = vivi_code_block_new ();
+	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
+	    statement_new);
+	g_object_unref (statement_new);
+      }
+
       vivi_code_init_object_add_variable (VIVI_CODE_INIT_OBJECT (*value),
 	  property, initializer);
     } while (check_token (scanner, TOKEN_COMMA));
@@ -250,6 +274,10 @@ parse_object_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
   if (!check_token (scanner, TOKEN_BRACE_RIGHT)) {
     g_object_unref (*value);
     *value = NULL;
+    if (*statement != NULL) {
+      g_object_unref (*statement);
+      *statement = NULL;
+    }
     return TOKEN_BRACE_RIGHT;
   }
 
@@ -259,42 +287,38 @@ parse_object_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
 // misc
 
 static int
-parse_assignment_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value, ViviCodeStatement **pre_statement);
-
-static int
 parse_variable_declaration (ViviCompilerScanner *scanner,
     ViviCodeStatement **statement)
 {
   int expected;
   ViviCodeValue *identifier, *value;
-  ViviCodeStatement *pre_statement, *assignment;
+  ViviCodeStatement *assignment, *statement_right;
 
   *statement = NULL;
-  pre_statement = NULL;
 
   expected = parse_identifier (scanner, &identifier);
   if (expected != TOKEN_NONE)
     return expected;
 
   if (check_token (scanner, TOKEN_ASSIGN)) {
-    expected = parse_assignment_expression (scanner, &value, &pre_statement);
+    expected = parse_assignment_expression (scanner, &value, &statement_right);
     if (expected != TOKEN_NONE) {
       g_object_unref (identifier);
       return FAIL (expected);
     }
   } else {
     value = vivi_code_constant_new_undefined ();
+    statement_right = NULL;
   }
 
   assignment = vivi_code_assignment_new (NULL, identifier, value);
   vivi_code_assignment_set_local (VIVI_CODE_ASSIGNMENT (assignment), TRUE);
 
-  if (pre_statement != NULL) {
+  if (statement_right != NULL) {
     *statement = vivi_code_block_new ();
     vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
-	pre_statement);
-    g_object_unref (pre_statement);
+	statement_right);
+    g_object_unref (statement_right);
     vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement), assignment);
     g_object_unref (assignment);
   } else {
@@ -307,18 +331,22 @@ parse_variable_declaration (ViviCompilerScanner *scanner,
 // expression
 
 static int
-parse_primary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
+parse_expression (ViviCompilerScanner *scanner, ViviCodeValue **value, ViviCodeStatement **statement);
+
+static int
+parse_primary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
+    ViviCodeStatement **statement)
 {
   int i, expected;
-  ParseLiteralFunction functions[] = {
+  ParseValueFunction functions[] = {
     parse_identifier,
     parse_literal,
     //parse_array_literal,
-    parse_object_literal,
     NULL
   };
 
   *value = NULL;
+  *statement = NULL;
 
   if (check_token (scanner, TOKEN_THIS)) {
     *value = vivi_code_get_new_name ("this");
@@ -326,9 +354,7 @@ parse_primary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
   }
 
   if (check_token (scanner, TOKEN_PARENTHESIS_LEFT)) {
-    ViviCodeStatement *pre_statement = NULL;
-    // FIXME: assignment expression
-    expected = parse_logical_or_expression (scanner, value, &pre_statement);
+    expected = parse_expression (scanner, value, statement);
     if (expected != TOKEN_NONE)
       return FAIL (expected);
     if (!check_token (scanner, TOKEN_PARENTHESIS_RIGHT)) {
@@ -339,6 +365,11 @@ parse_primary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
     return TOKEN_NONE;
   }
 
+
+  expected = parse_object_literal (scanner, value, statement);
+  if (expected == TOKEN_NONE || expected >= 0)
+    return expected;
+
   for (i = 0; functions[i] != NULL; i++) {
     expected = functions[i] (scanner, value);
     if (expected >= 0)
@@ -349,15 +380,19 @@ parse_primary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 }
 
 static int
-parse_member_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
+parse_member_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
+    ViviCodeStatement **statement)
 {
   int expected;
   ViviCodeValue *member;
-  ViviCodeStatement *pre_statement = NULL;
+  ViviCodeStatement *statement_member;
+
+  *value = NULL;
+  *statement = NULL;
 
   // TODO: new MemberExpression Arguments
 
-  expected = parse_primary_expression (scanner, value);
+  expected = parse_primary_expression (scanner, value, statement);
   //if (expected == STATUS_CANCEL)
   //  expected = parse_function_expression (scanner, value);
 
@@ -368,14 +403,15 @@ parse_member_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
     ViviCodeValue *tmp;
 
     if (check_token (scanner, TOKEN_BRACKET_LEFT)) {
-      // FIXME: expression
-      expected = parse_logical_or_expression (scanner, &member, &pre_statement);
+      // TODO: statement
+      expected = parse_expression (scanner, &member, &statement_member);
       if (expected != TOKEN_NONE)
 	return FAIL (expected);
       if (!check_token (scanner, TOKEN_BRACKET_RIGHT))
 	return TOKEN_BRACKET_RIGHT;
     } else if (check_token (scanner, TOKEN_DOT)) {
       expected = parse_identifier (scanner, &member);
+      g_assert (statement_member == NULL);
       if (expected != TOKEN_NONE)
 	return FAIL (expected);
     } else {
@@ -392,14 +428,16 @@ parse_member_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 }
 
 static int
-parse_new_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
+parse_new_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
+    ViviCodeStatement **statement)
 {
   int expected;
 
   *value = NULL;
+  *statement = NULL;
 
   if (check_token (scanner, TOKEN_NEW)) {
-    expected = parse_new_expression (scanner, value);
+    expected = parse_new_expression (scanner, value, statement);
     if (expected != TOKEN_NONE)
       return FAIL (expected);
     if (!VIVI_IS_CODE_FUNCTION_CALL (*value)) {
@@ -411,18 +449,19 @@ parse_new_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 	TRUE);
     return TOKEN_NONE;
   } else {
-    return parse_member_expression (scanner, value);
+    return parse_member_expression (scanner, value, statement);
   }
 }
 
 static int
-parse_left_hand_side_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
+parse_left_hand_side_expression (ViviCompilerScanner *scanner,
+    ViviCodeValue **value, ViviCodeStatement **statement)
 {
   int expected;
 
   *value = NULL;
 
-  expected = parse_new_expression (scanner, value);
+  expected = parse_new_expression (scanner, value, statement);
   //if (expected == STATUS_CANCEL)
   //  expected = parse_call_expression (scanner, value);
 
@@ -431,15 +470,16 @@ parse_left_hand_side_expression (ViviCompilerScanner *scanner, ViviCodeValue **v
 
 static int
 parse_postfix_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
-    ViviCodeStatement **pre_statement)
+    ViviCodeStatement **statement)
 {
   int expected;
   ViviCodeValue *operation, *one, *temporary;
   const char *operator;
 
   *value = NULL;
+  *statement = NULL;
 
-  expected = parse_left_hand_side_expression (scanner, value);
+  expected = parse_left_hand_side_expression (scanner, value, statement);
   if (expected != TOKEN_NONE)
     return expected;
 
@@ -462,14 +502,14 @@ parse_postfix_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
   operation = vivi_code_binary_new_name (*value, one, operator);
   g_object_unref (one);
 
-  g_assert (*pre_statement == NULL);
+  g_assert (*statement == NULL);
 
-  *pre_statement = vivi_code_block_new ();
+  *statement = vivi_code_block_new ();
 
   temporary = vivi_compiler_get_temporary_new ();
-  vivi_code_block_add_statement (VIVI_CODE_BLOCK (*pre_statement),
+  vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
       vivi_code_assignment_new (NULL, temporary, *value));
-  vivi_code_block_add_statement (VIVI_CODE_BLOCK (*pre_statement),
+  vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
       vivi_code_assignment_new (NULL, *value, operation));
   g_object_unref (operation);
 
@@ -481,7 +521,7 @@ parse_postfix_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
 
 static int
 parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
-    ViviCodeStatement **pre_statement)
+    ViviCodeStatement **statement)
 {
   int expected;
   ViviCodeValue *tmp, *one;
@@ -503,7 +543,7 @@ parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
       if (!operator) operator = "-";
 
       vivi_compiler_scanner_get_next_token (scanner);
-      expected = parse_unary_expression (scanner, value, pre_statement);
+      expected = parse_unary_expression (scanner, value, statement);
       if (expected != TOKEN_NONE)
 	return FAIL (expected);
 
@@ -516,9 +556,9 @@ parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
       tmp = vivi_code_binary_new_name (*value, one, operator);
       g_object_unref (one);
 
-      g_assert (*pre_statement == NULL);
+      g_assert (*statement == NULL);
 
-      *pre_statement = vivi_code_assignment_new (NULL, *value, tmp);
+      *statement = vivi_code_assignment_new (NULL, *value, tmp);
       g_object_unref (tmp);
 
       return TOKEN_NONE;
@@ -527,7 +567,7 @@ parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
     case TOKEN_BITWISE_NOT:*/
     case TOKEN_LOGICAL_NOT:
       vivi_compiler_scanner_get_next_token (scanner);
-      expected = parse_unary_expression (scanner, value, pre_statement);
+      expected = parse_unary_expression (scanner, value, statement);
       if (expected != TOKEN_NONE)
 	return FAIL (expected);
       tmp = VIVI_CODE_VALUE (*value);
@@ -535,7 +575,7 @@ parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
       g_object_unref (tmp);
       return TOKEN_NONE;
     default:
-      return parse_postfix_expression (scanner, value, pre_statement);
+      return parse_postfix_expression (scanner, value, statement);
   }
 }
 
@@ -547,45 +587,45 @@ typedef enum {
 
 static int
 parse_operator_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value, ViviCodeStatement **pre_statement,
+    ViviCodeValue **value, ViviCodeStatement **statement,
     const ViviCompilerScannerToken *tokens, ParseOperatorPass pass,
-    ParseValueFunction next_parse_function)
+    ParseValueStatementFunction next_parse_function)
 {
   int expected, i;
   ViviCodeValue *left, *right;
-  ViviCodeStatement *pre_statement_right;
+  ViviCodeStatement *statement_right;
 
   *value = NULL;
-  *pre_statement = NULL;
+  *statement = NULL;
 
-  expected = next_parse_function (scanner, value, pre_statement);
+  expected = next_parse_function (scanner, value, statement);
   if (expected != TOKEN_NONE)
     return expected;
 
   for (i = 0; tokens[i] != TOKEN_NONE; i++) {
     if (check_token (scanner, tokens[i])) {
-      expected = next_parse_function (scanner, &right, &pre_statement_right);
+      expected = next_parse_function (scanner, &right, &statement_right);
       if (expected != TOKEN_NONE) {
 	g_object_unref (*value);
 	*value = NULL;
 	return FAIL (expected);
       }
 
-      if (pre_statement_right != NULL) {
-	ViviCodeStatement *pre_statement_left, *tmp;
+      if (statement_right != NULL) {
+	ViviCodeStatement *statement_left, *tmp;
 
 	switch (pass) {
 	  case PASS_LOGICAL_OR:
 	    tmp = vivi_code_if_new (vivi_code_unary_new (*value, '!'));
-	    vivi_code_if_set_if (VIVI_CODE_IF (tmp), pre_statement_right);
-	    g_object_unref (pre_statement_right);
-	    pre_statement_right = tmp;
+	    vivi_code_if_set_if (VIVI_CODE_IF (tmp), statement_right);
+	    g_object_unref (statement_right);
+	    statement_right = tmp;
 	    break;
 	  case PASS_LOGICAL_AND:
 	    tmp = vivi_code_if_new (*value);
-	    vivi_code_if_set_if (VIVI_CODE_IF (tmp), pre_statement_right);
-	    g_object_unref (pre_statement_right);
-	    pre_statement_right = tmp;
+	    vivi_code_if_set_if (VIVI_CODE_IF (tmp), statement_right);
+	    g_object_unref (statement_right);
+	    statement_right = tmp;
 	    break;
 	  case PASS_ALWAYS:
 	    // nothing
@@ -594,12 +634,12 @@ parse_operator_expression (ViviCompilerScanner *scanner,
 	    g_assert_not_reached ();
 	}
 
-	pre_statement_left = *pre_statement;
-	*pre_statement = vivi_code_block_new ();
-	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*pre_statement),
-	    pre_statement_left);
-	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*pre_statement),
-	    pre_statement_right);
+	statement_left = *statement;
+	*statement = vivi_code_block_new ();
+	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
+	    statement_left);
+	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
+	    statement_right);
       }
 
       left = VIVI_CODE_VALUE (*value);
@@ -615,126 +655,126 @@ parse_operator_expression (ViviCompilerScanner *scanner,
 
 static int
 parse_multiplicative_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value, ViviCodeStatement **pre_statement)
+    ViviCodeValue **value, ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_MULTIPLY,
     TOKEN_DIVIDE, TOKEN_REMAINDER, TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, pre_statement, tokens,
+  return parse_operator_expression (scanner, value, statement, tokens,
       PASS_ALWAYS, parse_unary_expression);
 }
 
 static int
 parse_additive_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value, ViviCodeStatement **pre_statement)
+    ViviCodeValue **value, ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_PLUS, TOKEN_MINUS,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, pre_statement, tokens,
+  return parse_operator_expression (scanner, value, statement, tokens,
       PASS_ALWAYS, parse_multiplicative_expression);
 }
 
 static int
 parse_shift_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
-    ViviCodeStatement **pre_statement)
+    ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_SHIFT_LEFT,
     TOKEN_SHIFT_RIGHT, TOKEN_SHIFT_RIGHT_UNSIGNED, TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, pre_statement, tokens,
+  return parse_operator_expression (scanner, value, statement, tokens,
       PASS_ALWAYS, parse_additive_expression);
 }
 
 static int
 parse_relational_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value, ViviCodeStatement **pre_statement)
+    ViviCodeValue **value, ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_LESS_THAN,
     TOKEN_GREATER_THAN, /*TOKEN_LESS_THAN_OR_EQUAL,
     TOKEN_EQUAL_OR_GREATER_THAN, TOKEN_INSTANCEOF, TOKEN_IN,*/ TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, pre_statement, tokens,
+  return parse_operator_expression (scanner, value, statement, tokens,
       PASS_ALWAYS, parse_shift_expression);
 }
 
 static int
 parse_equality_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value, ViviCodeStatement **pre_statement)
+    ViviCodeValue **value, ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_EQUAL,
     /*TOKEN_NOT_EQUAL,*/ TOKEN_STRICT_EQUAL, /*TOKEN_NOT_STRICT_EQUAL,*/
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, pre_statement, tokens,
+  return parse_operator_expression (scanner, value, statement, tokens,
       PASS_ALWAYS, parse_relational_expression);
 }
 
 static int
 parse_bitwise_and_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value, ViviCodeStatement **pre_statement)
+    ViviCodeValue **value, ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_BITWISE_AND,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, pre_statement, tokens,
+  return parse_operator_expression (scanner, value, statement, tokens,
       PASS_ALWAYS, parse_equality_expression);
 }
 
 static int
 parse_bitwise_xor_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value, ViviCodeStatement **pre_statement)
+    ViviCodeValue **value, ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_BITWISE_XOR,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, pre_statement, tokens,
+  return parse_operator_expression (scanner, value, statement, tokens,
       PASS_ALWAYS, parse_bitwise_and_expression);
 }
 
 static int
 parse_bitwise_or_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value, ViviCodeStatement **pre_statement)
+    ViviCodeValue **value, ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_BITWISE_OR,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, pre_statement, tokens,
+  return parse_operator_expression (scanner, value, statement, tokens,
       PASS_ALWAYS, parse_bitwise_xor_expression);
 }
 
 static int
 parse_logical_and_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value, ViviCodeStatement **pre_statement)
+    ViviCodeValue **value, ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_LOGICAL_AND,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, pre_statement, tokens,
+  return parse_operator_expression (scanner, value, statement, tokens,
       PASS_LOGICAL_AND, parse_bitwise_or_expression);
 }
 
 static int
 parse_logical_or_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value, ViviCodeStatement **pre_statement)
+    ViviCodeValue **value, ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_LOGICAL_OR,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, pre_statement, tokens,
+  return parse_operator_expression (scanner, value, statement, tokens,
       PASS_LOGICAL_OR, parse_logical_and_expression);
 }
 
 static int
 parse_conditional_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value, ViviCodeStatement **pre_statement)
+    ViviCodeValue **value, ViviCodeStatement **statement)
 {
   int expected;
   //ViviCodeStatement *if_statement, *else_statement;
 
   *value = NULL;
 
-  expected = parse_logical_or_expression (scanner, value, pre_statement);
+  expected = parse_logical_or_expression (scanner, value, statement);
   if (expected != TOKEN_NONE)
     return expected;
 
@@ -778,24 +818,24 @@ parse_conditional_expression (ViviCompilerScanner *scanner,
 
 static int
 parse_assignment_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value, ViviCodeStatement **pre_statement)
+    ViviCodeValue **value, ViviCodeStatement **statement)
 {
   int expected;
   ViviCodeValue *right;
-  ViviCodeStatement *assignment, *pre_statement_right;
+  ViviCodeStatement *assignment, *statement_right;
   const char *operator;
 
   *value = NULL;
-  *pre_statement = NULL;
+  *statement = NULL;
 
-  expected = parse_conditional_expression (scanner, value, pre_statement);
+  expected = parse_conditional_expression (scanner, value, statement);
   if (expected != TOKEN_NONE)
     return expected;
 
   if (!VIVI_IS_CODE_GET (*value))
     return TOKEN_NONE;
 
-  g_assert (*pre_statement == NULL);
+  g_assert (*statement == NULL);
 
   operator = NULL;
 
@@ -826,7 +866,7 @@ parse_assignment_expression (ViviCompilerScanner *scanner,
     case TOKEN_ASSIGN:
       vivi_compiler_scanner_get_next_token (scanner);
       expected = parse_assignment_expression (scanner, &right,
-	  &pre_statement_right);
+	  &statement_right);
       if (expected != TOKEN_NONE) {
 	g_object_unref (*value);
 	*value = NULL;
@@ -841,16 +881,16 @@ parse_assignment_expression (ViviCompilerScanner *scanner,
       }
       g_object_unref (right);
 
-      if (pre_statement_right != NULL) {
-	*pre_statement = vivi_code_block_new ();
-	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*pre_statement),
-	    pre_statement_right);
-	g_object_unref (pre_statement_right);
-	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*pre_statement),
+      if (statement_right != NULL) {
+	*statement = vivi_code_block_new ();
+	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
+	    statement_right);
+	g_object_unref (statement_right);
+	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
 	    assignment);
 	g_object_unref (assignment);
       } else {
-	*pre_statement = assignment;
+	*statement = assignment;
       }
 
       break;
@@ -863,32 +903,34 @@ parse_assignment_expression (ViviCompilerScanner *scanner,
 }
 
 static int
-parse_expression (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
+parse_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
+    ViviCodeStatement **statement)
 {
-  ViviCodeValue *value;
-  ViviCodeStatement *pre_statement;
+  ViviCodeStatement *statement_one;
   int expected;
 
   *statement = NULL;
 
-  expected = parse_assignment_expression (scanner, &value, &pre_statement);
+  expected = parse_assignment_expression (scanner, value, &statement_one);
   if (expected != TOKEN_NONE)
     return expected;
 
   *statement = vivi_code_block_new ();
 
   do {
-    if (pre_statement != NULL) {
+    if (statement_one != NULL) {
       vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
-	  pre_statement);
-      g_object_unref (pre_statement);
+	  statement_one);
+      g_object_unref (statement_one);
     }
 
     if (!check_token (scanner, TOKEN_COMMA))
       break;
 
-    expected = parse_assignment_expression (scanner, &value, &pre_statement);
+    expected = parse_assignment_expression (scanner, value, &statement_one);
     if (expected != TOKEN_NONE && expected >= 0) {
+      g_object_unref (*value);
+      *value = NULL;
       g_object_unref (*statement);
       *statement = NULL;
       return expected;
@@ -905,6 +947,7 @@ parse_expression_statement (ViviCompilerScanner *scanner,
     ViviCodeStatement **statement)
 {
   int expected;
+  ViviCodeValue *value;
 
   *statement = NULL;
 
@@ -913,11 +956,12 @@ parse_expression_statement (ViviCompilerScanner *scanner,
       scanner->next_token == TOKEN_FUNCTION)
     return -ERROR_TOKEN_EXPRESSION_STATEMENT;
 
-  expected = parse_expression (scanner, statement);
+  expected = parse_expression (scanner, &value, statement);
   if (expected != TOKEN_NONE)
     return expected;
 
   if (!check_token (scanner, TOKEN_SEMICOLON)) {
+    g_object_unref (value);
     g_object_unref (*statement);
     *statement = NULL;
     return TOKEN_SEMICOLON;
@@ -1060,7 +1104,8 @@ parse_function_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **st
     return TOKEN_PARENTHESIS_LEFT;
   }
 
-  expected = parse_literal_list (scanner, parse_identifier, &arguments, TOKEN_COMMA);
+  expected =
+    parse_value_list (scanner, parse_identifier, &arguments, TOKEN_COMMA);
   if (expected != TOKEN_NONE && expected >= 0)
     return expected;
 
@@ -1179,8 +1224,8 @@ parse_statement_list (ViviCompilerScanner *scanner, ParseStatementFunction funct
 }
 
 static int
-parse_literal_list (ViviCompilerScanner *scanner,
-    ParseLiteralFunction function, ViviCodeValue ***list, guint separator)
+parse_value_list (ViviCompilerScanner *scanner, ParseValueFunction function,
+    ViviCodeValue ***list, guint separator)
 {
   GPtrArray *array;
   ViviCodeValue *value;
@@ -1190,6 +1235,8 @@ parse_literal_list (ViviCompilerScanner *scanner,
   g_assert (function != NULL);
   g_assert (list != NULL);
 
+  **list = NULL;
+
   expected = function (scanner, &value);
   if (expected != TOKEN_NONE)
     return expected;
commit a0a050ebcd63967ac65a5ad43224b8c3f74abf83
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed Apr 2 14:23:33 2008 +0300

    Implement the parsing of assignment expressions

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 3a1ef0f..1513e0a 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -781,8 +781,12 @@ parse_assignment_expression (ViviCompilerScanner *scanner,
     ViviCodeValue **value, ViviCodeStatement **pre_statement)
 {
   int expected;
+  ViviCodeValue *right;
+  ViviCodeStatement *assignment, *pre_statement_right;
+  const char *operator;
 
   *value = NULL;
+  *pre_statement = NULL;
 
   expected = parse_conditional_expression (scanner, value, pre_statement);
   if (expected != TOKEN_NONE)
@@ -791,20 +795,65 @@ parse_assignment_expression (ViviCompilerScanner *scanner,
   if (!VIVI_IS_CODE_GET (*value))
     return TOKEN_NONE;
 
+  g_assert (*pre_statement == NULL);
+
+  operator = NULL;
+
   vivi_compiler_scanner_peek_next_token (scanner);
   switch ((int)scanner->next_token) {
-    case TOKEN_ASSIGN:
-    /*case TOKEN_ASSIGN_MULTIPLY:
+    case TOKEN_ASSIGN_MULTIPLY:
+      if (operator == NULL) operator = "*";
     case TOKEN_ASSIGN_DIVIDE:
+      if (operator == NULL) operator = "/";
     case TOKEN_ASSIGN_REMAINDER:
+      if (operator == NULL) operator = "%";
     case TOKEN_ASSIGN_ADD:
+      if (operator == NULL) operator = "+";
     case TOKEN_ASSIGN_MINUS:
+      if (operator == NULL) operator = "-";
     case TOKEN_ASSIGN_SHIFT_LEFT:
+      if (operator == NULL) operator = "<<";
     case TOKEN_ASSIGN_SHIFT_RIGHT:
+      if (operator == NULL) operator = ">>";
     case TOKEN_ASSIGN_SHIFT_RIGHT_ZERO:
+      if (operator == NULL) operator = ">>>";
     case TOKEN_ASSIGN_BITWISE_AND:
+      if (operator == NULL) operator = "&";
     case TOKEN_ASSIGN_BITWISE_OR:
-    case TOKEN_ASSIGN_BITWISE_XOR:*/
+      if (operator == NULL) operator = "|";
+    case TOKEN_ASSIGN_BITWISE_XOR:
+      if (operator == NULL) operator = "^";
+    case TOKEN_ASSIGN:
+      vivi_compiler_scanner_get_next_token (scanner);
+      expected = parse_assignment_expression (scanner, &right,
+	  &pre_statement_right);
+      if (expected != TOKEN_NONE) {
+	g_object_unref (*value);
+	*value = NULL;
+	return FAIL (expected);
+      }
+
+      if (operator != NULL) {
+	assignment = vivi_code_assignment_new (NULL, *value,
+	    vivi_code_binary_new_name (*value, right, operator));
+      } else {
+	assignment = vivi_code_assignment_new (NULL, *value, right);
+      }
+      g_object_unref (right);
+
+      if (pre_statement_right != NULL) {
+	*pre_statement = vivi_code_block_new ();
+	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*pre_statement),
+	    pre_statement_right);
+	g_object_unref (pre_statement_right);
+	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*pre_statement),
+	    assignment);
+	g_object_unref (assignment);
+      } else {
+	*pre_statement = assignment;
+      }
+
+      break;
     default:
       return TOKEN_NONE;
   }
commit 585e399677054e86b0f7e70e6f1a960db9a11d60
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed Apr 2 14:01:43 2008 +0300

    Handle || and && better with side-effects

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 128757b..3a1ef0f 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -539,10 +539,16 @@ parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
   }
 }
 
+typedef enum {
+  PASS_ALWAYS,
+  PASS_LOGICAL_OR,
+  PASS_LOGICAL_AND
+} ParseOperatorPass;
+
 static int
 parse_operator_expression (ViviCompilerScanner *scanner,
     ViviCodeValue **value, ViviCodeStatement **pre_statement,
-    const ViviCompilerScannerToken *tokens,
+    const ViviCompilerScannerToken *tokens, ParseOperatorPass pass,
     ParseValueFunction next_parse_function)
 {
   int expected, i;
@@ -566,7 +572,29 @@ parse_operator_expression (ViviCompilerScanner *scanner,
       }
 
       if (pre_statement_right != NULL) {
-	ViviCodeStatement *pre_statement_left = *pre_statement;
+	ViviCodeStatement *pre_statement_left, *tmp;
+
+	switch (pass) {
+	  case PASS_LOGICAL_OR:
+	    tmp = vivi_code_if_new (vivi_code_unary_new (*value, '!'));
+	    vivi_code_if_set_if (VIVI_CODE_IF (tmp), pre_statement_right);
+	    g_object_unref (pre_statement_right);
+	    pre_statement_right = tmp;
+	    break;
+	  case PASS_LOGICAL_AND:
+	    tmp = vivi_code_if_new (*value);
+	    vivi_code_if_set_if (VIVI_CODE_IF (tmp), pre_statement_right);
+	    g_object_unref (pre_statement_right);
+	    pre_statement_right = tmp;
+	    break;
+	  case PASS_ALWAYS:
+	    // nothing
+	    break;
+	  default:
+	    g_assert_not_reached ();
+	}
+
+	pre_statement_left = *pre_statement;
 	*pre_statement = vivi_code_block_new ();
 	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*pre_statement),
 	    pre_statement_left);
@@ -593,7 +621,7 @@ parse_multiplicative_expression (ViviCompilerScanner *scanner,
     TOKEN_DIVIDE, TOKEN_REMAINDER, TOKEN_NONE };
 
   return parse_operator_expression (scanner, value, pre_statement, tokens,
-      parse_unary_expression);
+      PASS_ALWAYS, parse_unary_expression);
 }
 
 static int
@@ -604,7 +632,7 @@ parse_additive_expression (ViviCompilerScanner *scanner,
     TOKEN_NONE };
 
   return parse_operator_expression (scanner, value, pre_statement, tokens,
-      parse_multiplicative_expression);
+      PASS_ALWAYS, parse_multiplicative_expression);
 }
 
 static int
@@ -615,7 +643,7 @@ parse_shift_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
     TOKEN_SHIFT_RIGHT, TOKEN_SHIFT_RIGHT_UNSIGNED, TOKEN_NONE };
 
   return parse_operator_expression (scanner, value, pre_statement, tokens,
-      parse_additive_expression);
+      PASS_ALWAYS, parse_additive_expression);
 }
 
 static int
@@ -627,7 +655,7 @@ parse_relational_expression (ViviCompilerScanner *scanner,
     TOKEN_EQUAL_OR_GREATER_THAN, TOKEN_INSTANCEOF, TOKEN_IN,*/ TOKEN_NONE };
 
   return parse_operator_expression (scanner, value, pre_statement, tokens,
-      parse_shift_expression);
+      PASS_ALWAYS, parse_shift_expression);
 }
 
 static int
@@ -639,7 +667,7 @@ parse_equality_expression (ViviCompilerScanner *scanner,
     TOKEN_NONE };
 
   return parse_operator_expression (scanner, value, pre_statement, tokens,
-      parse_relational_expression);
+      PASS_ALWAYS, parse_relational_expression);
 }
 
 static int
@@ -650,7 +678,7 @@ parse_bitwise_and_expression (ViviCompilerScanner *scanner,
     TOKEN_NONE };
 
   return parse_operator_expression (scanner, value, pre_statement, tokens,
-      parse_equality_expression);
+      PASS_ALWAYS, parse_equality_expression);
 }
 
 static int
@@ -661,7 +689,7 @@ parse_bitwise_xor_expression (ViviCompilerScanner *scanner,
     TOKEN_NONE };
 
   return parse_operator_expression (scanner, value, pre_statement, tokens,
-      parse_bitwise_and_expression);
+      PASS_ALWAYS, parse_bitwise_and_expression);
 }
 
 static int
@@ -672,7 +700,7 @@ parse_bitwise_or_expression (ViviCompilerScanner *scanner,
     TOKEN_NONE };
 
   return parse_operator_expression (scanner, value, pre_statement, tokens,
-      parse_bitwise_xor_expression);
+      PASS_ALWAYS, parse_bitwise_xor_expression);
 }
 
 static int
@@ -683,7 +711,7 @@ parse_logical_and_expression (ViviCompilerScanner *scanner,
     TOKEN_NONE };
 
   return parse_operator_expression (scanner, value, pre_statement, tokens,
-      parse_bitwise_or_expression);
+      PASS_LOGICAL_AND, parse_bitwise_or_expression);
 }
 
 static int
@@ -694,7 +722,7 @@ parse_logical_or_expression (ViviCompilerScanner *scanner,
     TOKEN_NONE };
 
   return parse_operator_expression (scanner, value, pre_statement, tokens,
-      parse_logical_and_expression);
+      PASS_LOGICAL_OR, parse_logical_and_expression);
 }
 
 static int
commit 41cf66655511e0b671098030d812123c474957cd
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed Apr 2 13:45:49 2008 +0300

    Make postfix operators (hopefully) work right

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 85d2055..128757b 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -46,6 +46,8 @@
 #include "vivi_code_unary.h"
 #include "vivi_code_value_statement.h"
 #include "vivi_compiler_empty_statement.h"
+#include "vivi_compiler_get_temporary.h"
+
 
 #include "vivi_code_text_printer.h"
 
@@ -432,7 +434,7 @@ parse_postfix_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
     ViviCodeStatement **pre_statement)
 {
   int expected;
-  ViviCodeValue *tmp, *one;
+  ViviCodeValue *operation, *one, *temporary;
   const char *operator;
 
   *value = NULL;
@@ -457,15 +459,22 @@ parse_postfix_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
   }
 
   one = vivi_code_constant_new_number (1);
-  tmp = vivi_code_binary_new_name (*value, one, operator);
+  operation = vivi_code_binary_new_name (*value, one, operator);
   g_object_unref (one);
 
   g_assert (*pre_statement == NULL);
 
   *pre_statement = vivi_code_block_new ();
+
+  temporary = vivi_compiler_get_temporary_new ();
   vivi_code_block_add_statement (VIVI_CODE_BLOCK (*pre_statement),
-      vivi_code_assignment_new (NULL, *value, tmp));
-  g_object_unref (tmp);
+      vivi_code_assignment_new (NULL, temporary, *value));
+  vivi_code_block_add_statement (VIVI_CODE_BLOCK (*pre_statement),
+      vivi_code_assignment_new (NULL, *value, operation));
+  g_object_unref (operation);
+
+  g_object_unref (*value);
+  *value = temporary;
 
   return TOKEN_NONE;
 }
@@ -556,6 +565,15 @@ parse_operator_expression (ViviCompilerScanner *scanner,
 	return FAIL (expected);
       }
 
+      if (pre_statement_right != NULL) {
+	ViviCodeStatement *pre_statement_left = *pre_statement;
+	*pre_statement = vivi_code_block_new ();
+	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*pre_statement),
+	    pre_statement_left);
+	vivi_code_block_add_statement (VIVI_CODE_BLOCK (*pre_statement),
+	    pre_statement_right);
+      }
+
       left = VIVI_CODE_VALUE (*value);
       *value = vivi_code_binary_new_name (left, VIVI_CODE_VALUE (right),
 	  vivi_compiler_scanner_token_name (tokens[i]));
@@ -734,11 +752,37 @@ static int
 parse_assignment_expression (ViviCompilerScanner *scanner,
     ViviCodeValue **value, ViviCodeStatement **pre_statement)
 {
+  int expected;
+
   *value = NULL;
 
-  // TODO
+  expected = parse_conditional_expression (scanner, value, pre_statement);
+  if (expected != TOKEN_NONE)
+    return expected;
 
-  return parse_conditional_expression (scanner, value, pre_statement);
+  if (!VIVI_IS_CODE_GET (*value))
+    return TOKEN_NONE;
+
+  vivi_compiler_scanner_peek_next_token (scanner);
+  switch ((int)scanner->next_token) {
+    case TOKEN_ASSIGN:
+    /*case TOKEN_ASSIGN_MULTIPLY:
+    case TOKEN_ASSIGN_DIVIDE:
+    case TOKEN_ASSIGN_REMAINDER:
+    case TOKEN_ASSIGN_ADD:
+    case TOKEN_ASSIGN_MINUS:
+    case TOKEN_ASSIGN_SHIFT_LEFT:
+    case TOKEN_ASSIGN_SHIFT_RIGHT:
+    case TOKEN_ASSIGN_SHIFT_RIGHT_ZERO:
+    case TOKEN_ASSIGN_BITWISE_AND:
+    case TOKEN_ASSIGN_BITWISE_OR:
+    case TOKEN_ASSIGN_BITWISE_XOR:*/
+    default:
+      return TOKEN_NONE;
+  }
+
+
+  return TOKEN_NONE;
 }
 
 static int
diff --git a/vivified/code/vivi_compiler_get_temporary.c b/vivified/code/vivi_compiler_get_temporary.c
index 8876502..2b5b515 100644
--- a/vivified/code/vivi_compiler_get_temporary.c
+++ b/vivified/code/vivi_compiler_get_temporary.c
@@ -45,7 +45,7 @@ vivi_compiler_get_temporary_new (void)
 {
   static int counter = 0;
   ViviCompilerGetTemporary *get;
-  char *name = g_strdup_printf ("_%i", ++counter);
+  char *name = g_strdup_printf ("$%i", ++counter);
 
   get = g_object_new (VIVI_TYPE_COMPILER_GET_TEMPORARY, NULL);
   VIVI_CODE_GET (get)->name = vivi_code_constant_new_string (name);
diff --git a/vivified/code/vivi_compiler_get_temporary.h b/vivified/code/vivi_compiler_get_temporary.h
index 5c5bcf8..43b0baf 100644
--- a/vivified/code/vivi_compiler_get_temporary.h
+++ b/vivified/code/vivi_compiler_get_temporary.h
@@ -20,7 +20,7 @@
 #ifndef _VIVI_COMPILER_GET_TEMPORARY_H_
 #define _VIVI_COMPILER_GET_TEMPORARY_H_
 
-#include <vivified/code/vivi_code_value.h>
+#include <vivified/code/vivi_code_get.h>
 
 G_BEGIN_DECLS
 
@@ -37,12 +37,12 @@ typedef struct _ViviCompilerGetTemporaryClass ViviCompilerGetTemporaryClass;
 
 struct _ViviCompilerGetTemporary
 {
-  ViviCodeValue		value;
+  ViviCodeGet		value;
 };
 
 struct _ViviCompilerGetTemporaryClass
 {
-  ViviCodeValueClass	value_class;
+  ViviCodeGetClass	value_class;
 };
 
 GType			vivi_compiler_get_temporary_get_type   	(void);
commit a503cf49aaae664f65b9be838fe984e702718524
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed Apr 2 13:04:56 2008 +0300

    Checking for a wrong token here

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index dd448f7..85d2055 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -261,7 +261,8 @@ parse_assignment_expression (ViviCompilerScanner *scanner,
     ViviCodeValue **value, ViviCodeStatement **pre_statement);
 
 static int
-parse_variable_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
+parse_variable_declaration (ViviCompilerScanner *scanner,
+    ViviCodeStatement **statement)
 {
   int expected;
   ViviCodeValue *identifier, *value;
@@ -274,7 +275,7 @@ parse_variable_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **st
   if (expected != TOKEN_NONE)
     return expected;
 
-  if (check_token (scanner, TOKEN_EQUAL)) {
+  if (check_token (scanner, TOKEN_ASSIGN)) {
     expected = parse_assignment_expression (scanner, &value, &pre_statement);
     if (expected != TOKEN_NONE) {
       g_object_unref (identifier);
@@ -284,7 +285,6 @@ parse_variable_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **st
     value = vivi_code_constant_new_undefined ();
   }
 
-
   assignment = vivi_code_assignment_new (NULL, identifier, value);
   vivi_code_assignment_set_local (VIVI_CODE_ASSIGNMENT (assignment), TRUE);
 
@@ -860,8 +860,8 @@ parse_variable_statement (ViviCompilerScanner *scanner, ViviCodeStatement **stat
   if (!check_token (scanner, TOKEN_VAR))
     return -TOKEN_VAR;
 
-  expected =
-    parse_statement_list (scanner, parse_variable_declaration, statement, TOKEN_COMMA);
+  expected = parse_statement_list (scanner, parse_variable_declaration,
+      statement, TOKEN_COMMA);
   if (expected != TOKEN_NONE)
     return FAIL (expected);
 
commit 758206ecba33302efa867cd1b948612f63eec2cb
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed Apr 2 12:53:11 2008 +0300

    Start working on expression side effect support and add simple error messages

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index cd866af..64a6960 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -33,6 +33,7 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_value_statement.c \
 	vivi_compiler.c \
 	vivi_compiler_empty_statement.c \
+	vivi_compiler_get_temporary.c \
 	vivi_compiler_scanner.c \
 	vivi_compiler_scanner_lex.c \
 	vivi_decompiler_block.c \
@@ -69,6 +70,7 @@ noinst_HEADERS = \
 	vivi_code_value_statement.h \
 	vivi_compiler.h \
 	vivi_compiler_empty_statement.h \
+	vivi_compiler_get_temporary.h \
 	vivi_compiler_scanner.h \
 	vivi_compiler_scanner_lex.h \
 	vivi_compiler_scanner_lex_include.h \
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 70b5832..dd448f7 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -60,12 +60,13 @@ enum {
 #define FAIL(x) ((x) < 0 ? -x : x)
 
 typedef int (*ParseStatementFunction) (ViviCompilerScanner *scanner, ViviCodeStatement **statement);
-typedef int (*ParseValueFunction) (ViviCompilerScanner *scanner, ViviCodeValue **value);
+typedef int (*ParseValueFunction) (ViviCompilerScanner *scanner, ViviCodeValue **value, ViviCodeStatement **pre_statement);
+typedef int (*ParseLiteralFunction) (ViviCompilerScanner *scanner, ViviCodeValue **value);
 
 static int
 parse_statement_list (ViviCompilerScanner *scanner, ParseStatementFunction function, ViviCodeStatement **statement, guint separator);
 static int
-parse_value_list (ViviCompilerScanner *scanner, ParseValueFunction function, ViviCodeValue ***list, guint separator);
+parse_literal_list (ViviCompilerScanner *scanner, ParseLiteralFunction function, ViviCodeValue ***list, guint separator);
 
 // helpers
 
@@ -144,7 +145,7 @@ static int
 parse_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   int i, expected;
-  ParseValueFunction functions[] = {
+  ParseLiteralFunction functions[] = {
     parse_null_literal,
     parse_boolean_literal,
     parse_numeric_literal,
@@ -180,7 +181,7 @@ static int
 parse_property_name (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   int i, expected;
-  ParseValueFunction functions[] = {
+  ParseLiteralFunction functions[] = {
     parse_identifier,
     parse_string_literal,
     parse_numeric_literal,
@@ -199,7 +200,7 @@ parse_property_name (ViviCompilerScanner *scanner, ViviCodeValue **value)
 }
 
 static int
-parse_logical_or_expression (ViviCompilerScanner *scanner, ViviCodeValue **value);
+parse_logical_or_expression (ViviCompilerScanner *scanner, ViviCodeValue **value, ViviCodeStatement **pre_statement);
 
 static int
 parse_object_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
@@ -216,6 +217,7 @@ parse_object_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
   if (!check_token (scanner, TOKEN_BRACE_RIGHT)) {
     do {
       ViviCodeValue *property, *initializer;
+      ViviCodeStatement *pre_statement = NULL;
 
       expected = parse_property_name (scanner, &property);
       if (expected != TOKEN_NONE) {
@@ -231,7 +233,7 @@ parse_object_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
       }
 
       // FIXME: assignment expression
-      expected = parse_logical_or_expression (scanner, &initializer);
+      expected = parse_logical_or_expression (scanner, &initializer, &pre_statement);
       if (expected != TOKEN_NONE) {
 	g_object_unref (*value);
 	*value = NULL;
@@ -255,21 +257,25 @@ parse_object_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
 // misc
 
 static int
+parse_assignment_expression (ViviCompilerScanner *scanner,
+    ViviCodeValue **value, ViviCodeStatement **pre_statement);
+
+static int
 parse_variable_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 {
   int expected;
-  ViviCodeValue *identifier;
-  ViviCodeValue *value;
+  ViviCodeValue *identifier, *value;
+  ViviCodeStatement *pre_statement, *assignment;
 
   *statement = NULL;
+  pre_statement = NULL;
 
   expected = parse_identifier (scanner, &identifier);
   if (expected != TOKEN_NONE)
     return expected;
 
   if (check_token (scanner, TOKEN_EQUAL)) {
-    // FIXME: assignment expression
-    expected = parse_logical_or_expression (scanner, &value);
+    expected = parse_assignment_expression (scanner, &value, &pre_statement);
     if (expected != TOKEN_NONE) {
       g_object_unref (identifier);
       return FAIL (expected);
@@ -278,8 +284,20 @@ parse_variable_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **st
     value = vivi_code_constant_new_undefined ();
   }
 
-  *statement = vivi_code_assignment_new (NULL, identifier, value);
-  vivi_code_assignment_set_local (VIVI_CODE_ASSIGNMENT (*statement), TRUE);
+
+  assignment = vivi_code_assignment_new (NULL, identifier, value);
+  vivi_code_assignment_set_local (VIVI_CODE_ASSIGNMENT (assignment), TRUE);
+
+  if (pre_statement != NULL) {
+    *statement = vivi_code_block_new ();
+    vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
+	pre_statement);
+    g_object_unref (pre_statement);
+    vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement), assignment);
+    g_object_unref (assignment);
+  } else {
+    *statement = assignment;
+  }
 
   return TOKEN_NONE;
 }
@@ -290,7 +308,7 @@ static int
 parse_primary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   int i, expected;
-  ParseValueFunction functions[] = {
+  ParseLiteralFunction functions[] = {
     parse_identifier,
     parse_literal,
     //parse_array_literal,
@@ -306,8 +324,9 @@ parse_primary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
   }
 
   if (check_token (scanner, TOKEN_PARENTHESIS_LEFT)) {
+    ViviCodeStatement *pre_statement = NULL;
     // FIXME: assignment expression
-    expected = parse_logical_or_expression (scanner, value);
+    expected = parse_logical_or_expression (scanner, value, &pre_statement);
     if (expected != TOKEN_NONE)
       return FAIL (expected);
     if (!check_token (scanner, TOKEN_PARENTHESIS_RIGHT)) {
@@ -332,6 +351,7 @@ parse_member_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   int expected;
   ViviCodeValue *member;
+  ViviCodeStatement *pre_statement = NULL;
 
   // TODO: new MemberExpression Arguments
 
@@ -347,7 +367,7 @@ parse_member_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 
     if (check_token (scanner, TOKEN_BRACKET_LEFT)) {
       // FIXME: expression
-      expected = parse_logical_or_expression (scanner, &member);
+      expected = parse_logical_or_expression (scanner, &member, &pre_statement);
       if (expected != TOKEN_NONE)
 	return FAIL (expected);
       if (!check_token (scanner, TOKEN_BRACKET_RIGHT))
@@ -408,12 +428,15 @@ parse_left_hand_side_expression (ViviCompilerScanner *scanner, ViviCodeValue **v
 }
 
 static int
-parse_postfix_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
+parse_postfix_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
+    ViviCodeStatement **pre_statement)
 {
   int expected;
   ViviCodeValue *tmp, *one;
   const char *operator;
 
+  *value = NULL;
+
   expected = parse_left_hand_side_expression (scanner, value);
   if (expected != TOKEN_NONE)
     return expected;
@@ -428,39 +451,74 @@ parse_postfix_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
     return TOKEN_NONE;
   }
 
+  if (!VIVI_IS_CODE_GET (*value)) {
+    g_printerr ("Invalid INCREASE/DECREASE\n");
+    return -scanner->token;
+  }
+
   one = vivi_code_constant_new_number (1);
+  tmp = vivi_code_binary_new_name (*value, one, operator);
+  g_object_unref (one);
 
-  // FIXME: Side effect!
-  tmp = *value;
-  *value = vivi_code_binary_new_name (tmp, one, operator);
-  g_object_unref (tmp);
+  g_assert (*pre_statement == NULL);
 
-  g_object_unref (one);
+  *pre_statement = vivi_code_block_new ();
+  vivi_code_block_add_statement (VIVI_CODE_BLOCK (*pre_statement),
+      vivi_code_assignment_new (NULL, *value, tmp));
+  g_object_unref (tmp);
 
   return TOKEN_NONE;
 }
 
 static int
-parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
+parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
+    ViviCodeStatement **pre_statement)
 {
   int expected;
-  ViviCodeValue *tmp;
+  ViviCodeValue *tmp, *one;
+  const char *operator;
 
   *value = NULL;
 
+  operator = NULL;
+
   vivi_compiler_scanner_peek_next_token (scanner);
   switch ((int)scanner->next_token) {
     /*case TOKEN_DELETE:
     case TOKEN_VOID:
-    case TOKEN_TYPEOF:
+    case TOKEN_TYPEOF:*/
     case TOKEN_INCREASE:
+      operator = "+";
+      // fall through
     case TOKEN_DESCREASE:
-    case TOKEN_PLUS:
+      if (!operator) operator = "-";
+
+      vivi_compiler_scanner_get_next_token (scanner);
+      expected = parse_unary_expression (scanner, value, pre_statement);
+      if (expected != TOKEN_NONE)
+	return FAIL (expected);
+
+      if (!VIVI_IS_CODE_GET (*value)) {
+	g_printerr ("Invalid INCREASE/DECREASE\n");
+	return -scanner->token;
+      }
+
+      one = vivi_code_constant_new_number (1);
+      tmp = vivi_code_binary_new_name (*value, one, operator);
+      g_object_unref (one);
+
+      g_assert (*pre_statement == NULL);
+
+      *pre_statement = vivi_code_assignment_new (NULL, *value, tmp);
+      g_object_unref (tmp);
+
+      return TOKEN_NONE;
+    /*case TOKEN_PLUS:
     case TOKEN_MINUS:
     case TOKEN_BITWISE_NOT:*/
     case TOKEN_LOGICAL_NOT:
       vivi_compiler_scanner_get_next_token (scanner);
-      expected = parse_unary_expression (scanner, value);
+      expected = parse_unary_expression (scanner, value, pre_statement);
       if (expected != TOKEN_NONE)
 	return FAIL (expected);
       tmp = VIVI_CODE_VALUE (*value);
@@ -468,28 +526,30 @@ parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
       g_object_unref (tmp);
       return TOKEN_NONE;
     default:
-      return parse_postfix_expression (scanner, value);
+      return parse_postfix_expression (scanner, value, pre_statement);
   }
 }
 
 static int
 parse_operator_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value, const ViviCompilerScannerToken *tokens,
+    ViviCodeValue **value, ViviCodeStatement **pre_statement,
+    const ViviCompilerScannerToken *tokens,
     ParseValueFunction next_parse_function)
 {
   int expected, i;
-  ViviCodeValue *left;
-  ViviCodeValue *right;
+  ViviCodeValue *left, *right;
+  ViviCodeStatement *pre_statement_right;
 
   *value = NULL;
+  *pre_statement = NULL;
 
-  expected = next_parse_function (scanner, value);
+  expected = next_parse_function (scanner, value, pre_statement);
   if (expected != TOKEN_NONE)
     return expected;
 
   for (i = 0; tokens[i] != TOKEN_NONE; i++) {
     if (check_token (scanner, tokens[i])) {
-      expected = next_parse_function (scanner, &right);
+      expected = next_parse_function (scanner, &right, &pre_statement_right);
       if (expected != TOKEN_NONE) {
 	g_object_unref (*value);
 	*value = NULL;
@@ -509,131 +569,130 @@ parse_operator_expression (ViviCompilerScanner *scanner,
 
 static int
 parse_multiplicative_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value)
+    ViviCodeValue **value, ViviCodeStatement **pre_statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_MULTIPLY,
     TOKEN_DIVIDE, TOKEN_REMAINDER, TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, tokens,
+  return parse_operator_expression (scanner, value, pre_statement, tokens,
       parse_unary_expression);
 }
 
 static int
 parse_additive_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value)
+    ViviCodeValue **value, ViviCodeStatement **pre_statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_PLUS, TOKEN_MINUS,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, tokens,
+  return parse_operator_expression (scanner, value, pre_statement, tokens,
       parse_multiplicative_expression);
 }
 
 static int
-parse_shift_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
+parse_shift_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
+    ViviCodeStatement **pre_statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_SHIFT_LEFT,
     TOKEN_SHIFT_RIGHT, TOKEN_SHIFT_RIGHT_UNSIGNED, TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, tokens,
+  return parse_operator_expression (scanner, value, pre_statement, tokens,
       parse_additive_expression);
 }
 
 static int
 parse_relational_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value)
+    ViviCodeValue **value, ViviCodeStatement **pre_statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_LESS_THAN,
     TOKEN_GREATER_THAN, /*TOKEN_LESS_THAN_OR_EQUAL,
     TOKEN_EQUAL_OR_GREATER_THAN, TOKEN_INSTANCEOF, TOKEN_IN,*/ TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, tokens,
+  return parse_operator_expression (scanner, value, pre_statement, tokens,
       parse_shift_expression);
 }
 
 static int
 parse_equality_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value)
+    ViviCodeValue **value, ViviCodeStatement **pre_statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_EQUAL,
     /*TOKEN_NOT_EQUAL,*/ TOKEN_STRICT_EQUAL, /*TOKEN_NOT_STRICT_EQUAL,*/
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, tokens,
+  return parse_operator_expression (scanner, value, pre_statement, tokens,
       parse_relational_expression);
 }
 
 static int
 parse_bitwise_and_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value)
+    ViviCodeValue **value, ViviCodeStatement **pre_statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_BITWISE_AND,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, tokens,
+  return parse_operator_expression (scanner, value, pre_statement, tokens,
       parse_equality_expression);
 }
 
 static int
 parse_bitwise_xor_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value)
+    ViviCodeValue **value, ViviCodeStatement **pre_statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_BITWISE_XOR,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, tokens,
+  return parse_operator_expression (scanner, value, pre_statement, tokens,
       parse_bitwise_and_expression);
 }
 
 static int
 parse_bitwise_or_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value)
+    ViviCodeValue **value, ViviCodeStatement **pre_statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_BITWISE_OR,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, tokens,
+  return parse_operator_expression (scanner, value, pre_statement, tokens,
       parse_bitwise_xor_expression);
 }
 
 static int
 parse_logical_and_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value)
+    ViviCodeValue **value, ViviCodeStatement **pre_statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_LOGICAL_AND,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, tokens,
+  return parse_operator_expression (scanner, value, pre_statement, tokens,
       parse_bitwise_or_expression);
 }
 
 static int
 parse_logical_or_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value)
+    ViviCodeValue **value, ViviCodeStatement **pre_statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_LOGICAL_OR,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, tokens,
+  return parse_operator_expression (scanner, value, pre_statement, tokens,
       parse_logical_and_expression);
 }
 
 static int
-parse_assignment_expression (ViviCompilerScanner *scanner, ViviCodeStatement **statement);
-
-static int
-parse_conditional_expression (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
+parse_conditional_expression (ViviCompilerScanner *scanner,
+    ViviCodeValue **value, ViviCodeStatement **pre_statement)
 {
   int expected;
-  ViviCodeValue *value;
-  ViviCodeStatement *if_statement, *else_statement;
+  //ViviCodeStatement *if_statement, *else_statement;
 
-  *statement = NULL;
+  *value = NULL;
 
-  expected = parse_logical_or_expression (scanner, &value);
+  expected = parse_logical_or_expression (scanner, value, pre_statement);
   if (expected != TOKEN_NONE)
     return expected;
 
+#if 0
   if (!check_token (scanner, TOKEN_QUESTION_MARK)) {
     *statement = vivi_code_value_statement_new (VIVI_CODE_VALUE (value));
     g_object_unref (value);
@@ -666,40 +725,71 @@ parse_conditional_expression (ViviCompilerScanner *scanner, ViviCodeStatement **
   g_object_unref (value);
   g_object_unref (if_statement);
   g_object_unref (else_statement);
+#endif
 
   return TOKEN_NONE;
 }
 
 static int
-parse_assignment_expression (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
+parse_assignment_expression (ViviCompilerScanner *scanner,
+    ViviCodeValue **value, ViviCodeStatement **pre_statement)
 {
-  *statement = NULL;
+  *value = NULL;
 
   // TODO
 
-  return parse_conditional_expression (scanner, statement);
+  return parse_conditional_expression (scanner, value, pre_statement);
 }
 
 static int
 parse_expression (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 {
+  ViviCodeValue *value;
+  ViviCodeStatement *pre_statement;
+  int expected;
+
   *statement = NULL;
 
-  return parse_statement_list (scanner, parse_assignment_expression, statement,
-      TOKEN_COMMA);
+  expected = parse_assignment_expression (scanner, &value, &pre_statement);
+  if (expected != TOKEN_NONE)
+    return expected;
+
+  *statement = vivi_code_block_new ();
+
+  do {
+    if (pre_statement != NULL) {
+      vivi_code_block_add_statement (VIVI_CODE_BLOCK (*statement),
+	  pre_statement);
+      g_object_unref (pre_statement);
+    }
+
+    if (!check_token (scanner, TOKEN_COMMA))
+      break;
+
+    expected = parse_assignment_expression (scanner, &value, &pre_statement);
+    if (expected != TOKEN_NONE && expected >= 0) {
+      g_object_unref (*statement);
+      *statement = NULL;
+      return expected;
+    }
+  } while (expected == TOKEN_NONE);
+
+  return TOKEN_NONE;
 }
 
 // statement
 
 static int
-parse_expression_statement (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
+parse_expression_statement (ViviCompilerScanner *scanner,
+    ViviCodeStatement **statement)
 {
   int expected;
 
   *statement = NULL;
 
   vivi_compiler_scanner_peek_next_token (scanner);
-  if (scanner->next_token == TOKEN_BRACE_LEFT || scanner->next_token == TOKEN_FUNCTION)
+  if (scanner->next_token == TOKEN_BRACE_LEFT ||
+      scanner->next_token == TOKEN_FUNCTION)
     return -ERROR_TOKEN_EXPRESSION_STATEMENT;
 
   expected = parse_expression (scanner, statement);
@@ -849,7 +939,7 @@ parse_function_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **st
     return TOKEN_PARENTHESIS_LEFT;
   }
 
-  expected = parse_value_list (scanner, parse_identifier, &arguments, TOKEN_COMMA);
+  expected = parse_literal_list (scanner, parse_identifier, &arguments, TOKEN_COMMA);
   if (expected != TOKEN_NONE && expected >= 0)
     return expected;
 
@@ -968,8 +1058,8 @@ parse_statement_list (ViviCompilerScanner *scanner, ParseStatementFunction funct
 }
 
 static int
-parse_value_list (ViviCompilerScanner *scanner, ParseValueFunction function,
-    ViviCodeValue ***list, guint separator)
+parse_literal_list (ViviCompilerScanner *scanner,
+    ParseLiteralFunction function, ViviCodeValue ***list, guint separator)
 {
   GPtrArray *array;
   ViviCodeValue *value;
@@ -1019,6 +1109,11 @@ vivi_compile_file (FILE *file, const char *input_name)
   g_assert ((expected == TOKEN_NONE && VIVI_IS_CODE_STATEMENT (statement)) ||
 	(expected != TOKEN_NONE && statement == NULL));
 
+  if (expected != TOKEN_NONE) {
+    vivi_compiler_scanner_get_next_token (scanner);
+    vivi_compiler_scanner_unexp_token (scanner, expected);
+  }
+
   g_object_unref (scanner);
 
   return statement;
diff --git a/vivified/code/vivi_compiler_get_temporary.c b/vivified/code/vivi_compiler_get_temporary.c
new file mode 100644
index 0000000..8876502
--- /dev/null
+++ b/vivified/code/vivi_compiler_get_temporary.c
@@ -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
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "vivi_compiler_get_temporary.h"
+
+#include "vivi_code_get.h"
+#include "vivi_code_constant.h"
+#include "vivi_code_printer.h"
+
+G_DEFINE_TYPE (ViviCompilerGetTemporary, vivi_compiler_get_temporary, VIVI_TYPE_CODE_GET)
+
+static void
+vivi_compiler_get_temporary_class_init (ViviCompilerGetTemporaryClass *klass)
+{
+}
+
+static void
+vivi_compiler_get_temporary_init (ViviCompilerGetTemporary *get)
+{
+}
+
+ViviCodeValue *
+vivi_compiler_get_temporary_new (void)
+{
+  static int counter = 0;
+  ViviCompilerGetTemporary *get;
+  char *name = g_strdup_printf ("_%i", ++counter);
+
+  get = g_object_new (VIVI_TYPE_COMPILER_GET_TEMPORARY, NULL);
+  VIVI_CODE_GET (get)->name = vivi_code_constant_new_string (name);
+
+  g_free (name);
+
+  return VIVI_CODE_VALUE (get);
+}
diff --git a/vivified/code/vivi_compiler_get_temporary.h b/vivified/code/vivi_compiler_get_temporary.h
new file mode 100644
index 0000000..5c5bcf8
--- /dev/null
+++ b/vivified/code/vivi_compiler_get_temporary.h
@@ -0,0 +1,54 @@
+/* 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_COMPILER_GET_TEMPORARY_H_
+#define _VIVI_COMPILER_GET_TEMPORARY_H_
+
+#include <vivified/code/vivi_code_value.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCompilerGetTemporary ViviCompilerGetTemporary;
+typedef struct _ViviCompilerGetTemporaryClass ViviCompilerGetTemporaryClass;
+
+#define VIVI_TYPE_COMPILER_GET_TEMPORARY                    (vivi_compiler_get_temporary_get_type())
+#define VIVI_IS_COMPILER_GET_TEMPORARY(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_COMPILER_GET_TEMPORARY))
+#define VIVI_IS_COMPILER_GET_TEMPORARY_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_COMPILER_GET_TEMPORARY))
+#define VIVI_COMPILER_GET_TEMPORARY(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_COMPILER_GET_TEMPORARY, ViviCompilerGetTemporary))
+#define VIVI_COMPILER_GET_TEMPORARY_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_COMPILER_GET_TEMPORARY, ViviCompilerGetTemporaryClass))
+#define VIVI_COMPILER_GET_TEMPORARY_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_COMPILER_GET_TEMPORARY, ViviCompilerGetTemporaryClass))
+
+struct _ViviCompilerGetTemporary
+{
+  ViviCodeValue		value;
+};
+
+struct _ViviCompilerGetTemporaryClass
+{
+  ViviCodeValueClass	value_class;
+};
+
+GType			vivi_compiler_get_temporary_get_type   	(void);
+
+ViviCodeValue *		vivi_compiler_get_temporary_new		(void);
+
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_compiler_scanner.c b/vivified/code/vivi_compiler_scanner.c
index b931818..a350529 100644
--- a/vivified/code/vivi_compiler_scanner.c
+++ b/vivified/code/vivi_compiler_scanner.c
@@ -233,3 +233,21 @@ vivi_compiler_scanner_peek_next_token (ViviCompilerScanner *scanner)
 
   return scanner->next_token;
 }
+
+guint
+vivi_compiler_scanner_cur_line (ViviCompilerScanner *scanner)
+{
+  g_return_val_if_fail (VIVI_IS_COMPILER_SCANNER (scanner), 0);
+
+  return yylineno;
+}
+
+void
+vivi_compiler_scanner_unexp_token (ViviCompilerScanner *scanner,
+    ViviCompilerScannerToken expected)
+{
+  g_printerr ("%i: Unexpected token %s, expected %s\n",
+      vivi_compiler_scanner_cur_line (scanner),
+      vivi_compiler_scanner_token_name (scanner->token),
+      vivi_compiler_scanner_token_name (expected));
+}
diff --git a/vivified/code/vivi_compiler_scanner.h b/vivified/code/vivi_compiler_scanner.h
index 26b8d1d..f782a3a 100644
--- a/vivified/code/vivi_compiler_scanner.h
+++ b/vivified/code/vivi_compiler_scanner.h
@@ -183,6 +183,11 @@ ViviCompilerScannerToken	vivi_compiler_scanner_peek_next_token	(ViviCompilerScan
 
 const char *			vivi_compiler_scanner_token_name	(ViviCompilerScannerToken token);
 
+guint				vivi_compiler_scanner_cur_line		(ViviCompilerScanner *scanner);
+
+void				vivi_compiler_scanner_unexp_token	(ViviCompilerScanner *	scanner,
+									 ViviCompilerScannerToken expected);
+
 
 G_END_DECLS
 #endif
commit d74042af00286a50c162fabb6af56f380d5843ad
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed Apr 2 01:20:06 2008 +0300

    Define missing tokens

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 2f54365..70b5832 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -49,65 +49,6 @@
 
 #include "vivi_code_text_printer.h"
 
-#if 0
-  { 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" },
-#endif
-
 enum {
   ERROR_TOKEN_LITERAL = TOKEN_LAST + 1,
   ERROR_TOKEN_PROPERTY_NAME,
@@ -479,9 +420,9 @@ parse_postfix_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 
   // FIXME: Don't allow new line here
 
-  if (check_token (scanner, TOKEN_PLUSPLUS)) {
+  if (check_token (scanner, TOKEN_INCREASE)) {
     operator = "+";
-  } else if (check_token (scanner, TOKEN_MINUSMINUS)) {
+  } else if (check_token (scanner, TOKEN_DESCREASE)) {
     operator = "-";
   } else {
     return TOKEN_NONE;
@@ -512,8 +453,8 @@ parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
     /*case TOKEN_DELETE:
     case TOKEN_VOID:
     case TOKEN_TYPEOF:
-    case TOKEN_PLUSPLUS:
-    case TOKEN_MINUSMINUS:
+    case TOKEN_INCREASE:
+    case TOKEN_DESCREASE:
     case TOKEN_PLUS:
     case TOKEN_MINUS:
     case TOKEN_BITWISE_NOT:*/
diff --git a/vivified/code/vivi_compiler_scanner.c b/vivified/code/vivi_compiler_scanner.c
index bcef86f..b931818 100644
--- a/vivified/code/vivi_compiler_scanner.c
+++ b/vivified/code/vivi_compiler_scanner.c
@@ -103,8 +103,8 @@ static const struct {
   // unary/postfix
   { TOKEN_LOGICAL_NOT, "!" },
   { TOKEN_BITWISE_NOT, "~" },
-  { TOKEN_PLUSPLUS, "++" },
-  { TOKEN_MINUSMINUS, "--" },
+  { TOKEN_INCREASE, "++" },
+  { TOKEN_DESCREASE, "--" },
 
   // conditional
   { TOKEN_QUESTION_MARK, "?" },
@@ -129,7 +129,7 @@ static const struct {
   { TOKEN_ASSIGN_BITWISE_OR, "|=" },
 
   // values
-  { TOKEN_NULL, "null" },
+  { TOKEN_NULL, "NULL" },
   { TOKEN_BOOLEAN, "BOOLEAN" },
   { TOKEN_NUMBER, "NUMBER" },
   { TOKEN_STRING, "STRING" },
@@ -138,28 +138,28 @@ static const struct {
   // keywords
   { TOKEN_BREAK, "break" },
   { TOKEN_CASE, "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, "" },
+  { 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, "void" },
+  { TOKEN_WITH, "with" },
 
   // reserved keywords
   { TOKEN_FUTURE, "RESERVED KEYWORD" },
diff --git a/vivified/code/vivi_compiler_scanner.h b/vivified/code/vivi_compiler_scanner.h
index 37207fd..26b8d1d 100644
--- a/vivified/code/vivi_compiler_scanner.h
+++ b/vivified/code/vivi_compiler_scanner.h
@@ -77,8 +77,8 @@ typedef enum {
   // unary/postfix
   TOKEN_LOGICAL_NOT,
   TOKEN_BITWISE_NOT,
-  TOKEN_PLUSPLUS,
-  TOKEN_MINUSMINUS,
+  TOKEN_INCREASE,
+  TOKEN_DESCREASE,
 
   // conditional
   TOKEN_QUESTION_MARK,
diff --git a/vivified/code/vivi_compiler_scanner_lex.lex b/vivified/code/vivi_compiler_scanner_lex.lex
index 9cbfa1e..875bdb3 100644
--- a/vivified/code/vivi_compiler_scanner_lex.lex
+++ b/vivified/code/vivi_compiler_scanner_lex.lex
@@ -48,8 +48,8 @@ identifier_part		[$_a-zA-Z0-9]
 
 "!"			{ return TOKEN_LOGICAL_NOT; }
 "~"			{ return TOKEN_BITWISE_NOT; }
-"++"			{ return TOKEN_PLUSPLUS; }
-"--"			{ return TOKEN_MINUSMINUS; }
+"++"			{ return TOKEN_INCREASE; }
+"--"			{ return TOKEN_DESCREASE; }
 
 "?"			{ return TOKEN_QUESTION_MARK; }
 ":"			{ return TOKEN_COLON; }
@@ -75,11 +75,63 @@ identifier_part		[$_a-zA-Z0-9]
 			  return TOKEN_BOOLEAN; }
 "false"			{ yylval.v_boolean = 0;
 			  return TOKEN_BOOLEAN; }
-"this"			{ return TOKEN_THIS; }
 
 "break"			{ return TOKEN_BREAK; }
+"case"			{ return TOKEN_CASE; }
+"catch"			{ return TOKEN_CATCH; }
+"continue"		{ return TOKEN_CONTINUE; }
+"default"		{ return TOKEN_DEFAULT; }
+"delete"		{ return TOKEN_DELETE; }
+"do"			{ return TOKEN_DO; }
+"else"			{ return TOKEN_ELSE; }
+"finally"		{ return TOKEN_FINALLY; }
+"for"			{ return TOKEN_FOR; }
+"function"		{ return TOKEN_FUNCTION; }
+"if"			{ return TOKEN_IF; }
+"in"			{ return TOKEN_IN; }
+"instanceof"		{ return TOKEN_INSTANCEOF; }
+"new"			{ return TOKEN_NEW; }
+"return"		{ return TOKEN_RETURN; }
+"switch"		{ return TOKEN_SWITCH; }
+"this"			{ return TOKEN_THIS; }
+"throw"			{ return TOKEN_THROW; }
+"try"			{ return TOKEN_TRY; }
+"typeof"		{ return TOKEN_TYPEOF; }
+"var"			{ return TOKEN_VAR; }
+"void"			{ return TOKEN_VOID; }
+"with"			{ return TOKEN_WITH; }
 
 "abstract"		{ return TOKEN_FUTURE; }
+"boolean"		{ return TOKEN_FUTURE; }
+"byte"			{ return TOKEN_FUTURE; }
+"char"			{ return TOKEN_FUTURE; }
+"class"			{ return TOKEN_FUTURE; }
+"const"			{ return TOKEN_FUTURE; }
+"debugger"		{ return TOKEN_FUTURE; }
+"double"		{ return TOKEN_FUTURE; }
+"enum"			{ return TOKEN_FUTURE; }
+"export"		{ return TOKEN_FUTURE; }
+"extends"		{ return TOKEN_FUTURE; }
+"final"			{ return TOKEN_FUTURE; }
+"float"			{ return TOKEN_FUTURE; }
+"goto"			{ return TOKEN_FUTURE; }
+"implements"		{ return TOKEN_FUTURE; }
+"import"		{ return TOKEN_FUTURE; }
+"int"			{ return TOKEN_FUTURE; }
+"interface"		{ return TOKEN_FUTURE; }
+"long"			{ return TOKEN_FUTURE; }
+"native"		{ return TOKEN_FUTURE; }
+"package"		{ return TOKEN_FUTURE; }
+"private"		{ return TOKEN_FUTURE; }
+"protected"		{ return TOKEN_FUTURE; }
+"public"		{ return TOKEN_FUTURE; }
+"short"			{ return TOKEN_FUTURE; }
+"static"		{ return TOKEN_FUTURE; }
+"super"			{ return TOKEN_FUTURE; }
+"synchronized"		{ return TOKEN_FUTURE; }
+"throws"		{ return TOKEN_FUTURE; }
+"transient"		{ return TOKEN_FUTURE; }
+"volatile"		{ return TOKEN_FUTURE; }
 
 {digit}+		{ yylval.v_number = atoi(yytext);
 			  return TOKEN_NUMBER; }
commit c1bc85ce6f7b9f529ef748d538992e562603e944
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed Apr 2 01:10:02 2008 +0300

    More improvements to the operator parsing

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 562e5fb..2f54365 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -502,20 +502,32 @@ parse_postfix_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 static int
 parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
+  int expected;
   ViviCodeValue *tmp;
 
   *value = NULL;
 
-  if (check_token (scanner, TOKEN_LOGICAL_NOT)) {
-    int expected = parse_unary_expression (scanner, value);
-    if (expected != TOKEN_NONE)
-      return FAIL (expected);
-    tmp = VIVI_CODE_VALUE (*value);
-    *value = vivi_code_unary_new (tmp, '!');
-    g_object_unref (tmp);
-    return TOKEN_NONE;
-  } else {
-    return parse_postfix_expression (scanner, value);
+  vivi_compiler_scanner_peek_next_token (scanner);
+  switch ((int)scanner->next_token) {
+    /*case TOKEN_DELETE:
+    case TOKEN_VOID:
+    case TOKEN_TYPEOF:
+    case TOKEN_PLUSPLUS:
+    case TOKEN_MINUSMINUS:
+    case TOKEN_PLUS:
+    case TOKEN_MINUS:
+    case TOKEN_BITWISE_NOT:*/
+    case TOKEN_LOGICAL_NOT:
+      vivi_compiler_scanner_get_next_token (scanner);
+      expected = parse_unary_expression (scanner, value);
+      if (expected != TOKEN_NONE)
+	return FAIL (expected);
+      tmp = VIVI_CODE_VALUE (*value);
+      *value = vivi_code_unary_new (tmp, '!');
+      g_object_unref (tmp);
+      return TOKEN_NONE;
+    default:
+      return parse_postfix_expression (scanner, value);
   }
 }
 
@@ -555,14 +567,59 @@ parse_operator_expression (ViviCompilerScanner *scanner,
 }
 
 static int
+parse_multiplicative_expression (ViviCompilerScanner *scanner,
+    ViviCodeValue **value)
+{
+  static const ViviCompilerScannerToken tokens[] = { TOKEN_MULTIPLY,
+    TOKEN_DIVIDE, TOKEN_REMAINDER, TOKEN_NONE };
+
+  return parse_operator_expression (scanner, value, tokens,
+      parse_unary_expression);
+}
+
+static int
+parse_additive_expression (ViviCompilerScanner *scanner,
+    ViviCodeValue **value)
+{
+  static const ViviCompilerScannerToken tokens[] = { TOKEN_PLUS, TOKEN_MINUS,
+    TOKEN_NONE };
+
+  return parse_operator_expression (scanner, value, tokens,
+      parse_multiplicative_expression);
+}
+
+static int
+parse_shift_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
+{
+  static const ViviCompilerScannerToken tokens[] = { TOKEN_SHIFT_LEFT,
+    TOKEN_SHIFT_RIGHT, TOKEN_SHIFT_RIGHT_UNSIGNED, TOKEN_NONE };
+
+  return parse_operator_expression (scanner, value, tokens,
+      parse_additive_expression);
+}
+
+static int
+parse_relational_expression (ViviCompilerScanner *scanner,
+    ViviCodeValue **value)
+{
+  static const ViviCompilerScannerToken tokens[] = { TOKEN_LESS_THAN,
+    TOKEN_GREATER_THAN, /*TOKEN_LESS_THAN_OR_EQUAL,
+    TOKEN_EQUAL_OR_GREATER_THAN, TOKEN_INSTANCEOF, TOKEN_IN,*/ TOKEN_NONE };
+
+  return parse_operator_expression (scanner, value, tokens,
+      parse_shift_expression);
+}
+
+static int
 parse_equality_expression (ViviCompilerScanner *scanner,
     ViviCodeValue **value)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_EQUAL,
-    TOKEN_NOT_EQUAL, TOKEN_STRICT_EQUAL, TOKEN_NOT_STRICT_EQUAL, TOKEN_NONE };
+    /*TOKEN_NOT_EQUAL,*/ TOKEN_STRICT_EQUAL, /*TOKEN_NOT_STRICT_EQUAL,*/
+    TOKEN_NONE };
 
   return parse_operator_expression (scanner, value, tokens,
-      parse_unary_expression);
+      parse_relational_expression);
 }
 
 static int
diff --git a/vivified/code/vivi_compiler_scanner.c b/vivified/code/vivi_compiler_scanner.c
index 18a7772..bcef86f 100644
--- a/vivified/code/vivi_compiler_scanner.c
+++ b/vivified/code/vivi_compiler_scanner.c
@@ -75,7 +75,7 @@ static const struct {
   { TOKEN_LESS_THAN, "<" },
   { TOKEN_GREATER_THAN, ">" },
   { TOKEN_LESS_THAN_OR_EQUAL, "<=" },
-  { TOKEN_EQUAL_OR_MORE_THAN, "=>" },
+  { TOKEN_EQUAL_OR_GREATER_THAN, "=>" },
 
   // equality
   { TOKEN_EQUAL, "=" },
diff --git a/vivified/code/vivi_compiler_scanner.h b/vivified/code/vivi_compiler_scanner.h
index 9a1dc03..37207fd 100644
--- a/vivified/code/vivi_compiler_scanner.h
+++ b/vivified/code/vivi_compiler_scanner.h
@@ -49,7 +49,7 @@ typedef enum {
   TOKEN_LESS_THAN,
   TOKEN_GREATER_THAN,
   TOKEN_LESS_THAN_OR_EQUAL,
-  TOKEN_EQUAL_OR_MORE_THAN,
+  TOKEN_EQUAL_OR_GREATER_THAN,
 
   // equality
   TOKEN_EQUAL,
diff --git a/vivified/code/vivi_compiler_scanner_lex.lex b/vivified/code/vivi_compiler_scanner_lex.lex
index 8429618..9cbfa1e 100644
--- a/vivified/code/vivi_compiler_scanner_lex.lex
+++ b/vivified/code/vivi_compiler_scanner_lex.lex
@@ -25,7 +25,7 @@ identifier_part		[$_a-zA-Z0-9]
 "<"			{ return TOKEN_LESS_THAN; }
 ">"			{ return TOKEN_GREATER_THAN; }
 "<="			{ return TOKEN_LESS_THAN_OR_EQUAL; }
-"=>"			{ return TOKEN_EQUAL_OR_MORE_THAN; }
+"=>"			{ return TOKEN_EQUAL_OR_GREATER_THAN; }
 
 "==",			{ return TOKEN_EQUAL; }
 "!=",			{ return TOKEN_NOT_EQUAL; }
commit 1ee9194bada58237a2f5b9cab8b8266858fdb8ec
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed Apr 2 00:56:32 2008 +0300

    Improvements to operator parsing

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 2b2d03f..562e5fb 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -521,10 +521,10 @@ parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 
 static int
 parse_operator_expression (ViviCompilerScanner *scanner,
-    ViviCodeValue **value, ViviCompilerScannerToken token, const char *name,
+    ViviCodeValue **value, const ViviCompilerScannerToken *tokens,
     ParseValueFunction next_parse_function)
 {
-  int expected;
+  int expected, i;
   ViviCodeValue *left;
   ViviCodeValue *right;
 
@@ -534,44 +534,78 @@ parse_operator_expression (ViviCompilerScanner *scanner,
   if (expected != TOKEN_NONE)
     return expected;
 
-  while (check_token (scanner, token)) {
-    expected = next_parse_function (scanner, &right);
-    if (expected != TOKEN_NONE) {
-      g_object_unref (*value);
-      *value = NULL;
-      return FAIL (expected);
-    }
+  for (i = 0; tokens[i] != TOKEN_NONE; i++) {
+    if (check_token (scanner, tokens[i])) {
+      expected = next_parse_function (scanner, &right);
+      if (expected != TOKEN_NONE) {
+	g_object_unref (*value);
+	*value = NULL;
+	return FAIL (expected);
+      }
 
-    left = VIVI_CODE_VALUE (*value);
-    *value = vivi_code_binary_new_name (left, VIVI_CODE_VALUE (right), name);
-    g_object_unref (left);
-    g_object_unref (right);
-  };
+      left = VIVI_CODE_VALUE (*value);
+      *value = vivi_code_binary_new_name (left, VIVI_CODE_VALUE (right),
+	  vivi_compiler_scanner_token_name (tokens[i]));
+      g_object_unref (left);
+      g_object_unref (right);
+    };
+  }
 
   return TOKEN_NONE;
 }
 
 static int
-parse_bitwise_and_expression (ViviCompilerScanner *scanner,
+parse_equality_expression (ViviCompilerScanner *scanner,
     ViviCodeValue **value)
 {
-  return parse_operator_expression (scanner, value, TOKEN_BITWISE_AND, "&",
+  static const ViviCompilerScannerToken tokens[] = { TOKEN_EQUAL,
+    TOKEN_NOT_EQUAL, TOKEN_STRICT_EQUAL, TOKEN_NOT_STRICT_EQUAL, TOKEN_NONE };
+
+  return parse_operator_expression (scanner, value, tokens,
       parse_unary_expression);
 }
 
 static int
-parse_bitwise_or_expression (ViviCompilerScanner *scanner,
+parse_bitwise_and_expression (ViviCompilerScanner *scanner,
     ViviCodeValue **value)
 {
-  return parse_operator_expression (scanner, value, TOKEN_BITWISE_OR, "|",
+  static const ViviCompilerScannerToken tokens[] = { TOKEN_BITWISE_AND,
+    TOKEN_NONE };
+
+  return parse_operator_expression (scanner, value, tokens,
+      parse_equality_expression);
+}
+
+static int
+parse_bitwise_xor_expression (ViviCompilerScanner *scanner,
+    ViviCodeValue **value)
+{
+  static const ViviCompilerScannerToken tokens[] = { TOKEN_BITWISE_XOR,
+    TOKEN_NONE };
+
+  return parse_operator_expression (scanner, value, tokens,
       parse_bitwise_and_expression);
 }
 
 static int
+parse_bitwise_or_expression (ViviCompilerScanner *scanner,
+    ViviCodeValue **value)
+{
+  static const ViviCompilerScannerToken tokens[] = { TOKEN_BITWISE_OR,
+    TOKEN_NONE };
+
+  return parse_operator_expression (scanner, value, tokens,
+      parse_bitwise_xor_expression);
+}
+
+static int
 parse_logical_and_expression (ViviCompilerScanner *scanner,
     ViviCodeValue **value)
 {
-  return parse_operator_expression (scanner, value, TOKEN_LOGICAL_AND, "&&",
+  static const ViviCompilerScannerToken tokens[] = { TOKEN_LOGICAL_AND,
+    TOKEN_NONE };
+
+  return parse_operator_expression (scanner, value, tokens,
       parse_bitwise_or_expression);
 }
 
@@ -579,7 +613,10 @@ static int
 parse_logical_or_expression (ViviCompilerScanner *scanner,
     ViviCodeValue **value)
 {
-  return parse_operator_expression (scanner, value, TOKEN_LOGICAL_OR, "||",
+  static const ViviCompilerScannerToken tokens[] = { TOKEN_LOGICAL_OR,
+    TOKEN_NONE };
+
+  return parse_operator_expression (scanner, value, tokens,
       parse_logical_and_expression);
 }
 
commit 7621685773df5871374534967e8a0048d55d6859
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed Apr 2 00:43:41 2008 +0300

    Fix bugs in the GScanner -> ViviCompilerScanner conversion

diff --git a/vivified/code/compiler.c b/vivified/code/compiler.c
index d0b78e4..08d85b6 100644
--- a/vivified/code/compiler.c
+++ b/vivified/code/compiler.c
@@ -47,6 +47,9 @@ main (int argc, char *argv[])
   }
 
   statement = vivi_compile_file (file, argv[1]);
+
+  fclose (file);
+
   if (statement == NULL) {
     g_printerr ("Compilation failed\n");
     return -1;
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index ad05557..2b2d03f 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -192,8 +192,8 @@ parse_string_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   *value = NULL;
 
-  if (!check_token (scanner, G_TOKEN_STRING))
-    return -G_TOKEN_STRING;
+  if (!check_token (scanner, TOKEN_STRING))
+    return -TOKEN_STRING;
 
   *value = vivi_code_constant_new_string (scanner->value.v_string);
   return TOKEN_NONE;
@@ -227,8 +227,8 @@ parse_identifier (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   *value = NULL;
 
-  if (!check_token (scanner, G_TOKEN_IDENTIFIER))
-    return -G_TOKEN_IDENTIFIER;
+  if (!check_token (scanner, TOKEN_IDENTIFIER))
+    return -TOKEN_IDENTIFIER;
 
   *value = vivi_code_get_new_name (scanner->value.v_identifier);
 
@@ -258,7 +258,7 @@ parse_property_name (ViviCompilerScanner *scanner, ViviCodeValue **value)
 }
 
 static int
-parse_operator_expression (ViviCompilerScanner *scanner, ViviCodeValue **value);
+parse_logical_or_expression (ViviCompilerScanner *scanner, ViviCodeValue **value);
 
 static int
 parse_object_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
@@ -267,12 +267,12 @@ parse_object_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
 
   *value = NULL;
 
-  if (!check_token (scanner, '{'))
-    return -'{';
+  if (!check_token (scanner, TOKEN_BRACE_LEFT))
+    return -TOKEN_BRACE_LEFT;
 
   *value = vivi_code_init_object_new ();
 
-  if (!check_token (scanner, '}')) {
+  if (!check_token (scanner, TOKEN_BRACE_RIGHT)) {
     do {
       ViviCodeValue *property, *initializer;
 
@@ -283,14 +283,14 @@ parse_object_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
 	return FAIL (expected);
       }
 
-      if (!check_token (scanner, ':')) {
+      if (!check_token (scanner, TOKEN_COLON)) {
 	g_object_unref (*value);
 	*value = NULL;
-	return ':';
+	return TOKEN_COLON;
       }
 
       // FIXME: assignment expression
-      expected = parse_operator_expression (scanner, &initializer);
+      expected = parse_logical_or_expression (scanner, &initializer);
       if (expected != TOKEN_NONE) {
 	g_object_unref (*value);
 	*value = NULL;
@@ -299,13 +299,13 @@ parse_object_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
 
       vivi_code_init_object_add_variable (VIVI_CODE_INIT_OBJECT (*value),
 	  property, initializer);
-    } while (check_token (scanner, ','));
+    } while (check_token (scanner, TOKEN_COMMA));
   }
 
-  if (!check_token (scanner, '}')) {
+  if (!check_token (scanner, TOKEN_BRACE_RIGHT)) {
     g_object_unref (*value);
     *value = NULL;
-    return '}';
+    return TOKEN_BRACE_RIGHT;
   }
 
   return TOKEN_NONE;
@@ -326,9 +326,9 @@ parse_variable_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **st
   if (expected != TOKEN_NONE)
     return expected;
 
-  if (check_token (scanner, '=')) {
+  if (check_token (scanner, TOKEN_EQUAL)) {
     // FIXME: assignment expression
-    expected = parse_operator_expression (scanner, &value);
+    expected = parse_logical_or_expression (scanner, &value);
     if (expected != TOKEN_NONE) {
       g_object_unref (identifier);
       return FAIL (expected);
@@ -364,15 +364,15 @@ parse_primary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
     return TOKEN_NONE;
   }
 
-  if (check_token (scanner, '(')) {
+  if (check_token (scanner, TOKEN_PARENTHESIS_LEFT)) {
     // FIXME: assignment expression
-    expected = parse_operator_expression (scanner, value);
+    expected = parse_logical_or_expression (scanner, value);
     if (expected != TOKEN_NONE)
       return FAIL (expected);
-    if (!check_token (scanner, ')')) {
+    if (!check_token (scanner, TOKEN_PARENTHESIS_RIGHT)) {
       g_object_unref (*value);
       *value = NULL;
-      return ')';
+      return TOKEN_PARENTHESIS_RIGHT;
     }
     return TOKEN_NONE;
   }
@@ -404,14 +404,14 @@ parse_member_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
   do {
     ViviCodeValue *tmp;
 
-    if (check_token (scanner, '[')) {
+    if (check_token (scanner, TOKEN_BRACKET_LEFT)) {
       // FIXME: expression
-      expected = parse_operator_expression (scanner, &member);
+      expected = parse_logical_or_expression (scanner, &member);
       if (expected != TOKEN_NONE)
 	return FAIL (expected);
-      if (!check_token (scanner, ']'))
-	return ']';
-    } else if (check_token (scanner, '.')) {
+      if (!check_token (scanner, TOKEN_BRACKET_RIGHT))
+	return TOKEN_BRACKET_RIGHT;
+    } else if (check_token (scanner, TOKEN_DOT)) {
       expected = parse_identifier (scanner, &member);
       if (expected != TOKEN_NONE)
 	return FAIL (expected);
@@ -506,7 +506,7 @@ parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 
   *value = NULL;
 
-  if (check_token (scanner, '!')) {
+  if (check_token (scanner, TOKEN_LOGICAL_NOT)) {
     int expected = parse_unary_expression (scanner, value);
     if (expected != TOKEN_NONE)
       return FAIL (expected);
@@ -520,7 +520,9 @@ parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 }
 
 static int
-parse_operator_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
+parse_operator_expression (ViviCompilerScanner *scanner,
+    ViviCodeValue **value, ViviCompilerScannerToken token, const char *name,
+    ParseValueFunction next_parse_function)
 {
   int expected;
   ViviCodeValue *left;
@@ -528,12 +530,12 @@ parse_operator_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 
   *value = NULL;
 
-  expected = parse_unary_expression (scanner, value);
+  expected = next_parse_function (scanner, value);
   if (expected != TOKEN_NONE)
     return expected;
 
-  while (check_token (scanner, '+')) {
-    expected = parse_unary_expression (scanner, &right);
+  while (check_token (scanner, token)) {
+    expected = next_parse_function (scanner, &right);
     if (expected != TOKEN_NONE) {
       g_object_unref (*value);
       *value = NULL;
@@ -541,7 +543,7 @@ parse_operator_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
     }
 
     left = VIVI_CODE_VALUE (*value);
-    *value = vivi_code_binary_new_name (left, VIVI_CODE_VALUE (right), "+");
+    *value = vivi_code_binary_new_name (left, VIVI_CODE_VALUE (right), name);
     g_object_unref (left);
     g_object_unref (right);
   };
@@ -550,6 +552,38 @@ parse_operator_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 }
 
 static int
+parse_bitwise_and_expression (ViviCompilerScanner *scanner,
+    ViviCodeValue **value)
+{
+  return parse_operator_expression (scanner, value, TOKEN_BITWISE_AND, "&",
+      parse_unary_expression);
+}
+
+static int
+parse_bitwise_or_expression (ViviCompilerScanner *scanner,
+    ViviCodeValue **value)
+{
+  return parse_operator_expression (scanner, value, TOKEN_BITWISE_OR, "|",
+      parse_bitwise_and_expression);
+}
+
+static int
+parse_logical_and_expression (ViviCompilerScanner *scanner,
+    ViviCodeValue **value)
+{
+  return parse_operator_expression (scanner, value, TOKEN_LOGICAL_AND, "&&",
+      parse_bitwise_or_expression);
+}
+
+static int
+parse_logical_or_expression (ViviCompilerScanner *scanner,
+    ViviCodeValue **value)
+{
+  return parse_operator_expression (scanner, value, TOKEN_LOGICAL_OR, "||",
+      parse_logical_and_expression);
+}
+
+static int
 parse_assignment_expression (ViviCompilerScanner *scanner, ViviCodeStatement **statement);
 
 static int
@@ -561,11 +595,11 @@ parse_conditional_expression (ViviCompilerScanner *scanner, ViviCodeStatement **
 
   *statement = NULL;
 
-  expected = parse_operator_expression (scanner, &value);
+  expected = parse_logical_or_expression (scanner, &value);
   if (expected != TOKEN_NONE)
     return expected;
 
-  if (!check_token (scanner, '?')) {
+  if (!check_token (scanner, TOKEN_QUESTION_MARK)) {
     *statement = vivi_code_value_statement_new (VIVI_CODE_VALUE (value));
     g_object_unref (value);
     return TOKEN_NONE;
@@ -577,10 +611,10 @@ parse_conditional_expression (ViviCompilerScanner *scanner, ViviCodeStatement **
     return FAIL (expected);
   }
 
-  if (!check_token (scanner, ':')) {
+  if (!check_token (scanner, TOKEN_COLON)) {
     g_object_unref (value);
     g_object_unref (if_statement);
-    return ':';
+    return TOKEN_COLON;
   }
 
   expected = parse_assignment_expression (scanner, &else_statement);
@@ -617,7 +651,7 @@ parse_expression (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
   *statement = NULL;
 
   return parse_statement_list (scanner, parse_assignment_expression, statement,
-      ',');
+      TOKEN_COMMA);
 }
 
 // statement
@@ -630,17 +664,17 @@ parse_expression_statement (ViviCompilerScanner *scanner, ViviCodeStatement **st
   *statement = NULL;
 
   vivi_compiler_scanner_peek_next_token (scanner);
-  if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
+  if (scanner->next_token == TOKEN_BRACE_LEFT || scanner->next_token == TOKEN_FUNCTION)
     return -ERROR_TOKEN_EXPRESSION_STATEMENT;
 
   expected = parse_expression (scanner, statement);
   if (expected != TOKEN_NONE)
     return expected;
 
-  if (!check_token (scanner, ';')) {
+  if (!check_token (scanner, TOKEN_SEMICOLON)) {
     g_object_unref (*statement);
     *statement = NULL;
-    return ';';
+    return TOKEN_SEMICOLON;
   }
 
   return TOKEN_NONE;
@@ -651,8 +685,8 @@ parse_empty_statement (ViviCompilerScanner *scanner, ViviCodeStatement **stateme
 {
   *statement = NULL;
 
-  if (!check_token (scanner, ';'))
-    return -';';
+  if (!check_token (scanner, TOKEN_SEMICOLON))
+    return -TOKEN_SEMICOLON;
 
   *statement = vivi_compiler_empty_statement_new ();
 
@@ -669,11 +703,11 @@ parse_block (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 
   *statement = NULL;
 
-  if (!check_token (scanner, '{'))
-    return -'{';
+  if (!check_token (scanner, TOKEN_BRACE_LEFT))
+    return -TOKEN_BRACE_LEFT;
 
   vivi_compiler_scanner_peek_next_token (scanner);
-  if (scanner->next_token != '}') {
+  if (scanner->next_token != TOKEN_BRACE_RIGHT) {
     expected =
       parse_statement_list (scanner, parse_statement, statement, TOKEN_NONE);
     if (expected != TOKEN_NONE)
@@ -682,10 +716,10 @@ parse_block (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
     *statement = vivi_code_block_new ();
   }
 
-  if (!check_token (scanner, '}')) {
+  if (!check_token (scanner, TOKEN_BRACE_RIGHT)) {
     g_object_unref (*statement);
     *statement = NULL;
-    return '}';
+    return TOKEN_BRACE_RIGHT;
   }
 
   return TOKEN_NONE;
@@ -702,14 +736,14 @@ parse_variable_statement (ViviCompilerScanner *scanner, ViviCodeStatement **stat
     return -TOKEN_VAR;
 
   expected =
-    parse_statement_list (scanner, parse_variable_declaration, statement, ',');
+    parse_statement_list (scanner, parse_variable_declaration, statement, TOKEN_COMMA);
   if (expected != TOKEN_NONE)
     return FAIL (expected);
 
-  if (!check_token (scanner, ';')) {
+  if (!check_token (scanner, TOKEN_SEMICOLON)) {
     g_object_unref (*statement);
     *statement = NULL;
-    return ';';
+    return TOKEN_SEMICOLON;
   }
 
   return TOKEN_NONE;
@@ -775,25 +809,25 @@ parse_function_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **st
   if (expected != TOKEN_NONE)
     return FAIL (expected);
 
-  if (!check_token (scanner, '(')) {
+  if (!check_token (scanner, TOKEN_PARENTHESIS_LEFT)) {
     g_object_unref (identifier);
-    return '(';
+    return TOKEN_PARENTHESIS_LEFT;
   }
 
-  expected = parse_value_list (scanner, parse_identifier, &arguments, ',');
+  expected = parse_value_list (scanner, parse_identifier, &arguments, TOKEN_COMMA);
   if (expected != TOKEN_NONE && expected >= 0)
     return expected;
 
-  if (!check_token (scanner, ')')) {
+  if (!check_token (scanner, TOKEN_PARENTHESIS_RIGHT)) {
     g_object_unref (identifier);
     free_value_list (arguments);
-    return ')';
+    return TOKEN_PARENTHESIS_RIGHT;
   }
 
-  if (!check_token (scanner, '{')) {
+  if (!check_token (scanner, TOKEN_BRACE_LEFT)) {
     g_object_unref (identifier);
     free_value_list (arguments);
-    return '{';
+    return TOKEN_BRACE_LEFT;
   }
 
   expected = parse_statement_list (scanner, parse_source_element, &body,
@@ -804,11 +838,11 @@ parse_function_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **st
     return expected;
   }
 
-  if (!check_token (scanner, '}')) {
+  if (!check_token (scanner, TOKEN_BRACE_RIGHT)) {
     g_object_unref (identifier);
     free_value_list (arguments);
     g_object_unref (body);
-    return '}';
+    return TOKEN_BRACE_RIGHT;
   }
 
   /*function = vivi_code_function_new (arguments, body);
@@ -851,7 +885,7 @@ parse_program (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
   if (expected != TOKEN_NONE)
     return FAIL (expected);
 
-  if (!check_token (scanner, G_TOKEN_EOF)) {
+  if (!check_token (scanner, TOKEN_EOF)) {
     *statement = NULL;
     return FAIL (parse_statement (scanner, statement));
   }
diff --git a/vivified/code/vivi_compiler_scanner.c b/vivified/code/vivi_compiler_scanner.c
index 81cd0a7..18a7772 100644
--- a/vivified/code/vivi_compiler_scanner.c
+++ b/vivified/code/vivi_compiler_scanner.c
@@ -49,17 +49,136 @@ vivi_compiler_scanner_init (ViviCompilerScanner *token)
 {
 }
 
-ViviCompilerScanner *
-vivi_compiler_scanner_new (FILE *file)
+static const struct {
+  ViviCompilerScannerToken	token;
+  const char *			name;
+} token_names[] = {
+  // special
+  { TOKEN_NONE, "NONE" },
+  { TOKEN_EOF, "EOF" },
+  { TOKEN_UNKNOWN, "UNKNOWN" },
+
+  // comparision
+  { TOKEN_BRACE_LEFT, "{", },
+  { TOKEN_BRACE_RIGHT, "}", },
+  { TOKEN_BRACKET_LEFT, "[", },
+  { TOKEN_BRACKET_RIGHT, "]", },
+  { TOKEN_PARENTHESIS_LEFT, "(", },
+  { TOKEN_PARENTHESIS_RIGHT, ")", },
+
+  // punctuation
+  { TOKEN_DOT, ".", },
+  { TOKEN_SEMICOLON, ";" },
+  { TOKEN_COMMA, "," },
+
+  // comparision
+  { TOKEN_LESS_THAN, "<" },
+  { TOKEN_GREATER_THAN, ">" },
+  { TOKEN_LESS_THAN_OR_EQUAL, "<=" },
+  { TOKEN_EQUAL_OR_MORE_THAN, "=>" },
+
+  // equality
+  { TOKEN_EQUAL, "=" },
+  { TOKEN_NOT_EQUAL, "!=" },
+  { TOKEN_STRICT_EQUAL, "===" },
+  { TOKEN_NOT_STRICT_EQUAL, "!==" },
+
+  // operator
+  { TOKEN_PLUS, "+" },
+  { TOKEN_MINUS, "-" },
+  { TOKEN_MULTIPLY, "*" },
+  { TOKEN_DIVIDE, "/" },
+  { TOKEN_REMAINDER, "%" },
+
+  // shift
+  { TOKEN_SHIFT_LEFT, "<<" },
+  { TOKEN_SHIFT_RIGHT, ">>" },
+  { TOKEN_SHIFT_RIGHT_UNSIGNED, ">>>" },
+
+  // bitwise
+  { TOKEN_BITWISE_AND, "&" },
+  { TOKEN_BITWISE_OR, "|" },
+  { TOKEN_BITWISE_XOR, "^" },
+  
+  // unary/postfix
+  { TOKEN_LOGICAL_NOT, "!" },
+  { TOKEN_BITWISE_NOT, "~" },
+  { TOKEN_PLUSPLUS, "++" },
+  { TOKEN_MINUSMINUS, "--" },
+
+  // conditional
+  { TOKEN_QUESTION_MARK, "?" },
+  { TOKEN_COLON, ":" },
+
+  // logical
+  { TOKEN_LOGICAL_AND, "&&" },
+  { TOKEN_LOGICAL_OR, "||" },
+
+  // assign
+  { TOKEN_ASSIGN, "=" },
+  { TOKEN_ASSIGN_MULTIPLY, "*=" },
+  { TOKEN_ASSIGN_DIVIDE, "/=" },
+  { TOKEN_ASSIGN_REMAINDER, "%=" },
+  { TOKEN_ASSIGN_ADD, "+=" },
+  { TOKEN_ASSIGN_MINUS, "-=" },
+  { TOKEN_ASSIGN_SHIFT_LEFT, "<<=" },
+  { TOKEN_ASSIGN_SHIFT_RIGHT, ">>=" },
+  { TOKEN_ASSIGN_SHIFT_RIGHT_ZERO, ">>>=" },
+  { TOKEN_ASSIGN_BITWISE_AND, "&=" },
+  { TOKEN_ASSIGN_BITWISE_XOR, "^=" },
+  { TOKEN_ASSIGN_BITWISE_OR, "|=" },
+
+  // values
+  { TOKEN_NULL, "null" },
+  { TOKEN_BOOLEAN, "BOOLEAN" },
+  { TOKEN_NUMBER, "NUMBER" },
+  { TOKEN_STRING, "STRING" },
+  { TOKEN_IDENTIFIER, "IDENTIFIER" },
+
+  // keywords
+  { TOKEN_BREAK, "break" },
+  { TOKEN_CASE, "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, "RESERVED KEYWORD" },
+
+  { TOKEN_LAST, NULL }
+};
+
+const char *vivi_compiler_scanner_token_name (ViviCompilerScannerToken token)
 {
-  ViviCompilerScanner *scanner;
+  int i;
 
-  g_return_val_if_fail (file != NULL, NULL);
+  for (i = 0; token_names[i].token != TOKEN_LAST; i++) {
+    if (token_names[i].token == token)
+      return token_names[i].name;
+  }
 
-  scanner = g_object_new (VIVI_TYPE_COMPILER_SCANNER, NULL);
-  scanner->file = file;
+  g_assert_not_reached ();
 
-  return scanner;
+  return "INVALID TOKEN";
 }
 
 static void
@@ -79,6 +198,24 @@ vivi_compiler_scanner_advance (ViviCompilerScanner *scanner)
   }
 }
 
+ViviCompilerScanner *
+vivi_compiler_scanner_new (FILE *file)
+{
+  ViviCompilerScanner *scanner;
+
+  g_return_val_if_fail (file != NULL, NULL);
+
+  scanner = g_object_new (VIVI_TYPE_COMPILER_SCANNER, NULL);
+  scanner->file = file;
+
+  yyrestart (file);
+  yyout = stdout;
+
+  vivi_compiler_scanner_advance (scanner);
+
+  return scanner;
+}
+
 ViviCompilerScannerToken
 vivi_compiler_scanner_get_next_token (ViviCompilerScanner *scanner)
 {
diff --git a/vivified/code/vivi_compiler_scanner.h b/vivified/code/vivi_compiler_scanner.h
index 16618cb..9a1dc03 100644
--- a/vivified/code/vivi_compiler_scanner.h
+++ b/vivified/code/vivi_compiler_scanner.h
@@ -25,7 +25,9 @@
 
 G_BEGIN_DECLS
 
+
 typedef enum {
+  // special
   TOKEN_NONE = 0,
   TOKEN_EOF,
   TOKEN_UNKNOWN,
@@ -33,8 +35,8 @@ typedef enum {
   // comparision
   TOKEN_BRACE_LEFT,
   TOKEN_BRACE_RIGHT,
-  TOKEN_BRACKET_RIGHT,
   TOKEN_BRACKET_LEFT,
+  TOKEN_BRACKET_RIGHT,
   TOKEN_PARENTHESIS_LEFT,
   TOKEN_PARENTHESIS_RIGHT,
 
@@ -104,6 +106,7 @@ typedef enum {
   TOKEN_NULL,
   TOKEN_BOOLEAN,
   TOKEN_NUMBER,
+  TOKEN_STRING,
   TOKEN_IDENTIFIER,
 
   // keywords
@@ -178,5 +181,8 @@ ViviCompilerScanner *		vivi_compiler_scanner_new		(FILE *		file);
 ViviCompilerScannerToken	vivi_compiler_scanner_get_next_token	(ViviCompilerScanner *	scanner);
 ViviCompilerScannerToken	vivi_compiler_scanner_peek_next_token	(ViviCompilerScanner *	scanner);
 
+const char *			vivi_compiler_scanner_token_name	(ViviCompilerScannerToken token);
+
+
 G_END_DECLS
 #endif
diff --git a/vivified/code/vivi_compiler_scanner_lex.lex b/vivified/code/vivi_compiler_scanner_lex.lex
index b35fe96..8429618 100644
--- a/vivified/code/vivi_compiler_scanner_lex.lex
+++ b/vivified/code/vivi_compiler_scanner_lex.lex
@@ -9,6 +9,8 @@ identifier_part		[$_a-zA-Z0-9]
 %%
 
 [ \t\n\r]		/* skip whitespace */
+<<EOF>>			{ return TOKEN_EOF; }
+
 "{"			{ return TOKEN_BRACE_LEFT; }
 "}"			{ return TOKEN_BRACE_RIGHT; }
 "["			{ return TOKEN_BRACKET_RIGHT; }
commit ae92e76a913892ff0687c018dce37f1679327c16
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed Apr 2 00:12:36 2008 +0300

    Convert from GScanner to ViviCompilerScanner

diff --git a/vivified/code/compiler.c b/vivified/code/compiler.c
index 1e5cd3a..d0b78e4 100644
--- a/vivified/code/compiler.c
+++ b/vivified/code/compiler.c
@@ -30,8 +30,7 @@ int
 main (int argc, char *argv[])
 {
   SwfdecPlayer *player;
-  char *text;
-  gsize text_len;
+  FILE *file;
   ViviCodeStatement *statement;
 
   player = swfdec_player_new (NULL);
@@ -41,12 +40,13 @@ main (int argc, char *argv[])
     return 1;
   }
 
-  if (!g_file_get_contents (argv[1], &text, &text_len, NULL)) {
+  file = fopen (argv[1], "r");
+  if (file == NULL) {
     g_printerr ("Couldn't open file %s", argv[1]);
     return -1;
   }
 
-  statement = vivi_compile_text (text, text_len, argv[1]);
+  statement = vivi_compile_file (file, argv[1]);
   if (statement == NULL) {
     g_printerr ("Compilation failed\n");
     return -1;
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 760c14e..ad05557 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -25,6 +25,8 @@
 
 #include "vivi_compiler.h"
 
+#include "vivi_compiler_scanner.h"
+
 #include "vivi_code_assignment.h"
 #include "vivi_code_binary.h"
 #include "vivi_code_block.h"
@@ -47,57 +49,7 @@
 
 #include "vivi_code_text_printer.h"
 
-enum {
-  // 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,
-  // errors
-  ERROR_TOKEN_BOOLEAN,
-  ERROR_TOKEN_LITERAL,
-  ERROR_TOKEN_PROPERTY_NAME,
-  ERROR_TOKEN_PRIMARY_EXPRESSION,
-  ERROR_TOKEN_EXPRESSION_STATEMENT,
-  ERROR_TOKEN_STATEMENT
-};
-
-typedef struct {
-  guint		token;
-  const char *	symbol;
-} TokenDescription;
-
-static const TokenDescription custom_tokens[] = {
-  // keywords
+#if 0
   { TOKEN_BREAK, "break" },
   { TOKEN_CASE, "case" },
   { TOKEN_CATCH, "catch" },
@@ -154,48 +106,35 @@ static const TokenDescription custom_tokens[] = {
   { 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 }
-};
+#endif
 
-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 }
+enum {
+  ERROR_TOKEN_LITERAL = TOKEN_LAST + 1,
+  ERROR_TOKEN_PROPERTY_NAME,
+  ERROR_TOKEN_PRIMARY_EXPRESSION,
+  ERROR_TOKEN_EXPRESSION_STATEMENT,
+  ERROR_TOKEN_STATEMENT
 };
 
 #define FAIL(x) ((x) < 0 ? -x : x)
 
-typedef int (*ParseStatementFunction) (GScanner *scanner, ViviCodeStatement **statement);
-typedef int (*ParseValueFunction) (GScanner *scanner, ViviCodeValue **value);
+typedef int (*ParseStatementFunction) (ViviCompilerScanner *scanner, ViviCodeStatement **statement);
+typedef int (*ParseValueFunction) (ViviCompilerScanner *scanner, ViviCodeValue **value);
 
 static int
-parse_statement_list (GScanner *scanner, ParseStatementFunction function,
-    ViviCodeStatement **statement, guint separator);
+parse_statement_list (ViviCompilerScanner *scanner, ParseStatementFunction function, ViviCodeStatement **statement, guint separator);
 static int
-parse_value_list (GScanner *scanner, ParseValueFunction function,
-    ViviCodeValue ***list, guint separator);
+parse_value_list (ViviCompilerScanner *scanner, ParseValueFunction function, ViviCodeValue ***list, guint separator);
 
 // helpers
 
 static gboolean
-check_token (GScanner *scanner, guint token)
+check_token (ViviCompilerScanner *scanner, guint token)
 {
-  g_scanner_peek_next_token (scanner);
+  vivi_compiler_scanner_peek_next_token (scanner);
   if (scanner->next_token != token)
     return FALSE;
-  g_scanner_get_next_token (scanner);
+  vivi_compiler_scanner_get_next_token (scanner);
   return TRUE;
 }
 
@@ -213,7 +152,7 @@ free_value_list (ViviCodeValue **list)
 // values
 
 static int
-parse_null_literal (GScanner *scanner, ViviCodeValue **value)
+parse_null_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   *value = NULL;
 
@@ -221,39 +160,35 @@ parse_null_literal (GScanner *scanner, ViviCodeValue **value)
     return -TOKEN_NULL;
 
   *value = vivi_code_constant_new_null ();
-  return G_TOKEN_NONE;
+  return TOKEN_NONE;
 }
 
 static int
-parse_boolean_literal (GScanner *scanner, ViviCodeValue **value)
+parse_boolean_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   *value = NULL;
 
-  if (check_token (scanner, TOKEN_TRUE)) {
-    *value = vivi_code_constant_new_boolean (TRUE);
-    return G_TOKEN_NONE;
-  } else if (check_token (scanner, TOKEN_FALSE)) {
-    *value = vivi_code_constant_new_boolean (FALSE);
-    return G_TOKEN_NONE;
-  } else {
-    return -ERROR_TOKEN_BOOLEAN;
-  }
+  if (!check_token (scanner, TOKEN_BOOLEAN))
+    return -TOKEN_BOOLEAN;
+
+  *value = vivi_code_constant_new_boolean (scanner->value.v_boolean);
+  return TOKEN_NONE;
 }
 
 static int
-parse_numeric_literal (GScanner *scanner, ViviCodeValue **value)
+parse_numeric_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   *value = NULL;
 
-  if (!check_token (scanner, G_TOKEN_FLOAT))
-    return -G_TOKEN_FLOAT;
+  if (!check_token (scanner, TOKEN_NUMBER))
+    return -TOKEN_NUMBER;
 
-  *value = vivi_code_constant_new_number (scanner->value.v_float);
-  return G_TOKEN_NONE;
+  *value = vivi_code_constant_new_number (scanner->value.v_number);
+  return TOKEN_NONE;
 }
 
 static int
-parse_string_literal (GScanner *scanner, ViviCodeValue **value)
+parse_string_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   *value = NULL;
 
@@ -261,11 +196,11 @@ parse_string_literal (GScanner *scanner, ViviCodeValue **value)
     return -G_TOKEN_STRING;
 
   *value = vivi_code_constant_new_string (scanner->value.v_string);
-  return G_TOKEN_NONE;
+  return TOKEN_NONE;
 }
 
 static int
-parse_literal (GScanner *scanner, ViviCodeValue **value)
+parse_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   int i, expected;
   ParseValueFunction functions[] = {
@@ -288,7 +223,7 @@ parse_literal (GScanner *scanner, ViviCodeValue **value)
 }
 
 static int
-parse_identifier (GScanner *scanner, ViviCodeValue **value)
+parse_identifier (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   *value = NULL;
 
@@ -297,11 +232,11 @@ parse_identifier (GScanner *scanner, ViviCodeValue **value)
 
   *value = vivi_code_get_new_name (scanner->value.v_identifier);
 
-  return G_TOKEN_NONE;
+  return TOKEN_NONE;
 }
 
 static int
-parse_property_name (GScanner *scanner, ViviCodeValue **value)
+parse_property_name (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   int i, expected;
   ParseValueFunction functions[] = {
@@ -323,10 +258,10 @@ parse_property_name (GScanner *scanner, ViviCodeValue **value)
 }
 
 static int
-parse_operator_expression (GScanner *scanner, ViviCodeValue **value);
+parse_operator_expression (ViviCompilerScanner *scanner, ViviCodeValue **value);
 
 static int
-parse_object_literal (GScanner *scanner, ViviCodeValue **value)
+parse_object_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   int expected;
 
@@ -342,7 +277,7 @@ parse_object_literal (GScanner *scanner, ViviCodeValue **value)
       ViviCodeValue *property, *initializer;
 
       expected = parse_property_name (scanner, &property);
-      if (expected != G_TOKEN_NONE) {
+      if (expected != TOKEN_NONE) {
 	g_object_unref (*value);
 	*value = NULL;
 	return FAIL (expected);
@@ -356,7 +291,7 @@ parse_object_literal (GScanner *scanner, ViviCodeValue **value)
 
       // FIXME: assignment expression
       expected = parse_operator_expression (scanner, &initializer);
-      if (expected != G_TOKEN_NONE) {
+      if (expected != TOKEN_NONE) {
 	g_object_unref (*value);
 	*value = NULL;
 	return FAIL (expected);
@@ -373,13 +308,13 @@ parse_object_literal (GScanner *scanner, ViviCodeValue **value)
     return '}';
   }
 
-  return G_TOKEN_NONE;
+  return TOKEN_NONE;
 }
 
 // misc
 
 static int
-parse_variable_declaration (GScanner *scanner, ViviCodeStatement **statement)
+parse_variable_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 {
   int expected;
   ViviCodeValue *identifier;
@@ -388,13 +323,13 @@ parse_variable_declaration (GScanner *scanner, ViviCodeStatement **statement)
   *statement = NULL;
 
   expected = parse_identifier (scanner, &identifier);
-  if (expected != G_TOKEN_NONE)
+  if (expected != TOKEN_NONE)
     return expected;
 
   if (check_token (scanner, '=')) {
     // FIXME: assignment expression
     expected = parse_operator_expression (scanner, &value);
-    if (expected != G_TOKEN_NONE) {
+    if (expected != TOKEN_NONE) {
       g_object_unref (identifier);
       return FAIL (expected);
     }
@@ -405,13 +340,13 @@ 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 G_TOKEN_NONE;
+  return TOKEN_NONE;
 }
 
 // expression
 
 static int
-parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
+parse_primary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   int i, expected;
   ParseValueFunction functions[] = {
@@ -426,20 +361,20 @@ parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
 
   if (check_token (scanner, TOKEN_THIS)) {
     *value = vivi_code_get_new_name ("this");
-    return G_TOKEN_NONE;
+    return TOKEN_NONE;
   }
 
   if (check_token (scanner, '(')) {
     // FIXME: assignment expression
     expected = parse_operator_expression (scanner, value);
-    if (expected != G_TOKEN_NONE)
+    if (expected != TOKEN_NONE)
       return FAIL (expected);
     if (!check_token (scanner, ')')) {
       g_object_unref (*value);
       *value = NULL;
       return ')';
     }
-    return G_TOKEN_NONE;
+    return TOKEN_NONE;
   }
 
   for (i = 0; functions[i] != NULL; i++) {
@@ -452,7 +387,7 @@ parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
 }
 
 static int
-parse_member_expression (GScanner *scanner, ViviCodeValue **value)
+parse_member_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   int expected;
   ViviCodeValue *member;
@@ -463,7 +398,7 @@ parse_member_expression (GScanner *scanner, ViviCodeValue **value)
   //if (expected == STATUS_CANCEL)
   //  expected = parse_function_expression (scanner, value);
 
-  if (expected != G_TOKEN_NONE)
+  if (expected != TOKEN_NONE)
     return expected;
 
   do {
@@ -472,16 +407,16 @@ parse_member_expression (GScanner *scanner, ViviCodeValue **value)
     if (check_token (scanner, '[')) {
       // FIXME: expression
       expected = parse_operator_expression (scanner, &member);
-      if (expected != G_TOKEN_NONE)
+      if (expected != TOKEN_NONE)
 	return FAIL (expected);
       if (!check_token (scanner, ']'))
 	return ']';
     } else if (check_token (scanner, '.')) {
       expected = parse_identifier (scanner, &member);
-      if (expected != G_TOKEN_NONE)
+      if (expected != TOKEN_NONE)
 	return FAIL (expected);
     } else {
-      return G_TOKEN_NONE;
+      return TOKEN_NONE;
     }
 
     tmp = *value;
@@ -494,7 +429,7 @@ parse_member_expression (GScanner *scanner, ViviCodeValue **value)
 }
 
 static int
-parse_new_expression (GScanner *scanner, ViviCodeValue **value)
+parse_new_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   int expected;
 
@@ -502,7 +437,7 @@ parse_new_expression (GScanner *scanner, ViviCodeValue **value)
 
   if (check_token (scanner, TOKEN_NEW)) {
     expected = parse_new_expression (scanner, value);
-    if (expected != G_TOKEN_NONE)
+    if (expected != TOKEN_NONE)
       return FAIL (expected);
     if (!VIVI_IS_CODE_FUNCTION_CALL (*value)) {
       ViviCodeValue *tmp = VIVI_CODE_VALUE (*value);
@@ -511,14 +446,14 @@ parse_new_expression (GScanner *scanner, ViviCodeValue **value)
     }
     vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*value),
 	TRUE);
-    return G_TOKEN_NONE;
+    return TOKEN_NONE;
   } else {
     return parse_member_expression (scanner, value);
   }
 }
 
 static int
-parse_left_hand_side_expression (GScanner *scanner, ViviCodeValue **value)
+parse_left_hand_side_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   int expected;
 
@@ -532,14 +467,14 @@ parse_left_hand_side_expression (GScanner *scanner, ViviCodeValue **value)
 }
 
 static int
-parse_postfix_expression (GScanner *scanner, ViviCodeValue **value)
+parse_postfix_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   int expected;
   ViviCodeValue *tmp, *one;
   const char *operator;
 
   expected = parse_left_hand_side_expression (scanner, value);
-  if (expected != G_TOKEN_NONE)
+  if (expected != TOKEN_NONE)
     return expected;
 
   // FIXME: Don't allow new line here
@@ -549,7 +484,7 @@ parse_postfix_expression (GScanner *scanner, ViviCodeValue **value)
   } else if (check_token (scanner, TOKEN_MINUSMINUS)) {
     operator = "-";
   } else {
-    return G_TOKEN_NONE;
+    return TOKEN_NONE;
   }
 
   one = vivi_code_constant_new_number (1);
@@ -561,11 +496,11 @@ parse_postfix_expression (GScanner *scanner, ViviCodeValue **value)
 
   g_object_unref (one);
 
-  return G_TOKEN_NONE;
+  return TOKEN_NONE;
 }
 
 static int
-parse_unary_expression (GScanner *scanner, ViviCodeValue **value)
+parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   ViviCodeValue *tmp;
 
@@ -573,19 +508,19 @@ parse_unary_expression (GScanner *scanner, ViviCodeValue **value)
 
   if (check_token (scanner, '!')) {
     int expected = parse_unary_expression (scanner, value);
-    if (expected != G_TOKEN_NONE)
+    if (expected != TOKEN_NONE)
       return FAIL (expected);
     tmp = VIVI_CODE_VALUE (*value);
     *value = vivi_code_unary_new (tmp, '!');
     g_object_unref (tmp);
-    return G_TOKEN_NONE;
+    return TOKEN_NONE;
   } else {
     return parse_postfix_expression (scanner, value);
   }
 }
 
 static int
-parse_operator_expression (GScanner *scanner, ViviCodeValue **value)
+parse_operator_expression (ViviCompilerScanner *scanner, ViviCodeValue **value)
 {
   int expected;
   ViviCodeValue *left;
@@ -594,12 +529,12 @@ parse_operator_expression (GScanner *scanner, ViviCodeValue **value)
   *value = NULL;
 
   expected = parse_unary_expression (scanner, value);
-  if (expected != G_TOKEN_NONE)
+  if (expected != TOKEN_NONE)
     return expected;
 
   while (check_token (scanner, '+')) {
     expected = parse_unary_expression (scanner, &right);
-    if (expected != G_TOKEN_NONE) {
+    if (expected != TOKEN_NONE) {
       g_object_unref (*value);
       *value = NULL;
       return FAIL (expected);
@@ -611,14 +546,14 @@ parse_operator_expression (GScanner *scanner, ViviCodeValue **value)
     g_object_unref (right);
   };
 
-  return G_TOKEN_NONE;
+  return TOKEN_NONE;
 }
 
 static int
-parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement);
+parse_assignment_expression (ViviCompilerScanner *scanner, ViviCodeStatement **statement);
 
 static int
-parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
+parse_conditional_expression (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 {
   int expected;
   ViviCodeValue *value;
@@ -627,17 +562,17 @@ parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
   *statement = NULL;
 
   expected = parse_operator_expression (scanner, &value);
-  if (expected != G_TOKEN_NONE)
+  if (expected != TOKEN_NONE)
     return expected;
 
   if (!check_token (scanner, '?')) {
     *statement = vivi_code_value_statement_new (VIVI_CODE_VALUE (value));
     g_object_unref (value);
-    return G_TOKEN_NONE;
+    return TOKEN_NONE;
   }
 
   expected = parse_assignment_expression (scanner, &if_statement);
-  if (expected != G_TOKEN_NONE) {
+  if (expected != TOKEN_NONE) {
     g_object_unref (value);
     return FAIL (expected);
   }
@@ -649,7 +584,7 @@ parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
   }
 
   expected = parse_assignment_expression (scanner, &else_statement);
-  if (expected != G_TOKEN_NONE) {
+  if (expected != TOKEN_NONE) {
     g_object_unref (value);
     g_object_unref (if_statement);
     return FAIL (expected);
@@ -663,11 +598,11 @@ parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
   g_object_unref (if_statement);
   g_object_unref (else_statement);
 
-  return G_TOKEN_NONE;
+  return TOKEN_NONE;
 }
 
 static int
-parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement)
+parse_assignment_expression (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 {
   *statement = NULL;
 
@@ -677,7 +612,7 @@ parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement)
 }
 
 static int
-parse_expression (GScanner *scanner, ViviCodeStatement **statement)
+parse_expression (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 {
   *statement = NULL;
 
@@ -688,18 +623,18 @@ parse_expression (GScanner *scanner, ViviCodeStatement **statement)
 // statement
 
 static int
-parse_expression_statement (GScanner *scanner, ViviCodeStatement **statement)
+parse_expression_statement (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 {
   int expected;
 
   *statement = NULL;
 
-  g_scanner_peek_next_token (scanner);
+  vivi_compiler_scanner_peek_next_token (scanner);
   if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
     return -ERROR_TOKEN_EXPRESSION_STATEMENT;
 
   expected = parse_expression (scanner, statement);
-  if (expected != G_TOKEN_NONE)
+  if (expected != TOKEN_NONE)
     return expected;
 
   if (!check_token (scanner, ';')) {
@@ -708,11 +643,11 @@ parse_expression_statement (GScanner *scanner, ViviCodeStatement **statement)
     return ';';
   }
 
-  return G_TOKEN_NONE;
+  return TOKEN_NONE;
 }
 
 static int
-parse_empty_statement (GScanner *scanner, ViviCodeStatement **statement)
+parse_empty_statement (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 {
   *statement = NULL;
 
@@ -721,14 +656,14 @@ parse_empty_statement (GScanner *scanner, ViviCodeStatement **statement)
 
   *statement = vivi_compiler_empty_statement_new ();
 
-  return G_TOKEN_NONE;
+  return TOKEN_NONE;
 }
 
 static int
-parse_statement (GScanner *scanner, ViviCodeStatement **statement);
+parse_statement (ViviCompilerScanner *scanner, ViviCodeStatement **statement);
 
 static int
-parse_block (GScanner *scanner, ViviCodeStatement **statement)
+parse_block (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 {
   int expected;
 
@@ -737,11 +672,11 @@ parse_block (GScanner *scanner, ViviCodeStatement **statement)
   if (!check_token (scanner, '{'))
     return -'{';
 
-  g_scanner_peek_next_token (scanner);
+  vivi_compiler_scanner_peek_next_token (scanner);
   if (scanner->next_token != '}') {
     expected =
-      parse_statement_list (scanner, parse_statement, statement, G_TOKEN_NONE);
-    if (expected != G_TOKEN_NONE)
+      parse_statement_list (scanner, parse_statement, statement, TOKEN_NONE);
+    if (expected != TOKEN_NONE)
       return FAIL (expected);
   } else {
     *statement = vivi_code_block_new ();
@@ -753,11 +688,11 @@ parse_block (GScanner *scanner, ViviCodeStatement **statement)
     return '}';
   }
 
-  return G_TOKEN_NONE;
+  return TOKEN_NONE;
 }
 
 static int
-parse_variable_statement (GScanner *scanner, ViviCodeStatement **statement)
+parse_variable_statement (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 {
   int expected;
 
@@ -768,7 +703,7 @@ parse_variable_statement (GScanner *scanner, ViviCodeStatement **statement)
 
   expected =
     parse_statement_list (scanner, parse_variable_declaration, statement, ',');
-  if (expected != G_TOKEN_NONE)
+  if (expected != TOKEN_NONE)
     return FAIL (expected);
 
   if (!check_token (scanner, ';')) {
@@ -777,11 +712,11 @@ parse_variable_statement (GScanner *scanner, ViviCodeStatement **statement)
     return ';';
   }
 
-  return G_TOKEN_NONE;
+  return TOKEN_NONE;
 }
 
 static int
-parse_statement (GScanner *scanner, ViviCodeStatement **statement)
+parse_statement (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 {
   int i, expected;
   ParseStatementFunction functions[] = {
@@ -816,10 +751,10 @@ parse_statement (GScanner *scanner, ViviCodeStatement **statement)
 // function
 
 static int
-parse_source_element (GScanner *scanner, ViviCodeStatement **statement);
+parse_source_element (ViviCompilerScanner *scanner, ViviCodeStatement **statement);
 
 static int
-parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
+parse_function_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 {
   //ViviCodeStatement *function;
   ViviCodeValue *identifier;
@@ -837,7 +772,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
     return -TOKEN_FUNCTION;
 
   expected = parse_identifier (scanner, &identifier);
-  if (expected != G_TOKEN_NONE)
+  if (expected != TOKEN_NONE)
     return FAIL (expected);
 
   if (!check_token (scanner, '(')) {
@@ -846,7 +781,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
   }
 
   expected = parse_value_list (scanner, parse_identifier, &arguments, ',');
-  if (expected != G_TOKEN_NONE && expected >= 0)
+  if (expected != TOKEN_NONE && expected >= 0)
     return expected;
 
   if (!check_token (scanner, ')')) {
@@ -862,8 +797,8 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
   }
 
   expected = parse_statement_list (scanner, parse_source_element, &body,
-      G_TOKEN_NONE);
-  if (expected != G_TOKEN_NONE && expected >= 0) {
+      TOKEN_NONE);
+  if (expected != TOKEN_NONE && expected >= 0) {
     g_object_unref (identifier);
     free_value_list (arguments);
     return expected;
@@ -885,13 +820,13 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
   free_value_list (arguments);
   g_object_unref (body);
 
-  return G_TOKEN_NONE;
+  return TOKEN_NONE;
 }
 
 // top
 
 static int
-parse_source_element (GScanner *scanner, ViviCodeStatement **statement)
+parse_source_element (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 {
   int expected;
 
@@ -905,15 +840,15 @@ parse_source_element (GScanner *scanner, ViviCodeStatement **statement)
 }
 
 static int
-parse_program (GScanner *scanner, ViviCodeStatement **statement)
+parse_program (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 {
   int expected;
 
   *statement = NULL;
 
   expected = parse_statement_list (scanner, parse_source_element, statement,
-      G_TOKEN_NONE);
-  if (expected != G_TOKEN_NONE)
+      TOKEN_NONE);
+  if (expected != TOKEN_NONE)
     return FAIL (expected);
 
   if (!check_token (scanner, G_TOKEN_EOF)) {
@@ -921,13 +856,13 @@ parse_program (GScanner *scanner, ViviCodeStatement **statement)
     return FAIL (parse_statement (scanner, statement));
   }
 
-  return G_TOKEN_NONE;
+  return TOKEN_NONE;
 }
 
 // parsing
 
 static int
-parse_statement_list (GScanner *scanner, ParseStatementFunction function,
+parse_statement_list (ViviCompilerScanner *scanner, ParseStatementFunction function,
     ViviCodeStatement **block, guint separator)
 {
   ViviCodeStatement *statement;
@@ -940,7 +875,7 @@ parse_statement_list (GScanner *scanner, ParseStatementFunction function,
   *block = NULL;
 
   expected = function (scanner, &statement);
-  if (expected != G_TOKEN_NONE)
+  if (expected != TOKEN_NONE)
     return expected;
 
   *block = vivi_code_block_new ();
@@ -949,22 +884,22 @@ parse_statement_list (GScanner *scanner, ParseStatementFunction function,
     vivi_code_block_add_statement (VIVI_CODE_BLOCK (*block), statement);
     g_object_unref (statement);
 
-    if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
+    if (separator != TOKEN_NONE && !check_token (scanner, separator))
       break;
 
     expected = function (scanner, &statement);
-    if (expected != G_TOKEN_NONE && expected >= 0) {
+    if (expected != TOKEN_NONE && expected >= 0) {
       g_object_unref (*block);
       *block = NULL;
       return expected;
     }
-  } while (expected == G_TOKEN_NONE);
+  } while (expected == TOKEN_NONE);
 
-  return G_TOKEN_NONE;
+  return TOKEN_NONE;
 }
 
 static int
-parse_value_list (GScanner *scanner, ParseValueFunction function,
+parse_value_list (ViviCompilerScanner *scanner, ParseValueFunction function,
     ViviCodeValue ***list, guint separator)
 {
   GPtrArray *array;
@@ -976,7 +911,7 @@ parse_value_list (GScanner *scanner, ParseValueFunction function,
   g_assert (list != NULL);
 
   expected = function (scanner, &value);
-  if (expected != G_TOKEN_NONE)
+  if (expected != TOKEN_NONE)
     return expected;
 
   array = g_ptr_array_new ();
@@ -984,79 +919,38 @@ parse_value_list (GScanner *scanner, ParseValueFunction function,
   do {
     g_ptr_array_add (array, value);
 
-    if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
+    if (separator != TOKEN_NONE && !check_token (scanner, separator))
       break;
 
     expected = function (scanner, &value);
-    if (expected != G_TOKEN_NONE && expected >= 0)
+    if (expected != TOKEN_NONE && expected >= 0)
       return expected;
-  } while (expected == G_TOKEN_NONE);
+  } while (expected == TOKEN_NONE);
   g_ptr_array_add (array, NULL);
 
   *list = (ViviCodeValue **)g_ptr_array_free (array, FALSE);
 
-  return G_TOKEN_NONE;
+  return TOKEN_NONE;
 }
 
 // public
 
 ViviCodeStatement *
-vivi_compile_text (const char *text, gsize len, const char *input_name)
+vivi_compile_file (FILE *file, const char *input_name)
 {
-  GScanner *scanner;
+  ViviCompilerScanner *scanner;
   ViviCodeStatement *statement;
-  int expected, i;
-
-  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;
-  // 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);
-  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));
-  }
+  int expected;
 
-  scanner->input_name = input_name;
-  g_scanner_input_text (scanner, text, len);
+  g_return_val_if_fail (file != NULL, 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;
-	}
-      }
-    }
+  scanner = vivi_compiler_scanner_new (file);
 
-    g_scanner_get_next_token (scanner);
-    g_scanner_unexp_token (scanner, FAIL (expected), NULL, name, NULL, NULL,
-	TRUE);
-  }
+  expected = parse_program (scanner, &statement);
+  g_assert ((expected == TOKEN_NONE && VIVI_IS_CODE_STATEMENT (statement)) ||
+	(expected != TOKEN_NONE && statement == NULL));
 
-  g_scanner_destroy (scanner);
+  g_object_unref (scanner);
 
   return statement;
 }
diff --git a/vivified/code/vivi_compiler.h b/vivified/code/vivi_compiler.h
index f15108a..4a8529b 100644
--- a/vivified/code/vivi_compiler.h
+++ b/vivified/code/vivi_compiler.h
@@ -20,14 +20,15 @@
 #ifndef _VIVI_DECOMPILER_H_
 #define _VIVI_DECOMPILER_H_
 
+#include <stdio.h>
+
 #include <swfdec/swfdec.h>
 #include <vivified/code/vivi_code_statement.h>
 
 G_BEGIN_DECLS
 
 
-ViviCodeStatement *	vivi_compile_text		(const char *	text,
-							 gsize		len,
+ViviCodeStatement *	vivi_compile_file		(FILE *		file,
 							 const char *	input_name);
 
 
diff --git a/vivified/code/vivi_compiler_scanner.c b/vivified/code/vivi_compiler_scanner.c
index 39a5c51..81cd0a7 100644
--- a/vivified/code/vivi_compiler_scanner.c
+++ b/vivified/code/vivi_compiler_scanner.c
@@ -72,7 +72,7 @@ vivi_compiler_scanner_advance (ViviCompilerScanner *scanner)
 
   if (scanner->file == NULL) {
     scanner->next_token = TOKEN_EOF;
-    scanner->next_value.string = NULL;
+    scanner->next_value.v_string = NULL;
   } else {
     scanner->next_token = yylex ();
     scanner->next_value = yylval;
@@ -80,7 +80,7 @@ vivi_compiler_scanner_advance (ViviCompilerScanner *scanner)
 }
 
 ViviCompilerScannerToken
-vivi_compiler_scanner_get_token (ViviCompilerScanner *scanner)
+vivi_compiler_scanner_get_next_token (ViviCompilerScanner *scanner)
 {
   g_return_val_if_fail (VIVI_IS_COMPILER_SCANNER (scanner), TOKEN_EOF);
 
@@ -90,7 +90,7 @@ vivi_compiler_scanner_get_token (ViviCompilerScanner *scanner)
 }
 
 ViviCompilerScannerToken
-vivi_compiler_scanner_peek_token (ViviCompilerScanner *scanner)
+vivi_compiler_scanner_peek_next_token (ViviCompilerScanner *scanner)
 {
   g_return_val_if_fail (VIVI_IS_COMPILER_SCANNER (scanner), TOKEN_EOF);
 
diff --git a/vivified/code/vivi_compiler_scanner.h b/vivified/code/vivi_compiler_scanner.h
index 103ed2a..16618cb 100644
--- a/vivified/code/vivi_compiler_scanner.h
+++ b/vivified/code/vivi_compiler_scanner.h
@@ -26,6 +26,7 @@
 G_BEGIN_DECLS
 
 typedef enum {
+  TOKEN_NONE = 0,
   TOKEN_EOF,
   TOKEN_UNKNOWN,
 
@@ -132,14 +133,16 @@ typedef enum {
   TOKEN_WITH,
 
   // reserved keywords
-  TOKEN_FUTURE
+  TOKEN_FUTURE,
+
+  TOKEN_LAST
 } ViviCompilerScannerToken;
 
 typedef union {
-  gboolean	boolean;
-  double	number;
-  char *	string;
-  char *	identifier;
+  gboolean	v_boolean;
+  double	v_number;
+  char *	v_string;
+  char *	v_identifier;
 } ViviCompilerScannerValue;
 
 typedef struct _ViviCompilerScanner ViviCompilerScanner;
@@ -172,8 +175,8 @@ struct _ViviCompilerScannerClass
 GType				vivi_compiler_scanner_get_type   	(void);
 
 ViviCompilerScanner *		vivi_compiler_scanner_new		(FILE *		file);
-ViviCompilerScannerToken	vivi_compiler_scanner_get_token		(ViviCompilerScanner *	scanner);
-ViviCompilerScannerToken	vivi_compiler_scanner_peek_token	(ViviCompilerScanner *	scanner);
+ViviCompilerScannerToken	vivi_compiler_scanner_get_next_token	(ViviCompilerScanner *	scanner);
+ViviCompilerScannerToken	vivi_compiler_scanner_peek_next_token	(ViviCompilerScanner *	scanner);
 
 G_END_DECLS
 #endif
diff --git a/vivified/code/vivi_compiler_scanner_lex.lex b/vivified/code/vivi_compiler_scanner_lex.lex
index c6b8f70..b35fe96 100644
--- a/vivified/code/vivi_compiler_scanner_lex.lex
+++ b/vivified/code/vivi_compiler_scanner_lex.lex
@@ -69,9 +69,9 @@ identifier_part		[$_a-zA-Z0-9]
 "|="			{ return TOKEN_ASSIGN_BITWISE_OR; }
 
 "null"			{ return TOKEN_NULL; }
-"true"			{ yylval.boolean = 1;
+"true"			{ yylval.v_boolean = 1;
 			  return TOKEN_BOOLEAN; }
-"false"			{ yylval.boolean = 0;
+"false"			{ yylval.v_boolean = 0;
 			  return TOKEN_BOOLEAN; }
 "this"			{ return TOKEN_THIS; }
 
@@ -79,11 +79,11 @@ identifier_part		[$_a-zA-Z0-9]
 
 "abstract"		{ return TOKEN_FUTURE; }
 
-{digit}+		{ yylval.number = atoi(yytext);
+{digit}+		{ yylval.v_number = atoi(yytext);
 			  return TOKEN_NUMBER; }
 
 {identifier_start}({identifier_part})* {
-			  yylval.identifier = (char *)strdup(yytext);
+			  yylval.v_identifier = (char *)strdup(yytext);
 			  return TOKEN_IDENTIFIER; }
 
 .			{ printf("Unknown character [%c]\n",yytext[0]);
commit aed0aa90596e180169e89f33f16848bac0e6c7f6
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Tue Apr 1 23:55:37 2008 +0300

    Start implementing ViviCompilerScanner using flex

diff --git a/configure.ac b/configure.ac
index a3e186b..a5bb805 100644
--- a/configure.ac
+++ b/configure.ac
@@ -54,6 +54,8 @@ AM_PROG_CC_STDC
 AM_PROG_CC_C_O
 AM_PROG_AS
 AC_PROG_AWK
+dnl FIXME only require lex for vivi
+AM_PROG_LEX
 
 AC_HEADER_STDC
 
diff --git a/vivified/code/.gitignore b/vivified/code/.gitignore
index b85daef..70af836 100644
--- a/vivified/code/.gitignore
+++ b/vivified/code/.gitignore
@@ -11,5 +11,8 @@ Makefile.in
 *.lo
 *.loT
 
+vivi_compiler_scanner_lex.c
+vivi_compiler_scanner_lex.h
+
 vivi-decompile
 vivi-compile
diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index a0d2807..cd866af 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -33,6 +33,8 @@ libvivified_compiler_la_SOURCES = \
 	vivi_code_value_statement.c \
 	vivi_compiler.c \
 	vivi_compiler_empty_statement.c \
+	vivi_compiler_scanner.c \
+	vivi_compiler_scanner_lex.c \
 	vivi_decompiler_block.c \
 	vivi_decompiler_duplicate.c \
 	vivi_decompiler_state.c \
@@ -67,6 +69,10 @@ noinst_HEADERS = \
 	vivi_code_value_statement.h \
 	vivi_compiler.h \
 	vivi_compiler_empty_statement.h \
+	vivi_compiler_scanner.h \
+	vivi_compiler_scanner_lex.h \
+	vivi_compiler_scanner_lex_include.h \
+	vivi_compiler_scanner_lex.lex \
 	vivi_decompiler.h \
 	vivi_decompiler_block.h \
 	vivi_decompiler_duplicate.h \
@@ -74,9 +80,12 @@ noinst_HEADERS = \
 	vivi_decompiler_unknown.h \
 	vivified-compiler.h
 
-
 noinst_PROGRAMS = vivi-decompile vivi-compile
 
+vivi_compiler_scanner_lex.h: vivi_compiler_scanner_lex.c
+vivi_compiler_scanner_lex.c: vivi_compiler_scanner_lex.lex
+	$(LEX) -o vivi_compiler_scanner_lex.c --header-file=vivi_compiler_scanner_lex.h vivi_compiler_scanner_lex.lex
+
 vivi_decompile_SOURCES = \
 	decompiler.c
 
diff --git a/vivified/code/vivi_compiler_scanner.c b/vivified/code/vivi_compiler_scanner.c
new file mode 100644
index 0000000..39a5c51
--- /dev/null
+++ b/vivified/code/vivi_compiler_scanner.c
@@ -0,0 +1,98 @@
+/* Vivified
+ * Copyright (C) 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_scanner.h"
+
+#include "vivi_compiler_scanner_lex.h"
+#include "vivi_compiler_scanner_lex_include.h"
+
+G_DEFINE_TYPE (ViviCompilerScanner, vivi_compiler_scanner, G_TYPE_OBJECT)
+
+static void
+vivi_compiler_scanner_dispose (GObject *object)
+{
+  //ViviCompilerScanner *scanner = VIVI_COMPILER_SCANNER (object);
+
+  G_OBJECT_CLASS (vivi_compiler_scanner_parent_class)->dispose (object);
+}
+
+static void
+vivi_compiler_scanner_class_init (ViviCompilerScannerClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = vivi_compiler_scanner_dispose;
+}
+
+static void
+vivi_compiler_scanner_init (ViviCompilerScanner *token)
+{
+}
+
+ViviCompilerScanner *
+vivi_compiler_scanner_new (FILE *file)
+{
+  ViviCompilerScanner *scanner;
+
+  g_return_val_if_fail (file != NULL, NULL);
+
+  scanner = g_object_new (VIVI_TYPE_COMPILER_SCANNER, NULL);
+  scanner->file = file;
+
+  return scanner;
+}
+
+static void
+vivi_compiler_scanner_advance (ViviCompilerScanner *scanner)
+{
+  g_return_if_fail (VIVI_IS_COMPILER_SCANNER (scanner));
+
+  scanner->token = scanner->next_token;
+  scanner->value = scanner->next_value;
+
+  if (scanner->file == NULL) {
+    scanner->next_token = TOKEN_EOF;
+    scanner->next_value.string = NULL;
+  } else {
+    scanner->next_token = yylex ();
+    scanner->next_value = yylval;
+  }
+}
+
+ViviCompilerScannerToken
+vivi_compiler_scanner_get_token (ViviCompilerScanner *scanner)
+{
+  g_return_val_if_fail (VIVI_IS_COMPILER_SCANNER (scanner), TOKEN_EOF);
+
+  vivi_compiler_scanner_advance (scanner);
+
+  return scanner->token;
+}
+
+ViviCompilerScannerToken
+vivi_compiler_scanner_peek_token (ViviCompilerScanner *scanner)
+{
+  g_return_val_if_fail (VIVI_IS_COMPILER_SCANNER (scanner), TOKEN_EOF);
+
+  return scanner->next_token;
+}
diff --git a/vivified/code/vivi_compiler_scanner.h b/vivified/code/vivi_compiler_scanner.h
new file mode 100644
index 0000000..103ed2a
--- /dev/null
+++ b/vivified/code/vivi_compiler_scanner.h
@@ -0,0 +1,179 @@
+/* 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_COMPILER_SCANNER_H_
+#define _VIVI_COMPILER_SCANNER_H_
+
+#include <stdio.h>
+#include <swfdec/swfdec.h>
+
+G_BEGIN_DECLS
+
+typedef enum {
+  TOKEN_EOF,
+  TOKEN_UNKNOWN,
+
+  // comparision
+  TOKEN_BRACE_LEFT,
+  TOKEN_BRACE_RIGHT,
+  TOKEN_BRACKET_RIGHT,
+  TOKEN_BRACKET_LEFT,
+  TOKEN_PARENTHESIS_LEFT,
+  TOKEN_PARENTHESIS_RIGHT,
+
+  // punctuation
+  TOKEN_DOT,
+  TOKEN_SEMICOLON,
+  TOKEN_COMMA,
+
+  // comparision
+  TOKEN_LESS_THAN,
+  TOKEN_GREATER_THAN,
+  TOKEN_LESS_THAN_OR_EQUAL,
+  TOKEN_EQUAL_OR_MORE_THAN,
+
+  // equality
+  TOKEN_EQUAL,
+  TOKEN_NOT_EQUAL,
+  TOKEN_STRICT_EQUAL,
+  TOKEN_NOT_STRICT_EQUAL,
+
+  // operator
+  TOKEN_PLUS,
+  TOKEN_MINUS,
+  TOKEN_MULTIPLY,
+  TOKEN_DIVIDE,
+  TOKEN_REMAINDER,
+
+  // shift
+  TOKEN_SHIFT_LEFT,
+  TOKEN_SHIFT_RIGHT,
+  TOKEN_SHIFT_RIGHT_UNSIGNED,
+
+  // bitwise
+  TOKEN_BITWISE_AND,
+  TOKEN_BITWISE_OR,
+  TOKEN_BITWISE_XOR,
+  
+  // unary/postfix
+  TOKEN_LOGICAL_NOT,
+  TOKEN_BITWISE_NOT,
+  TOKEN_PLUSPLUS,
+  TOKEN_MINUSMINUS,
+
+  // conditional
+  TOKEN_QUESTION_MARK,
+  TOKEN_COLON,
+
+  // logical
+  TOKEN_LOGICAL_AND,
+  TOKEN_LOGICAL_OR,
+
+  // assign
+  TOKEN_ASSIGN,
+  TOKEN_ASSIGN_MULTIPLY,
+  TOKEN_ASSIGN_DIVIDE,
+  TOKEN_ASSIGN_REMAINDER,
+  TOKEN_ASSIGN_ADD,
+  TOKEN_ASSIGN_MINUS,
+  TOKEN_ASSIGN_SHIFT_LEFT,
+  TOKEN_ASSIGN_SHIFT_RIGHT,
+  TOKEN_ASSIGN_SHIFT_RIGHT_ZERO,
+  TOKEN_ASSIGN_BITWISE_AND,
+  TOKEN_ASSIGN_BITWISE_XOR,
+  TOKEN_ASSIGN_BITWISE_OR,
+
+  // values
+  TOKEN_NULL,
+  TOKEN_BOOLEAN,
+  TOKEN_NUMBER,
+  TOKEN_IDENTIFIER,
+
+  // keywords
+  TOKEN_BREAK,
+  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
+} ViviCompilerScannerToken;
+
+typedef union {
+  gboolean	boolean;
+  double	number;
+  char *	string;
+  char *	identifier;
+} ViviCompilerScannerValue;
+
+typedef struct _ViviCompilerScanner ViviCompilerScanner;
+typedef struct _ViviCompilerScannerClass ViviCompilerScannerClass;
+
+#define VIVI_TYPE_COMPILER_SCANNER                    (vivi_compiler_scanner_get_type())
+#define VIVI_IS_COMPILER_SCANNER(obj)                 (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_COMPILER_SCANNER))
+#define VIVI_IS_COMPILER_SCANNER_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_COMPILER_SCANNER))
+#define VIVI_COMPILER_SCANNER(obj)                    (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_COMPILER_SCANNER, ViviCompilerScanner))
+#define VIVI_COMPILER_SCANNER_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_COMPILER_SCANNER, ViviCompilerScannerClass))
+#define VIVI_COMPILER_SCANNER_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_COMPILER_SCANNER, ViviCompilerScannerClass))
+
+struct _ViviCompilerScanner
+{
+  GObject			object;
+
+  FILE *			file;
+
+  ViviCompilerScannerToken	token;
+  ViviCompilerScannerToken	next_token;
+  ViviCompilerScannerValue	value;
+  ViviCompilerScannerValue	next_value;
+};
+
+struct _ViviCompilerScannerClass
+{
+  GObjectClass		object_class;
+};
+
+GType				vivi_compiler_scanner_get_type   	(void);
+
+ViviCompilerScanner *		vivi_compiler_scanner_new		(FILE *		file);
+ViviCompilerScannerToken	vivi_compiler_scanner_get_token		(ViviCompilerScanner *	scanner);
+ViviCompilerScannerToken	vivi_compiler_scanner_peek_token	(ViviCompilerScanner *	scanner);
+
+G_END_DECLS
+#endif
diff --git a/vivified/code/vivi_compiler_scanner_lex.lex b/vivified/code/vivi_compiler_scanner_lex.lex
new file mode 100644
index 0000000..c6b8f70
--- /dev/null
+++ b/vivified/code/vivi_compiler_scanner_lex.lex
@@ -0,0 +1,93 @@
+%{
+#include "vivi_compiler_scanner_lex_include.h"
+%}
+
+digit			[0-9]
+identifier_start	[$_a-zA-Z]
+identifier_part		[$_a-zA-Z0-9]
+
+%%
+
+[ \t\n\r]		/* skip whitespace */
+"{"			{ return TOKEN_BRACE_LEFT; }
+"}"			{ return TOKEN_BRACE_RIGHT; }
+"["			{ return TOKEN_BRACKET_RIGHT; }
+"]"			{ return TOKEN_BRACKET_LEFT; }
+"("			{ return TOKEN_PARENTHESIS_LEFT; }
+")"			{ return TOKEN_PARENTHESIS_RIGHT; }
+
+"."			{ return TOKEN_DOT; }
+";"			{ return TOKEN_SEMICOLON; }
+","			{ return TOKEN_COMMA; }
+
+"<"			{ return TOKEN_LESS_THAN; }
+">"			{ return TOKEN_GREATER_THAN; }
+"<="			{ return TOKEN_LESS_THAN_OR_EQUAL; }
+"=>"			{ return TOKEN_EQUAL_OR_MORE_THAN; }
+
+"==",			{ return TOKEN_EQUAL; }
+"!=",			{ return TOKEN_NOT_EQUAL; }
+"===",			{ return TOKEN_STRICT_EQUAL; }
+"!==",			{ return TOKEN_NOT_STRICT_EQUAL; }
+
+"+"			{ return TOKEN_PLUS; }
+"-"			{ return TOKEN_MINUS; }
+"*"			{ return TOKEN_MULTIPLY; }
+"/"			{ return TOKEN_DIVIDE; }
+"%"			{ return TOKEN_REMAINDER; }
+
+"<<"			{ return TOKEN_SHIFT_LEFT; }
+">>"			{ return TOKEN_SHIFT_RIGHT; }
+">>>"			{ return TOKEN_SHIFT_RIGHT_UNSIGNED; }
+
+"&"			{ return TOKEN_BITWISE_AND; }
+"|"			{ return TOKEN_BITWISE_OR; }
+"^"			{ return TOKEN_BITWISE_XOR; }
+
+"!"			{ return TOKEN_LOGICAL_NOT; }
+"~"			{ return TOKEN_BITWISE_NOT; }
+"++"			{ return TOKEN_PLUSPLUS; }
+"--"			{ return TOKEN_MINUSMINUS; }
+
+"?"			{ return TOKEN_QUESTION_MARK; }
+":"			{ return TOKEN_COLON; }
+
+"&&"			{ return TOKEN_LOGICAL_AND; }
+"||"			{ return TOKEN_LOGICAL_OR; }
+
+"="			{ return TOKEN_ASSIGN; }
+"*="			{ return TOKEN_ASSIGN_MULTIPLY; }
+"/="			{ return TOKEN_ASSIGN_DIVIDE; }
+"%="			{ return TOKEN_ASSIGN_REMAINDER; }
+"+="			{ return TOKEN_ASSIGN_ADD; }
+"-="			{ return TOKEN_ASSIGN_MINUS; }
+"<<="			{ return TOKEN_ASSIGN_SHIFT_LEFT; }
+">>="			{ return TOKEN_ASSIGN_SHIFT_RIGHT; }
+">>>="			{ return TOKEN_ASSIGN_SHIFT_RIGHT_ZERO; }
+"&="			{ return TOKEN_ASSIGN_BITWISE_AND; }
+"^="			{ return TOKEN_ASSIGN_BITWISE_XOR; }
+"|="			{ return TOKEN_ASSIGN_BITWISE_OR; }
+
+"null"			{ return TOKEN_NULL; }
+"true"			{ yylval.boolean = 1;
+			  return TOKEN_BOOLEAN; }
+"false"			{ yylval.boolean = 0;
+			  return TOKEN_BOOLEAN; }
+"this"			{ return TOKEN_THIS; }
+
+"break"			{ return TOKEN_BREAK; }
+
+"abstract"		{ return TOKEN_FUTURE; }
+
+{digit}+		{ yylval.number = atoi(yytext);
+			  return TOKEN_NUMBER; }
+
+{identifier_start}({identifier_part})* {
+			  yylval.identifier = (char *)strdup(yytext);
+			  return TOKEN_IDENTIFIER; }
+
+.			{ printf("Unknown character [%c]\n",yytext[0]);
+			  return TOKEN_UNKNOWN; }
+%%
+
+int yywrap(void){return 1;}
diff --git a/vivified/code/vivi_compiler_scanner_lex_include.h b/vivified/code/vivi_compiler_scanner_lex_include.h
new file mode 100644
index 0000000..2224b2f
--- /dev/null
+++ b/vivified/code/vivi_compiler_scanner_lex_include.h
@@ -0,0 +1,8 @@
+#ifndef _VIVI_COMPILER_SCANNER_LEX_INCLUDE_H_
+#define _VIVI_COMPILER_SCANNER_LEX_INCLUDE_H_
+
+#include "vivi_compiler_scanner.h"
+
+ViviCompilerScannerValue yylval;
+
+#endif // _VIVI_COMPILER_SCANNER_LEX_INCLUDE_H_


More information about the Swfdec-commits mailing list