[Swfdec-commits] 12 commits - vivified/code

Pekka Lampila medar at kemper.freedesktop.org
Thu Apr 3 15:26:34 PDT 2008


 vivified/code/decompiler.c                |    2 
 vivified/code/vivi_code_function.c        |   44 -
 vivified/code/vivi_code_function.h        |   11 
 vivified/code/vivi_compiler.c             | 1247 +++++++++++++++++++-----------
 vivified/code/vivi_compiler_scanner.c     |   22 
 vivified/code/vivi_compiler_scanner.h     |    7 
 vivified/code/vivi_compiler_scanner_lex.l |   77 -
 vivified/code/vivi_decompiler.c           |    2 
 8 files changed, 921 insertions(+), 491 deletions(-)

New commits:
commit 1d7808def7d202930008c0b062975b177d0d7233
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Apr 4 01:21:26 2008 +0300

    Rename TOKEN_FUTURE to TOKEN_RESERVED_KEYWORD

diff --git a/vivified/code/vivi_compiler_scanner.c b/vivified/code/vivi_compiler_scanner.c
index 0243f8f..e9c576b 100644
--- a/vivified/code/vivi_compiler_scanner.c
+++ b/vivified/code/vivi_compiler_scanner.c
@@ -163,7 +163,7 @@ static const struct {
   { TOKEN_WITH, "with" },
 
   // reserved keywords
-  { TOKEN_FUTURE, "RESERVED KEYWORD" },
+  { TOKEN_RESERVED_KEYWORD, "RESERVED KEYWORD" },
 
   { TOKEN_LAST, NULL }
 };
diff --git a/vivified/code/vivi_compiler_scanner.h b/vivified/code/vivi_compiler_scanner.h
index c5c72f5..64067bd 100644
--- a/vivified/code/vivi_compiler_scanner.h
+++ b/vivified/code/vivi_compiler_scanner.h
@@ -137,7 +137,7 @@ typedef enum {
   TOKEN_WITH,
 
   // reserved keywords
-  TOKEN_FUTURE,
+  TOKEN_RESERVED_KEYWORD,
 
   TOKEN_LAST
 } ViviCompilerScannerToken;
diff --git a/vivified/code/vivi_compiler_scanner_lex.l b/vivified/code/vivi_compiler_scanner_lex.l
index a4d98d8..2a2c433 100644
--- a/vivified/code/vivi_compiler_scanner_lex.l
+++ b/vivified/code/vivi_compiler_scanner_lex.l
@@ -109,37 +109,37 @@ line_terminator		[\n\r]
 "while"			{ return TOKEN_WHILE; }
 "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; }
+"abstract"		{ return TOKEN_RESERVED_KEYWORD; }
+"boolean"		{ return TOKEN_RESERVED_KEYWORD; }
+"byte"			{ return TOKEN_RESERVED_KEYWORD; }
+"char"			{ return TOKEN_RESERVED_KEYWORD; }
+"class"			{ return TOKEN_RESERVED_KEYWORD; }
+"const"			{ return TOKEN_RESERVED_KEYWORD; }
+"debugger"		{ return TOKEN_RESERVED_KEYWORD; }
+"double"		{ return TOKEN_RESERVED_KEYWORD; }
+"enum"			{ return TOKEN_RESERVED_KEYWORD; }
+"export"		{ return TOKEN_RESERVED_KEYWORD; }
+"extends"		{ return TOKEN_RESERVED_KEYWORD; }
+"final"			{ return TOKEN_RESERVED_KEYWORD; }
+"float"			{ return TOKEN_RESERVED_KEYWORD; }
+"goto"			{ return TOKEN_RESERVED_KEYWORD; }
+"implements"		{ return TOKEN_RESERVED_KEYWORD; }
+"import"		{ return TOKEN_RESERVED_KEYWORD; }
+"int"			{ return TOKEN_RESERVED_KEYWORD; }
+"interface"		{ return TOKEN_RESERVED_KEYWORD; }
+"long"			{ return TOKEN_RESERVED_KEYWORD; }
+"native"		{ return TOKEN_RESERVED_KEYWORD; }
+"package"		{ return TOKEN_RESERVED_KEYWORD; }
+"private"		{ return TOKEN_RESERVED_KEYWORD; }
+"protected"		{ return TOKEN_RESERVED_KEYWORD; }
+"public"		{ return TOKEN_RESERVED_KEYWORD; }
+"short"			{ return TOKEN_RESERVED_KEYWORD; }
+"static"		{ return TOKEN_RESERVED_KEYWORD; }
+"super"			{ return TOKEN_RESERVED_KEYWORD; }
+"synchronized"		{ return TOKEN_RESERVED_KEYWORD; }
+"throws"		{ return TOKEN_RESERVED_KEYWORD; }
+"transient"		{ return TOKEN_RESERVED_KEYWORD; }
+"volatile"		{ return TOKEN_RESERVED_KEYWORD; }
 
 [-+]*{digit}+		{ yylval.v_number = atoi(yytext);
 			  return TOKEN_NUMBER; }
commit 90eabd4cb45d99e3017b853454623aa8bb787ff1
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Apr 4 01:20:05 2008 +0300

    Implement parsing of while loops

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 8b7a00f..c5db218 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -54,6 +54,7 @@ enum {
   ERROR_TOKEN_LITERAL = TOKEN_LAST + 1,
   ERROR_TOKEN_PROPERTY_NAME,
   ERROR_TOKEN_PRIMARY_EXPRESSION,
+  ERROR_TOKEN_ITERATION_STATEMENT,
   ERROR_TOKEN_EXPRESSION_STATEMENT,
   ERROR_TOKEN_STATEMENT
 };
@@ -65,6 +66,7 @@ static const struct {
   { ERROR_TOKEN_LITERAL, "LITERAL" },
   { ERROR_TOKEN_PROPERTY_NAME, "PROPERTY NAME" },
   { ERROR_TOKEN_PRIMARY_EXPRESSION, "PRIMARY EXPRESSION" },
+  { ERROR_TOKEN_ITERATION_STATEMENT, "ITERATION STATEMENT" },
   { ERROR_TOKEN_EXPRESSION_STATEMENT, "EXPRESSION STATEMENT" },
   { ERROR_TOKEN_STATEMENT, "STATEMENT" },
   { TOKEN_LAST, NULL }
@@ -1137,6 +1139,55 @@ static ParseStatus
 parse_statement (ParseData *data, ViviCodeStatement **statement);
 
 static ParseStatus
+parse_iteration_statement (ParseData *data, ViviCodeStatement **statement)
+{
+  ParseStatus status;
+  ViviCodeValue *condition;
+  ViviCodeStatement *pre_statement, *loop_statement;
+
+  *statement = NULL;
+
+  // TODO: for, do while
+
+  if (check_token (data, TOKEN_WHILE)) {
+    if (!check_token (data, TOKEN_PARENTHESIS_LEFT))
+      return FAIL (TOKEN_PARENTHESIS_LEFT);
+
+    status = parse_expression (data, &condition, &pre_statement);
+    if (status != STATUS_OK)
+      return FAIL_CHILD (status);
+
+    if (!check_token (data, TOKEN_PARENTHESIS_RIGHT)) {
+      g_object_unref (condition);
+      if (pre_statement != NULL)
+	g_object_unref (pre_statement);
+      return FAIL (TOKEN_PARENTHESIS_RIGHT);
+    }
+
+    status = parse_statement (data, &loop_statement); 
+    if (status != STATUS_OK) {
+      g_object_unref (condition);
+      if (pre_statement != NULL)
+	g_object_unref (pre_statement);
+      return FAIL_CHILD (status);
+    }
+
+    *statement = vivi_code_loop_new ();
+    vivi_code_loop_set_condition (VIVI_CODE_LOOP (*statement), condition);
+    g_object_unref (condition);
+    vivi_code_loop_set_statement (VIVI_CODE_LOOP (*statement), loop_statement);
+    g_object_unref (loop_statement);
+
+    *statement =
+      vivi_compiler_combine_statements (2, pre_statement, *statement);
+
+    return STATUS_OK;
+  } else {
+    return CANCEL (ERROR_TOKEN_ITERATION_STATEMENT);
+  }
+}
+
+static ParseStatus
 parse_if_statement (ParseData *data, ViviCodeStatement **statement)
 {
   ParseStatus status;
@@ -1317,7 +1368,7 @@ parse_statement (ParseData *data, ViviCodeStatement **statement)
     parse_empty_statement,
     parse_expression_statement,
     parse_if_statement,
-    //parse_iteration_statement,
+    parse_iteration_statement,
     //parse_continue_statement,
     //parse_break_statement,
     //parse_return_statement,
diff --git a/vivified/code/vivi_compiler_scanner.c b/vivified/code/vivi_compiler_scanner.c
index dcedc9d..0243f8f 100644
--- a/vivified/code/vivi_compiler_scanner.c
+++ b/vivified/code/vivi_compiler_scanner.c
@@ -197,8 +197,6 @@ vivi_compiler_scanner_advance (ViviCompilerScanner *scanner)
     scanner->next_token = yylex ();
     scanner->next_value = yylval;
   }
-
-  g_print (":: %s\n", vivi_compiler_scanner_token_name (scanner->next_token));
 }
 
 ViviCompilerScanner *
diff --git a/vivified/code/vivi_compiler_scanner_lex.l b/vivified/code/vivi_compiler_scanner_lex.l
index 5dc0a1c..a4d98d8 100644
--- a/vivified/code/vivi_compiler_scanner_lex.l
+++ b/vivified/code/vivi_compiler_scanner_lex.l
@@ -141,7 +141,7 @@ line_terminator		[\n\r]
 "transient"		{ return TOKEN_FUTURE; }
 "volatile"		{ return TOKEN_FUTURE; }
 
-{digit}+		{ yylval.v_number = atoi(yytext);
+[-+]*{digit}+		{ yylval.v_number = atoi(yytext);
 			  return TOKEN_NUMBER; }
 "\"".*"\""		{ yylval.v_string = g_strndup (yytext + 1, yyleng - 2);
 			  return TOKEN_STRING; }
commit ada5063c038b84a610255c1d7d5272ad32ee306c
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Apr 4 01:07:53 2008 +0300

    Add parsing of function expression and function call. Add missing while token

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 266b3c7..8b7a00f 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -95,6 +95,11 @@ static ParseStatus
 parse_statement_list (ParseData *data, ParseStatementFunction function, ViviCodeStatement **statement, guint separator);
 
 static ParseStatus
+parse_value_statement_list (ParseData *data,
+    ParseValueStatementFunction function, ViviCodeValue ***list,
+    ViviCodeStatement **statement, guint separator);
+
+static ParseStatus
 parse_value_list (ParseData *data, ParseValueFunction function,
     ViviCodeValue ***list, guint separator);
 
@@ -121,7 +126,7 @@ free_value_list (ViviCodeValue **list)
   g_free (list);
 }
 
-static ViviCodeStatement *
+G_GNUC_WARN_UNUSED_RESULT static ViviCodeStatement *
 vivi_compiler_combine_statements (guint count, ...)
 {
   va_list args;
@@ -158,6 +163,34 @@ vivi_compiler_combine_statements (guint count, ...)
   return VIVI_CODE_STATEMENT (block);
 }
 
+static ViviCodeValue *
+vivi_compiler_function_call_new (ViviCodeValue *name)
+{
+  ViviCodeValue *value;
+
+  g_return_val_if_fail (VIVI_IS_CODE_VALUE (name), NULL);
+
+  value = NULL;
+
+  if (VIVI_IS_CODE_GET (name)) {
+    ViviCodeGet *get = VIVI_CODE_GET (name);
+
+    if (get->from != NULL) {
+      value = g_object_ref (get->from);
+      name = g_object_ref (get->name);
+    }
+  }
+
+  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_function_call_new (value, name);
+}
+
 static ViviCodeStatement *
 vivi_compiler_assignment_new (ViviCodeValue *left, ViviCodeValue *right)
 {
@@ -479,6 +512,10 @@ parse_primary_expression (ParseData *data, ViviCodeValue **value,
 }
 
 static ParseStatus
+parse_function_expression (ParseData *data, ViviCodeValue **value,
+    ViviCodeStatement **statement);
+
+static ParseStatus
 parse_member_expression (ParseData *data, ViviCodeValue **value,
     ViviCodeStatement **statement)
 {
@@ -492,8 +529,8 @@ parse_member_expression (ParseData *data, ViviCodeValue **value,
   // TODO: new MemberExpression Arguments
 
   status = parse_primary_expression (data, value, statement);
-  //if (status == STATUS_CANCEL)
-  //  status = parse_function_expression (data, value);
+  if (status == STATUS_CANCEL)
+    status = parse_function_expression (data, value, statement);
 
   if (status != STATUS_OK)
     return status;
@@ -569,18 +606,85 @@ parse_new_expression (ParseData *data, ViviCodeValue **value,
 }
 
 static ParseStatus
-parse_left_hand_side_expression (ParseData *data,
-    ViviCodeValue **value, ViviCodeStatement **statement)
+parse_left_hand_side_expression (ParseData *data, ViviCodeValue **value,
+    ViviCodeStatement **statement)
 {
   ParseStatus status;
+  int i;
+  ViviCodeValue *name;
+  ViviCodeValue **arguments;
+  ViviCodeStatement *argument_statement;
 
   *value = NULL;
+  *statement = NULL;
+
+  if (check_token (data, TOKEN_NEW)) {
+    status = parse_new_expression (data, value, statement);
+    if (status != STATUS_OK)
+      return FAIL_CHILD (status);
+    if (!VIVI_IS_CODE_FUNCTION_CALL (*value)) {
+      ViviCodeValue *tmp = VIVI_CODE_VALUE (*value);
+      *value = vivi_code_function_call_new (NULL, tmp);
+      g_object_unref (tmp);
+    }
+    vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*value),
+	TRUE);
+    return STATUS_OK;
+  }
 
-  status = parse_new_expression (data, value, statement);
-  //if (status == STATUS_CANCEL)
-  //  status = parse_call_expression (data, value);
+  status = parse_member_expression (data, value, statement);
+  if (status != STATUS_OK)
+    return status;
 
-  return status;
+  while (TRUE) {
+    // TODO: member expressions?
+    if (!check_token (data, TOKEN_PARENTHESIS_LEFT))
+      break;
+
+    if (!check_token (data, TOKEN_PARENTHESIS_RIGHT)) {
+      // FIXME: assignment expression
+      status = parse_value_statement_list (data, parse_assignment_expression,
+	  &arguments, &argument_statement, TOKEN_COMMA);
+      if (status != STATUS_OK) {
+	g_object_unref (*value);
+	*value = NULL;
+	if (*statement != NULL) {
+	  g_object_unref (*statement);
+	  *statement = NULL;
+	}
+	return FAIL_CHILD (status);
+      }
+
+      *statement =
+	vivi_compiler_combine_statements (2, *statement, argument_statement);
+
+      if (!check_token (data, TOKEN_PARENTHESIS_RIGHT)) {
+	g_object_unref (*value);
+	*value = NULL;
+	if (*statement != NULL) {
+	  g_object_unref (*statement);
+	  *statement = NULL;
+	}
+	return FAIL (TOKEN_PARENTHESIS_RIGHT);
+      }
+    } else {
+      arguments = NULL;
+    }
+
+    name = *value;
+    *value = vivi_compiler_function_call_new (name);
+    g_object_unref (name);
+
+    if (arguments != NULL) {
+      for (i = 0; arguments[i] != NULL; i++) {
+	vivi_code_function_call_add_argument (VIVI_CODE_FUNCTION_CALL (*value),
+	    arguments[i]);
+      }
+      free_value_list (arguments);
+    }
+  }
+
+  return STATUS_OK;
 }
 
 static ParseStatus
@@ -1242,73 +1346,112 @@ static ParseStatus
 parse_source_element (ParseData *data, ViviCodeStatement **statement);
 
 static ParseStatus
-parse_function_declaration (ParseData *data, ViviCodeStatement **statement)
+parse_function_definition (ParseData *data, ViviCodeValue **function,
+    ViviCodeValue **identifier, gboolean identifier_required)
 {
-  ViviCodeValue *function, *identifier;
+  ParseStatus status;
   ViviCodeValue **arguments;
   ViviCodeStatement *body;
-  ParseStatus status;
 
-  *statement = NULL;
+  *function = NULL;
+  *identifier = NULL;
 
-  identifier = NULL;
   arguments = NULL;
   body = NULL;
 
   if (!check_token (data, TOKEN_FUNCTION))
     return CANCEL (TOKEN_FUNCTION);
 
-  status = parse_identifier (data, &identifier);
-  if (status != STATUS_OK)
+  status = parse_identifier (data, identifier);
+  if (status == STATUS_FAIL ||
+      (identifier_required && status == STATUS_CANCEL))
     return FAIL_CHILD (status);
 
   if (!check_token (data, TOKEN_PARENTHESIS_LEFT)) {
-    g_object_unref (identifier);
+    g_object_unref (*identifier);
     return FAIL (TOKEN_PARENTHESIS_LEFT);
   }
 
   status = parse_value_list (data, parse_identifier, &arguments, TOKEN_COMMA);
-  if (status == STATUS_FAIL)
-    return status;
+  if (status == STATUS_FAIL) {
+    g_object_unref (*identifier);
+    return STATUS_FAIL;
+  }
 
   if (!check_token (data, TOKEN_PARENTHESIS_RIGHT)) {
-    g_object_unref (identifier);
+    g_object_unref (*identifier);
     free_value_list (arguments);
     return FAIL (TOKEN_PARENTHESIS_RIGHT);
   }
 
   if (!check_token (data, TOKEN_BRACE_LEFT)) {
-    g_object_unref (identifier);
+    g_object_unref (*identifier);
     free_value_list (arguments);
     return FAIL (TOKEN_BRACE_LEFT);
   }
 
   status = parse_statement_list (data, parse_source_element, &body, STATUS_OK);
   if (status == STATUS_FAIL) {
-    g_object_unref (identifier);
+    g_object_unref (*identifier);
     free_value_list (arguments);
-    return status;
+    return STATUS_FAIL;
   }
 
   if (!check_token (data, TOKEN_BRACE_RIGHT)) {
-    g_object_unref (identifier);
+    g_object_unref (*identifier);
     free_value_list (arguments);
     g_object_unref (body);
     return FAIL (TOKEN_BRACE_RIGHT);
   }
 
-  function = vivi_code_function_new ();
-  vivi_code_function_set_body (VIVI_CODE_FUNCTION (function), body);
-  *statement = vivi_compiler_assignment_new (VIVI_CODE_VALUE (identifier),
-      VIVI_CODE_VALUE (function));
-
-  g_object_unref (identifier);
+  *function = vivi_code_function_new ();
+  vivi_code_function_set_body (VIVI_CODE_FUNCTION (*function), body);
   free_value_list (arguments);
   g_object_unref (body);
 
   return STATUS_OK;
 }
 
+static ParseStatus
+parse_function_declaration (ParseData *data, ViviCodeStatement **statement)
+{
+  ParseStatus status;
+  ViviCodeValue *function, *identifier;
+
+  *statement = NULL;
+
+  status = parse_function_definition (data, &function, &identifier, TRUE);
+  if (status != STATUS_OK)
+    return status;
+
+  *statement = vivi_compiler_assignment_new (identifier, function);
+  g_object_unref (identifier);
+  g_object_unref (function);
+
+  return STATUS_OK;
+}
+
+static ParseStatus
+parse_function_expression (ParseData *data, ViviCodeValue **value,
+    ViviCodeStatement **statement)
+{
+  ParseStatus status;
+  ViviCodeValue *identifier;
+
+  *statement = NULL;
+
+  status = parse_function_definition (data, value, &identifier, FALSE);
+  if (status != STATUS_OK)
+    return status;
+
+  if (identifier != NULL) {
+    *statement = vivi_compiler_assignment_new (identifier, *value);
+    g_object_unref (identifier);
+  }
+
+  return STATUS_OK;
+}
+
 // top
 
 static ParseStatus
@@ -1387,6 +1530,52 @@ parse_statement_list (ParseData *data, ParseStatementFunction function,
 }
 
 static ParseStatus
+parse_value_statement_list (ParseData *data,
+    ParseValueStatementFunction function, ViviCodeValue ***list,
+    ViviCodeStatement **statement, guint separator)
+{
+  GPtrArray *array;
+  ViviCodeValue *value;
+  ViviCodeStatement *statement_one;
+  ParseStatus status;
+
+  g_assert (data != NULL);
+  g_assert (function != NULL);
+  g_assert (list != NULL);
+  g_assert (statement != NULL);
+
+  *list = NULL;
+  *statement = NULL;
+
+  status = function (data, &value, statement);
+  if (status != STATUS_OK)
+    return status;
+
+  array = g_ptr_array_new ();
+
+  do {
+    g_ptr_array_add (array, value);
+
+    if (separator != TOKEN_NONE && !check_token (data, separator))
+      break;
+
+    status = function (data, &value, &statement_one);
+    if (status != STATUS_OK) {
+      if (status == STATUS_FAIL || separator != TOKEN_NONE)
+	return FAIL_CHILD (status);
+    } else {
+      *statement =
+	vivi_compiler_combine_statements (2, *statement, statement_one);
+    }
+  } while (status == STATUS_OK);
+  g_ptr_array_add (array, NULL);
+
+  *list = (ViviCodeValue **)g_ptr_array_free (array, FALSE);
+
+  return STATUS_OK;
+}
+
+static ParseStatus
 parse_value_list (ParseData *data, ParseValueFunction function,
     ViviCodeValue ***list, guint separator)
 {
diff --git a/vivified/code/vivi_compiler_scanner.c b/vivified/code/vivi_compiler_scanner.c
index 8a35437..dcedc9d 100644
--- a/vivified/code/vivi_compiler_scanner.c
+++ b/vivified/code/vivi_compiler_scanner.c
@@ -159,6 +159,7 @@ static const struct {
   { TOKEN_TYPEOF, "typeof" },
   { TOKEN_VAR, "var" },
   { TOKEN_VOID, "void" },
+  { TOKEN_WHILE, "while" },
   { TOKEN_WITH, "with" },
 
   // reserved keywords
@@ -196,6 +197,8 @@ vivi_compiler_scanner_advance (ViviCompilerScanner *scanner)
     scanner->next_token = yylex ();
     scanner->next_value = yylval;
   }
+
+  g_print (":: %s\n", vivi_compiler_scanner_token_name (scanner->next_token));
 }
 
 ViviCompilerScanner *
diff --git a/vivified/code/vivi_compiler_scanner.h b/vivified/code/vivi_compiler_scanner.h
index cfd1453..c5c72f5 100644
--- a/vivified/code/vivi_compiler_scanner.h
+++ b/vivified/code/vivi_compiler_scanner.h
@@ -133,6 +133,7 @@ typedef enum {
   TOKEN_TYPEOF,
   TOKEN_VAR,
   TOKEN_VOID,
+  TOKEN_WHILE,
   TOKEN_WITH,
 
   // reserved keywords
diff --git a/vivified/code/vivi_compiler_scanner_lex.l b/vivified/code/vivi_compiler_scanner_lex.l
index 5585d7e..5dc0a1c 100644
--- a/vivified/code/vivi_compiler_scanner_lex.l
+++ b/vivified/code/vivi_compiler_scanner_lex.l
@@ -2,15 +2,19 @@
 #include "vivi_compiler_scanner_lex_include.h"
 %}
 
+%option			noyywrap
+
 digit			[0-9]
 identifier_start	[$_a-zA-Z]
 identifier_part		[$_a-zA-Z0-9]
+line_terminator		[\n\r]
 
 /* r'([1-9][0-9]*|0)(\.[0-9]*)?([eE][+-][0-9]+)? */
 /* '\.[0-9]+([eE][+-][0-9]+)?' */
 
 %%
 
+"//".*{line_terminator}	/* skip single line comments */
 [ \t\n\r]		/* skip whitespace */
 <<EOF>>			{ return TOKEN_EOF; }
 
@@ -102,6 +106,7 @@ identifier_part		[$_a-zA-Z0-9]
 "typeof"		{ return TOKEN_TYPEOF; }
 "var"			{ return TOKEN_VAR; }
 "void"			{ return TOKEN_VOID; }
+"while"			{ return TOKEN_WHILE; }
 "with"			{ return TOKEN_WITH; }
 
 "abstract"		{ return TOKEN_FUTURE; }
@@ -138,13 +143,13 @@ identifier_part		[$_a-zA-Z0-9]
 
 {digit}+		{ yylval.v_number = atoi(yytext);
 			  return TOKEN_NUMBER; }
+"\"".*"\""		{ yylval.v_string = g_strndup (yytext + 1, yyleng - 2);
+			  return TOKEN_STRING; }
 
 {identifier_start}({identifier_part})* {
-			  yylval.v_identifier = (char *)strdup(yytext);
+			  yylval.v_identifier = g_strdup (yytext);
 			  return TOKEN_IDENTIFIER; }
 
 .			{ printf("Unknown character [%c]\n",yytext[0]);
 			  return TOKEN_UNKNOWN; }
 %%
-
-int yywrap(void){return 1;}
commit fc1d36fee8e4904e1236f636f3249eea88e5bf67
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu Apr 3 23:33:53 2008 +0300

    Just some whitespace fixes to vivi_compiler.c

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index c71436c..266b3c7 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -48,7 +48,6 @@
 #include "vivi_compiler_empty_statement.h"
 #include "vivi_compiler_get_temporary.h"
 
-
 #include "vivi_code_text_printer.h"
 
 enum {
@@ -88,12 +87,13 @@ typedef struct {
 #define CANCEL(x) (data->expected = (x), STATUS_CANCEL)
 #define CANCEL_CUSTOM(x) (data->custom_error = (x), STATUS_CANCEL)
 
-typedef int (*ParseValueFunction) (ParseData *data, ViviCodeValue **value);
-typedef int (*ParseValueStatementFunction) (ParseData *data, ViviCodeValue **value, ViviCodeStatement **statement);
-typedef int (*ParseStatementFunction) (ParseData *data, ViviCodeStatement **statement);
+typedef ParseStatus (*ParseValueFunction) (ParseData *data, ViviCodeValue **value);
+typedef ParseStatus (*ParseValueStatementFunction) (ParseData *data, ViviCodeValue **value, ViviCodeStatement **statement);
+typedef ParseStatus (*ParseStatementFunction) (ParseData *data, ViviCodeStatement **statement);
 
 static ParseStatus
 parse_statement_list (ParseData *data, ParseStatementFunction function, ViviCodeStatement **statement, guint separator);
+
 static ParseStatus
 parse_value_list (ParseData *data, ParseValueFunction function,
     ViviCodeValue ***list, guint separator);
@@ -314,8 +314,8 @@ parse_property_name (ParseData *data, ViviCodeValue **value)
 }
 
 static ParseStatus
-parse_assignment_expression (ParseData *data,
-    ViviCodeValue **value, ViviCodeStatement **statement);
+parse_assignment_expression (ParseData *data, ViviCodeValue **value,
+    ViviCodeStatement **statement);
 
 static ParseStatus
 parse_object_literal (ParseData *data, ViviCodeValue **value,
@@ -393,8 +393,7 @@ parse_object_literal (ParseData *data, ViviCodeValue **value,
 // misc
 
 static ParseStatus
-parse_variable_declaration (ParseData *data,
-    ViviCodeStatement **statement)
+parse_variable_declaration (ParseData *data, ViviCodeStatement **statement)
 {
   ParseStatus status;
   ViviCodeValue *identifier, *value;
@@ -429,7 +428,8 @@ parse_variable_declaration (ParseData *data,
 // expression
 
 static ParseStatus
-parse_expression (ParseData *data, ViviCodeValue **value, ViviCodeStatement **statement);
+parse_expression (ParseData *data, ViviCodeValue **value,
+    ViviCodeStatement **statement);
 
 static ParseStatus
 parse_primary_expression (ParseData *data, ViviCodeValue **value,
@@ -691,10 +691,9 @@ typedef enum {
 } ParseOperatorPass;
 
 static ParseStatus
-parse_operator_expression (ParseData *data,
-    ViviCodeValue **value, ViviCodeStatement **statement,
-    const ViviCompilerScannerToken *tokens, ParseOperatorPass pass,
-    ParseValueStatementFunction next_parse_function)
+parse_operator_expression (ParseData *data, ViviCodeValue **value,
+    ViviCodeStatement **statement, const ViviCompilerScannerToken *tokens,
+    ParseOperatorPass pass, ParseValueStatementFunction next_parse_function)
 {
   ParseStatus status;
   int i;
@@ -756,8 +755,8 @@ parse_operator_expression (ParseData *data,
 }
 
 static ParseStatus
-parse_multiplicative_expression (ParseData *data,
-    ViviCodeValue **value, ViviCodeStatement **statement)
+parse_multiplicative_expression (ParseData *data, ViviCodeValue **value,
+    ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_MULTIPLY,
     TOKEN_DIVIDE, TOKEN_REMAINDER, TOKEN_NONE };
@@ -767,8 +766,8 @@ parse_multiplicative_expression (ParseData *data,
 }
 
 static ParseStatus
-parse_additive_expression (ParseData *data,
-    ViviCodeValue **value, ViviCodeStatement **statement)
+parse_additive_expression (ParseData *data, ViviCodeValue **value,
+    ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_PLUS, TOKEN_MINUS,
     TOKEN_NONE };
@@ -789,8 +788,8 @@ parse_shift_expression (ParseData *data, ViviCodeValue **value,
 }
 
 static ParseStatus
-parse_relational_expression (ParseData *data,
-    ViviCodeValue **value, ViviCodeStatement **statement)
+parse_relational_expression (ParseData *data, ViviCodeValue **value,
+    ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_LESS_THAN,
     TOKEN_GREATER_THAN, /*TOKEN_LESS_THAN_OR_EQUAL,
@@ -801,8 +800,8 @@ parse_relational_expression (ParseData *data,
 }
 
 static ParseStatus
-parse_equality_expression (ParseData *data,
-    ViviCodeValue **value, ViviCodeStatement **statement)
+parse_equality_expression (ParseData *data, ViviCodeValue **value,
+    ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_EQUAL,
     /*TOKEN_NOT_EQUAL,*/ TOKEN_STRICT_EQUAL, /*TOKEN_NOT_STRICT_EQUAL,*/
@@ -813,8 +812,8 @@ parse_equality_expression (ParseData *data,
 }
 
 static ParseStatus
-parse_bitwise_and_expression (ParseData *data,
-    ViviCodeValue **value, ViviCodeStatement **statement)
+parse_bitwise_and_expression (ParseData *data, ViviCodeValue **value,
+    ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_BITWISE_AND,
     TOKEN_NONE };
@@ -824,8 +823,8 @@ parse_bitwise_and_expression (ParseData *data,
 }
 
 static ParseStatus
-parse_bitwise_xor_expression (ParseData *data,
-    ViviCodeValue **value, ViviCodeStatement **statement)
+parse_bitwise_xor_expression (ParseData *data, ViviCodeValue **value,
+    ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_BITWISE_XOR,
     TOKEN_NONE };
@@ -835,8 +834,8 @@ parse_bitwise_xor_expression (ParseData *data,
 }
 
 static ParseStatus
-parse_bitwise_or_expression (ParseData *data,
-    ViviCodeValue **value, ViviCodeStatement **statement)
+parse_bitwise_or_expression (ParseData *data, ViviCodeValue **value,
+    ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_BITWISE_OR,
     TOKEN_NONE };
@@ -846,8 +845,8 @@ parse_bitwise_or_expression (ParseData *data,
 }
 
 static ParseStatus
-parse_logical_and_expression (ParseData *data,
-    ViviCodeValue **value, ViviCodeStatement **statement)
+parse_logical_and_expression (ParseData *data, ViviCodeValue **value,
+    ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_LOGICAL_AND,
     TOKEN_NONE };
@@ -857,8 +856,8 @@ parse_logical_and_expression (ParseData *data,
 }
 
 static ParseStatus
-parse_logical_or_expression (ParseData *data,
-    ViviCodeValue **value, ViviCodeStatement **statement)
+parse_logical_or_expression (ParseData *data, ViviCodeValue **value,
+    ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_LOGICAL_OR,
     TOKEN_NONE };
@@ -868,8 +867,8 @@ parse_logical_or_expression (ParseData *data,
 }
 
 static ParseStatus
-parse_conditional_expression (ParseData *data,
-    ViviCodeValue **value, ViviCodeStatement **statement)
+parse_conditional_expression (ParseData *data, ViviCodeValue **value,
+    ViviCodeStatement **statement)
 {
   ParseStatus status;
   //ViviCodeStatement *if_statement, *else_statement;
@@ -919,8 +918,8 @@ parse_conditional_expression (ParseData *data,
 }
 
 static ParseStatus
-parse_assignment_expression (ParseData *data,
-    ViviCodeValue **value, ViviCodeStatement **statement)
+parse_assignment_expression (ParseData *data, ViviCodeValue **value,
+    ViviCodeStatement **statement)
 {
   ParseStatus status;
   ViviCodeValue *right;
@@ -1034,8 +1033,7 @@ static ParseStatus
 parse_statement (ParseData *data, ViviCodeStatement **statement);
 
 static ParseStatus
-parse_if_statement (ParseData *data,
-    ViviCodeStatement **statement)
+parse_if_statement (ParseData *data, ViviCodeStatement **statement)
 {
   ParseStatus status;
   ViviCodeValue *condition;
@@ -1139,8 +1137,7 @@ parse_expression_statement (ParseData *data, ViviCodeStatement **statement)
 }
 
 static ParseStatus
-parse_empty_statement (ParseData *data,
-    ViviCodeStatement **statement)
+parse_empty_statement (ParseData *data, ViviCodeStatement **statement)
 {
   *statement = NULL;
 
@@ -1191,8 +1188,8 @@ parse_variable_statement (ParseData *data, ViviCodeStatement **statement)
   if (!check_token (data, TOKEN_VAR))
     return CANCEL (TOKEN_VAR);
 
-  status = parse_statement_list (data, parse_variable_declaration,
-      statement, TOKEN_COMMA);
+  status = parse_statement_list (data, parse_variable_declaration, statement,
+      TOKEN_COMMA);
   if (status != STATUS_OK)
     return FAIL (status);
 
@@ -1270,8 +1267,7 @@ parse_function_declaration (ParseData *data, ViviCodeStatement **statement)
     return FAIL (TOKEN_PARENTHESIS_LEFT);
   }
 
-  status =
-    parse_value_list (data, parse_identifier, &arguments, TOKEN_COMMA);
+  status = parse_value_list (data, parse_identifier, &arguments, TOKEN_COMMA);
   if (status == STATUS_FAIL)
     return status;
 
@@ -1287,8 +1283,7 @@ parse_function_declaration (ParseData *data, ViviCodeStatement **statement)
     return FAIL (TOKEN_BRACE_LEFT);
   }
 
-  status = parse_statement_list (data, parse_source_element, &body,
-      STATUS_OK);
+  status = parse_statement_list (data, parse_source_element, &body, STATUS_OK);
   if (status == STATUS_FAIL) {
     g_object_unref (identifier);
     free_value_list (arguments);
@@ -1337,8 +1332,8 @@ parse_program (ParseData *data, ViviCodeStatement **statement)
 
   *statement = NULL;
 
-  status = parse_statement_list (data, parse_source_element, statement,
-      STATUS_OK);
+  status =
+    parse_statement_list (data, parse_source_element, statement, STATUS_OK);
   if (status != STATUS_OK)
     return FAIL_CHILD (status);
 
@@ -1355,9 +1350,8 @@ parse_program (ParseData *data, ViviCodeStatement **statement)
 // parsing
 
 static ParseStatus
-parse_statement_list (ParseData *data,
-    ParseStatementFunction function, ViviCodeStatement **block,
-    guint separator)
+parse_statement_list (ParseData *data, ParseStatementFunction function,
+    ViviCodeStatement **block, guint separator)
 {
   ViviCodeStatement *statement;
   ParseStatus status;
commit 397b78c64e404af861dbb317efecce3040fae66e
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu Apr 3 23:26:08 2008 +0300

    Oops, fix parsing of multiple same level operators

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 04582f8..c71436c 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -709,7 +709,7 @@ parse_operator_expression (ParseData *data,
     return status;
 
   for (i = 0; tokens[i] != STATUS_OK; i++) {
-    if (check_token (data, tokens[i])) {
+    while (check_token (data, tokens[i])) {
       status = next_parse_function (data, &right, &statement_right);
       if (status != STATUS_OK) {
 	g_object_unref (*value);
commit 841b25656ac1d507a0d988e3a7d8555a592fda63
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu Apr 3 23:20:55 2008 +0300

    Fix an error in expression parsing

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 2075ce1..04582f8 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -1007,7 +1007,7 @@ parse_expression (ParseData *data, ViviCodeValue **value,
   if (status != STATUS_OK)
     return status;
 
-  do {
+  while (TRUE) {
     *statement =
       vivi_compiler_combine_statements (2, *statement, statement_one);
 
@@ -1016,14 +1016,14 @@ parse_expression (ParseData *data, ViviCodeValue **value,
 
     statement_one = NULL;
     status = parse_assignment_expression (data, value, &statement_one);
-    if (status == STATUS_FAIL) {
+    if (status != STATUS_OK) {
       g_object_unref (*value);
       *value = NULL;
       g_object_unref (*statement);
       *statement = NULL;
-      return status;
+      return FAIL_CHILD (status);
     }
-  } while (status == STATUS_OK);
+  }
 
   return STATUS_OK;
 }
commit 60345df480f0ca6a256133dd93bee30614a3e44a
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu Apr 3 23:10:24 2008 +0300

    Compiler: Redo the error handling

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index d4c5aad..2075ce1 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -60,7 +60,7 @@ enum {
 };
 
 static const struct {
-  int				token;
+  guint				token;
   const char *			name;
 } error_names[] = {
   { ERROR_TOKEN_LITERAL, "LITERAL" },
@@ -71,27 +71,42 @@ static const struct {
   { TOKEN_LAST, NULL }
 };
 
-#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);
-
-static int
-parse_statement_list (ViviCompilerScanner *scanner, ParseStatementFunction function, ViviCodeStatement **statement, guint separator);
-static int
-parse_value_list (ViviCompilerScanner *scanner, ParseValueFunction function,
+typedef enum {
+  STATUS_CANCEL = -1,
+  STATUS_OK = 0,
+  STATUS_FAIL = 1
+} ParseStatus;
+
+typedef struct {
+  ViviCompilerScanner *		scanner;
+  guint				expected;
+  const char *			custom_error;
+} ParseData;
+
+#define FAIL(x) (data->expected = (x), STATUS_FAIL)
+#define FAIL_CHILD(x) STATUS_FAIL
+#define CANCEL(x) (data->expected = (x), STATUS_CANCEL)
+#define CANCEL_CUSTOM(x) (data->custom_error = (x), STATUS_CANCEL)
+
+typedef int (*ParseValueFunction) (ParseData *data, ViviCodeValue **value);
+typedef int (*ParseValueStatementFunction) (ParseData *data, ViviCodeValue **value, ViviCodeStatement **statement);
+typedef int (*ParseStatementFunction) (ParseData *data, ViviCodeStatement **statement);
+
+static ParseStatus
+parse_statement_list (ParseData *data, ParseStatementFunction function, ViviCodeStatement **statement, guint separator);
+static ParseStatus
+parse_value_list (ParseData *data, ParseValueFunction function,
     ViviCodeValue ***list, guint separator);
 
 // helpers
 
 static gboolean
-check_token (ViviCompilerScanner *scanner, ViviCompilerScannerToken token)
+check_token (ParseData *data, ViviCompilerScannerToken token)
 {
-  vivi_compiler_scanner_peek_next_token (scanner);
-  if (scanner->next_token != token)
+  vivi_compiler_scanner_peek_next_token (data->scanner);
+  if (data->scanner->next_token != token)
     return FALSE;
-  vivi_compiler_scanner_get_next_token (scanner);
+  vivi_compiler_scanner_get_next_token (data->scanner);
   return TRUE;
 }
 
@@ -190,58 +205,59 @@ vivi_compiler_get_new (ViviCodeValue *from, ViviCodeValue *name)
 
 // values
 
-static int
-parse_null_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
+static ParseStatus
+parse_null_literal (ParseData *data, ViviCodeValue **value)
 {
   *value = NULL;
 
-  if (!check_token (scanner, TOKEN_NULL))
-    return -TOKEN_NULL;
+  if (!check_token (data, TOKEN_NULL))
+    return CANCEL (TOKEN_NULL);
 
   *value = vivi_code_constant_new_null ();
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
-static int
-parse_boolean_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
+static ParseStatus
+parse_boolean_literal (ParseData *data, ViviCodeValue **value)
 {
   *value = NULL;
 
-  if (!check_token (scanner, TOKEN_BOOLEAN))
-    return -TOKEN_BOOLEAN;
+  if (!check_token (data, TOKEN_BOOLEAN))
+    return CANCEL (TOKEN_BOOLEAN);
 
-  *value = vivi_code_constant_new_boolean (scanner->value.v_boolean);
-  return TOKEN_NONE;
+  *value = vivi_code_constant_new_boolean (data->scanner->value.v_boolean);
+  return STATUS_OK;
 }
 
-static int
-parse_numeric_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
+static ParseStatus
+parse_numeric_literal (ParseData *data, ViviCodeValue **value)
 {
   *value = NULL;
 
-  if (!check_token (scanner, TOKEN_NUMBER))
-    return -TOKEN_NUMBER;
+  if (!check_token (data, TOKEN_NUMBER))
+    return CANCEL (TOKEN_NUMBER);
 
-  *value = vivi_code_constant_new_number (scanner->value.v_number);
-  return TOKEN_NONE;
+  *value = vivi_code_constant_new_number (data->scanner->value.v_number);
+  return STATUS_OK;
 }
 
-static int
-parse_string_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
+static ParseStatus
+parse_string_literal (ParseData *data, ViviCodeValue **value)
 {
   *value = NULL;
 
-  if (!check_token (scanner, TOKEN_STRING))
-    return -TOKEN_STRING;
+  if (!check_token (data, TOKEN_STRING))
+    return CANCEL (TOKEN_STRING);
 
-  *value = vivi_code_constant_new_string (scanner->value.v_string);
-  return TOKEN_NONE;
+  *value = vivi_code_constant_new_string (data->scanner->value.v_string);
+  return STATUS_OK;
 }
 
-static int
-parse_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
+static ParseStatus
+parse_literal (ParseData *data, ViviCodeValue **value)
 {
-  int i, expected;
+  ParseStatus status;
+  int i;
   ParseValueFunction functions[] = {
     parse_null_literal,
     parse_boolean_literal,
@@ -253,31 +269,32 @@ parse_literal (ViviCompilerScanner *scanner, ViviCodeValue **value)
   *value = NULL;
 
   for (i = 0; functions[i] != NULL; i++) {
-    expected = functions[i] (scanner, value);
-    if (expected >= 0)
-      return expected;
+    status = functions[i] (data, value);
+    if (status != STATUS_CANCEL)
+      return status;
   }
 
-  return -ERROR_TOKEN_LITERAL;
+  return CANCEL (ERROR_TOKEN_LITERAL);
 }
 
-static int
-parse_identifier (ViviCompilerScanner *scanner, ViviCodeValue **value)
+static ParseStatus
+parse_identifier (ParseData *data, ViviCodeValue **value)
 {
   *value = NULL;
 
-  if (!check_token (scanner, TOKEN_IDENTIFIER))
-    return -TOKEN_IDENTIFIER;
+  if (!check_token (data, TOKEN_IDENTIFIER))
+    return CANCEL (TOKEN_IDENTIFIER);
 
-  *value = vivi_code_get_new_name (scanner->value.v_identifier);
+  *value = vivi_code_get_new_name (data->scanner->value.v_identifier);
 
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
-static int
-parse_property_name (ViviCompilerScanner *scanner, ViviCodeValue **value)
+static ParseStatus
+parse_property_name (ParseData *data, ViviCodeValue **value)
 {
-  int i, expected;
+  ParseStatus status;
+  int i;
   ParseValueFunction functions[] = {
     parse_identifier,
     parse_string_literal,
@@ -288,68 +305,68 @@ parse_property_name (ViviCompilerScanner *scanner, ViviCodeValue **value)
   *value = NULL;
 
   for (i = 0; functions[i] != NULL; i++) {
-    expected = functions[i] (scanner, value);
-    if (expected >= 0)
-      return expected;
+    status = functions[i] (data, value);
+    if (status != STATUS_CANCEL)
+      return status;
   }
 
-  return -ERROR_TOKEN_PROPERTY_NAME;
+  return CANCEL (ERROR_TOKEN_PROPERTY_NAME);
 }
 
-static int
-parse_assignment_expression (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_assignment_expression (ParseData *data,
     ViviCodeValue **value, ViviCodeStatement **statement);
 
-static int
-parse_object_literal (ViviCompilerScanner *scanner, ViviCodeValue **value,
+static ParseStatus
+parse_object_literal (ParseData *data, ViviCodeValue **value,
     ViviCodeStatement **statement)
 {
-  int expected;
+  ParseStatus status;
 
   *value = NULL;
   *statement = NULL;
 
-  if (!check_token (scanner, TOKEN_BRACE_LEFT))
-    return -TOKEN_BRACE_LEFT;
+  if (!check_token (data, TOKEN_BRACE_LEFT))
+    return CANCEL (TOKEN_BRACE_LEFT);
 
   *value = vivi_code_init_object_new ();
 
-  if (!check_token (scanner, TOKEN_BRACE_RIGHT)) {
+  if (!check_token (data, TOKEN_BRACE_RIGHT)) {
     do {
       ViviCodeValue *property, *initializer;
       ViviCodeStatement *statement_new;
 
-      expected = parse_property_name (scanner, &property);
-      if (expected != TOKEN_NONE) {
+      status = parse_property_name (data, &property);
+      if (status != STATUS_OK) {
 	g_object_unref (*value);
 	*value = NULL;
 	if (*statement != NULL) {
 	  g_object_unref (*statement);
 	  *statement = NULL;
 	}
-	return FAIL (expected);
+	return FAIL_CHILD (status);
       }
 
-      if (!check_token (scanner, TOKEN_COLON)) {
+      if (!check_token (data, TOKEN_COLON)) {
 	g_object_unref (*value);
 	*value = NULL;
 	if (*statement != NULL) {
 	  g_object_unref (*statement);
 	  *statement = NULL;
 	}
-	return TOKEN_COLON;
+	return FAIL (TOKEN_COLON);
       }
 
-      expected = parse_assignment_expression (scanner, &initializer,
+      status = parse_assignment_expression (data, &initializer,
 	  &statement_new);
-      if (expected != TOKEN_NONE) {
+      if (status != STATUS_OK) {
 	g_object_unref (*value);
 	*value = NULL;
 	if (*statement != NULL) {
 	  g_object_unref (*statement);
 	  *statement = NULL;
 	}
-	return FAIL (expected);
+	return FAIL_CHILD (status);
       }
 
       *statement =
@@ -357,43 +374,43 @@ parse_object_literal (ViviCompilerScanner *scanner, ViviCodeValue **value,
 
       vivi_code_init_object_add_variable (VIVI_CODE_INIT_OBJECT (*value),
 	  property, initializer);
-    } while (check_token (scanner, TOKEN_COMMA));
+    } while (check_token (data, TOKEN_COMMA));
   }
 
-  if (!check_token (scanner, TOKEN_BRACE_RIGHT)) {
+  if (!check_token (data, TOKEN_BRACE_RIGHT)) {
     g_object_unref (*value);
     *value = NULL;
     if (*statement != NULL) {
       g_object_unref (*statement);
       *statement = NULL;
     }
-    return TOKEN_BRACE_RIGHT;
+    return FAIL (TOKEN_BRACE_RIGHT);
   }
 
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
 // misc
 
-static int
-parse_variable_declaration (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_variable_declaration (ParseData *data,
     ViviCodeStatement **statement)
 {
-  int expected;
+  ParseStatus status;
   ViviCodeValue *identifier, *value;
   ViviCodeStatement *assignment, *statement_right;
 
   *statement = NULL;
 
-  expected = parse_identifier (scanner, &identifier);
-  if (expected != TOKEN_NONE)
-    return expected;
+  status = parse_identifier (data, &identifier);
+  if (status != STATUS_OK)
+    return status;
 
-  if (check_token (scanner, TOKEN_ASSIGN)) {
-    expected = parse_assignment_expression (scanner, &value, &statement_right);
-    if (expected != TOKEN_NONE) {
+  if (check_token (data, TOKEN_ASSIGN)) {
+    status = parse_assignment_expression (data, &value, &statement_right);
+    if (status != STATUS_OK) {
       g_object_unref (identifier);
-      return FAIL (expected);
+      return FAIL_CHILD (status);
     }
   } else {
     value = vivi_code_constant_new_undefined ();
@@ -406,19 +423,20 @@ parse_variable_declaration (ViviCompilerScanner *scanner,
   *statement =
     vivi_compiler_combine_statements (2, statement_right, assignment);
 
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
 // expression
 
-static int
-parse_expression (ViviCompilerScanner *scanner, ViviCodeValue **value, ViviCodeStatement **statement);
+static ParseStatus
+parse_expression (ParseData *data, ViviCodeValue **value, ViviCodeStatement **statement);
 
-static int
-parse_primary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
+static ParseStatus
+parse_primary_expression (ParseData *data, ViviCodeValue **value,
     ViviCodeStatement **statement)
 {
-  int i, expected;
+  ParseStatus status;
+  int i;
   ParseValueFunction functions[] = {
     parse_identifier,
     parse_literal,
@@ -429,42 +447,42 @@ parse_primary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
   *value = NULL;
   *statement = NULL;
 
-  if (check_token (scanner, TOKEN_THIS)) {
+  if (check_token (data, TOKEN_THIS)) {
     *value = vivi_code_get_new_name ("this");
-    return TOKEN_NONE;
+    return STATUS_OK;
   }
 
-  if (check_token (scanner, TOKEN_PARENTHESIS_LEFT)) {
-    expected = parse_expression (scanner, value, statement);
-    if (expected != TOKEN_NONE)
-      return FAIL (expected);
-    if (!check_token (scanner, TOKEN_PARENTHESIS_RIGHT)) {
+  if (check_token (data, TOKEN_PARENTHESIS_LEFT)) {
+    status = parse_expression (data, value, statement);
+    if (status != STATUS_OK)
+      return FAIL_CHILD (status);
+    if (!check_token (data, TOKEN_PARENTHESIS_RIGHT)) {
       g_object_unref (*value);
       *value = NULL;
-      return TOKEN_PARENTHESIS_RIGHT;
+      return FAIL (TOKEN_PARENTHESIS_RIGHT);
     }
-    return TOKEN_NONE;
+    return STATUS_OK;
   }
 
 
-  expected = parse_object_literal (scanner, value, statement);
-  if (expected == TOKEN_NONE || expected >= 0)
-    return expected;
+  status = parse_object_literal (data, value, statement);
+  if (status != STATUS_CANCEL)
+    return status;
 
   for (i = 0; functions[i] != NULL; i++) {
-    expected = functions[i] (scanner, value);
-    if (expected >= 0)
-      return expected;
+    status = functions[i] (data, value);
+    if (status != STATUS_CANCEL)
+      return status;
   }
 
-  return -ERROR_TOKEN_PRIMARY_EXPRESSION;
+  return CANCEL (ERROR_TOKEN_PRIMARY_EXPRESSION);
 }
 
-static int
-parse_member_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
+static ParseStatus
+parse_member_expression (ParseData *data, ViviCodeValue **value,
     ViviCodeStatement **statement)
 {
-  int expected;
+  ParseStatus status;
   ViviCodeValue *member;
   ViviCodeStatement *statement_member;
 
@@ -473,46 +491,46 @@ parse_member_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
 
   // TODO: new MemberExpression Arguments
 
-  expected = parse_primary_expression (scanner, value, statement);
-  //if (expected == STATUS_CANCEL)
-  //  expected = parse_function_expression (scanner, value);
+  status = parse_primary_expression (data, value, statement);
+  //if (status == STATUS_CANCEL)
+  //  status = parse_function_expression (data, value);
 
-  if (expected != TOKEN_NONE)
-    return expected;
+  if (status != STATUS_OK)
+    return status;
 
   do {
     ViviCodeValue *tmp;
 
-    if (check_token (scanner, TOKEN_BRACKET_LEFT)) {
-      expected = parse_expression (scanner, &member, &statement_member);
-      if (expected != TOKEN_NONE) {
+    if (check_token (data, TOKEN_BRACKET_LEFT)) {
+      status = parse_expression (data, &member, &statement_member);
+      if (status != STATUS_OK) {
 	g_object_unref (*value);
 	*value = NULL;
 	if (*statement != NULL) {
 	  g_object_unref (*statement);
 	  *statement = NULL;
 	}
-	return FAIL (expected);
+	return FAIL_CHILD (status);
       }
 
       *statement = vivi_compiler_combine_statements (2, *statement,
 	  statement_member);
 
-      if (!check_token (scanner, TOKEN_BRACKET_RIGHT)) {
+      if (!check_token (data, TOKEN_BRACKET_RIGHT)) {
 	g_object_unref (*value);
 	*value = NULL;
 	if (*statement != NULL) {
 	  g_object_unref (*statement);
 	  *statement = NULL;
 	}
-	return TOKEN_BRACKET_RIGHT;
+	return FAIL (TOKEN_BRACKET_RIGHT);
       }
-    } else if (check_token (scanner, TOKEN_DOT)) {
-      expected = parse_identifier (scanner, &member);
-      if (expected != TOKEN_NONE)
-	return FAIL (expected);
+    } else if (check_token (data, TOKEN_DOT)) {
+      status = parse_identifier (data, &member);
+      if (status != STATUS_OK)
+	return FAIL_CHILD (status);
     } else {
-      return TOKEN_NONE;
+      return STATUS_OK;
     }
 
     tmp = *value;
@@ -524,19 +542,19 @@ parse_member_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
   g_assert_not_reached ();
 }
 
-static int
-parse_new_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
+static ParseStatus
+parse_new_expression (ParseData *data, ViviCodeValue **value,
     ViviCodeStatement **statement)
 {
-  int expected;
+  ParseStatus status;
 
   *value = NULL;
   *statement = NULL;
 
-  if (check_token (scanner, TOKEN_NEW)) {
-    expected = parse_new_expression (scanner, value, statement);
-    if (expected != TOKEN_NONE)
-      return FAIL (expected);
+  if (check_token (data, TOKEN_NEW)) {
+    status = parse_new_expression (data, value, statement);
+    if (status != STATUS_OK)
+      return FAIL_CHILD (status);
     if (!VIVI_IS_CODE_FUNCTION_CALL (*value)) {
       ViviCodeValue *tmp = VIVI_CODE_VALUE (*value);
       *value = vivi_code_function_call_new (NULL, tmp);
@@ -544,56 +562,54 @@ parse_new_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
     }
     vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*value),
 	TRUE);
-    return TOKEN_NONE;
+    return STATUS_OK;
   } else {
-    return parse_member_expression (scanner, value, statement);
+    return parse_member_expression (data, value, statement);
   }
 }
 
-static int
-parse_left_hand_side_expression (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_left_hand_side_expression (ParseData *data,
     ViviCodeValue **value, ViviCodeStatement **statement)
 {
-  int expected;
+  ParseStatus status;
 
   *value = NULL;
 
-  expected = parse_new_expression (scanner, value, statement);
-  //if (expected == STATUS_CANCEL)
-  //  expected = parse_call_expression (scanner, value);
+  status = parse_new_expression (data, value, statement);
+  //if (status == STATUS_CANCEL)
+  //  status = parse_call_expression (data, value);
 
-  return expected;
+  return status;
 }
 
-static int
-parse_postfix_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
+static ParseStatus
+parse_postfix_expression (ParseData *data, ViviCodeValue **value,
     ViviCodeStatement **statement)
 {
-  int expected;
+  ParseStatus status;
   ViviCodeValue *operation, *one, *temporary;
   const char *operator;
 
   *value = NULL;
   *statement = NULL;
 
-  expected = parse_left_hand_side_expression (scanner, value, statement);
-  if (expected != TOKEN_NONE)
-    return expected;
+  status = parse_left_hand_side_expression (data, value, statement);
+  if (status != STATUS_OK)
+    return status;
 
   // FIXME: Don't allow new line here
 
-  if (check_token (scanner, TOKEN_INCREASE)) {
+  if (check_token (data, TOKEN_INCREASE)) {
     operator = "+";
-  } else if (check_token (scanner, TOKEN_DESCREASE)) {
+  } else if (check_token (data, TOKEN_DESCREASE)) {
     operator = "-";
   } else {
-    return TOKEN_NONE;
+    return STATUS_OK;
   }
 
-  if (!VIVI_IS_CODE_GET (*value)) {
-    g_printerr ("Invalid INCREASE/DECREASE\n");
-    return -scanner->token;
-  }
+  if (!VIVI_IS_CODE_GET (*value))
+    return CANCEL_CUSTOM ("INCREASE/DECREASE not allowed here");
 
   one = vivi_code_constant_new_number (1);
   operation = vivi_code_binary_new_name (*value, one, operator);
@@ -608,14 +624,14 @@ parse_postfix_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
   g_object_unref (*value);
   *value = temporary;
 
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
-static int
-parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
+static ParseStatus
+parse_unary_expression (ParseData *data, ViviCodeValue **value,
     ViviCodeStatement **statement)
 {
-  int expected;
+  ParseStatus status;
   ViviCodeValue *tmp, *one;
   const char *operator;
 
@@ -623,8 +639,8 @@ parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
 
   operator = NULL;
 
-  vivi_compiler_scanner_peek_next_token (scanner);
-  switch ((int)scanner->next_token) {
+  vivi_compiler_scanner_peek_next_token (data->scanner);
+  switch ((guint)data->scanner->next_token) {
     /*case TOKEN_DELETE:
     case TOKEN_VOID:
     case TOKEN_TYPEOF:*/
@@ -634,15 +650,13 @@ parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
     case TOKEN_DESCREASE:
       if (!operator) operator = "-";
 
-      vivi_compiler_scanner_get_next_token (scanner);
-      expected = parse_unary_expression (scanner, value, statement);
-      if (expected != TOKEN_NONE)
-	return FAIL (expected);
+      vivi_compiler_scanner_get_next_token (data->scanner);
+      status = parse_unary_expression (data, value, statement);
+      if (status != STATUS_OK)
+	return FAIL_CHILD (status);
 
-      if (!VIVI_IS_CODE_GET (*value)) {
-	g_printerr ("Invalid INCREASE/DECREASE\n");
-	return -scanner->token;
-      }
+      if (!VIVI_IS_CODE_GET (*value))
+	return CANCEL_CUSTOM ("INCREASE/DECREASE not allowed here");
 
       one = vivi_code_constant_new_number (1);
       tmp = vivi_code_binary_new_name (*value, one, operator);
@@ -652,21 +666,21 @@ parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
 	  vivi_compiler_assignment_new (*value, tmp));
       g_object_unref (tmp);
 
-      return TOKEN_NONE;
+      return STATUS_OK;
     /*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, statement);
-      if (expected != TOKEN_NONE)
-	return FAIL (expected);
+      vivi_compiler_scanner_get_next_token (data->scanner);
+      status = parse_unary_expression (data, value, statement);
+      if (status != STATUS_OK)
+	return FAIL_CHILD (status);
       tmp = VIVI_CODE_VALUE (*value);
       *value = vivi_code_unary_new (tmp, '!');
       g_object_unref (tmp);
-      return TOKEN_NONE;
+      return STATUS_OK;
     default:
-      return parse_postfix_expression (scanner, value, statement);
+      return parse_postfix_expression (data, value, statement);
   }
 }
 
@@ -676,30 +690,31 @@ typedef enum {
   PASS_LOGICAL_AND
 } ParseOperatorPass;
 
-static int
-parse_operator_expression (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_operator_expression (ParseData *data,
     ViviCodeValue **value, ViviCodeStatement **statement,
     const ViviCompilerScannerToken *tokens, ParseOperatorPass pass,
     ParseValueStatementFunction next_parse_function)
 {
-  int expected, i;
+  ParseStatus status;
+  int i;
   ViviCodeValue *left, *right;
   ViviCodeStatement *statement_right;
 
   *value = NULL;
   *statement = NULL;
 
-  expected = next_parse_function (scanner, value, statement);
-  if (expected != TOKEN_NONE)
-    return expected;
+  status = next_parse_function (data, value, statement);
+  if (status != STATUS_OK)
+    return status;
 
-  for (i = 0; tokens[i] != TOKEN_NONE; i++) {
-    if (check_token (scanner, tokens[i])) {
-      expected = next_parse_function (scanner, &right, &statement_right);
-      if (expected != TOKEN_NONE) {
+  for (i = 0; tokens[i] != STATUS_OK; i++) {
+    if (check_token (data, tokens[i])) {
+      status = next_parse_function (data, &right, &statement_right);
+      if (status != STATUS_OK) {
 	g_object_unref (*value);
 	*value = NULL;
-	return FAIL (expected);
+	return FAIL_CHILD (status);
       }
 
       if (statement_right != NULL) {
@@ -737,158 +752,158 @@ parse_operator_expression (ViviCompilerScanner *scanner,
     };
   }
 
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
-static int
-parse_multiplicative_expression (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_multiplicative_expression (ParseData *data,
     ViviCodeValue **value, ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_MULTIPLY,
     TOKEN_DIVIDE, TOKEN_REMAINDER, TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, statement, tokens,
+  return parse_operator_expression (data, value, statement, tokens,
       PASS_ALWAYS, parse_unary_expression);
 }
 
-static int
-parse_additive_expression (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_additive_expression (ParseData *data,
     ViviCodeValue **value, ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_PLUS, TOKEN_MINUS,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, statement, tokens,
+  return parse_operator_expression (data, value, statement, tokens,
       PASS_ALWAYS, parse_multiplicative_expression);
 }
 
-static int
-parse_shift_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
+static ParseStatus
+parse_shift_expression (ParseData *data, ViviCodeValue **value,
     ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_SHIFT_LEFT,
     TOKEN_SHIFT_RIGHT, TOKEN_SHIFT_RIGHT_UNSIGNED, TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, statement, tokens,
+  return parse_operator_expression (data, value, statement, tokens,
       PASS_ALWAYS, parse_additive_expression);
 }
 
-static int
-parse_relational_expression (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_relational_expression (ParseData *data,
     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, statement, tokens,
+  return parse_operator_expression (data, value, statement, tokens,
       PASS_ALWAYS, parse_shift_expression);
 }
 
-static int
-parse_equality_expression (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_equality_expression (ParseData *data,
     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, statement, tokens,
+  return parse_operator_expression (data, value, statement, tokens,
       PASS_ALWAYS, parse_relational_expression);
 }
 
-static int
-parse_bitwise_and_expression (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_bitwise_and_expression (ParseData *data,
     ViviCodeValue **value, ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_BITWISE_AND,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, statement, tokens,
+  return parse_operator_expression (data, value, statement, tokens,
       PASS_ALWAYS, parse_equality_expression);
 }
 
-static int
-parse_bitwise_xor_expression (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_bitwise_xor_expression (ParseData *data,
     ViviCodeValue **value, ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_BITWISE_XOR,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, statement, tokens,
+  return parse_operator_expression (data, value, statement, tokens,
       PASS_ALWAYS, parse_bitwise_and_expression);
 }
 
-static int
-parse_bitwise_or_expression (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_bitwise_or_expression (ParseData *data,
     ViviCodeValue **value, ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_BITWISE_OR,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, statement, tokens,
+  return parse_operator_expression (data, value, statement, tokens,
       PASS_ALWAYS, parse_bitwise_xor_expression);
 }
 
-static int
-parse_logical_and_expression (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_logical_and_expression (ParseData *data,
     ViviCodeValue **value, ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_LOGICAL_AND,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, statement, tokens,
+  return parse_operator_expression (data, value, statement, tokens,
       PASS_LOGICAL_AND, parse_bitwise_or_expression);
 }
 
-static int
-parse_logical_or_expression (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_logical_or_expression (ParseData *data,
     ViviCodeValue **value, ViviCodeStatement **statement)
 {
   static const ViviCompilerScannerToken tokens[] = { TOKEN_LOGICAL_OR,
     TOKEN_NONE };
 
-  return parse_operator_expression (scanner, value, statement, tokens,
+  return parse_operator_expression (data, value, statement, tokens,
       PASS_LOGICAL_OR, parse_logical_and_expression);
 }
 
-static int
-parse_conditional_expression (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_conditional_expression (ParseData *data,
     ViviCodeValue **value, ViviCodeStatement **statement)
 {
-  int expected;
+  ParseStatus status;
   //ViviCodeStatement *if_statement, *else_statement;
 
   *value = NULL;
 
-  expected = parse_logical_or_expression (scanner, value, statement);
-  if (expected != TOKEN_NONE)
-    return expected;
+  status = parse_logical_or_expression (data, value, statement);
+  if (status != STATUS_OK)
+    return status;
 
 #if 0
-  if (!check_token (scanner, TOKEN_QUESTION_MARK)) {
+  if (!check_token (data, TOKEN_QUESTION_MARK)) {
     *statement = vivi_code_value_statement_new (VIVI_CODE_VALUE (value));
     g_object_unref (value);
-    return TOKEN_NONE;
+    return STATUS_OK;
   }
 
-  expected = parse_assignment_expression (scanner, &if_statement);
-  if (expected != TOKEN_NONE) {
+  status = parse_assignment_expression (data, &if_statement);
+  if (status != STATUS_OK) {
     g_object_unref (value);
-    return FAIL (expected);
+    return FAIL (status);
   }
 
-  if (!check_token (scanner, TOKEN_COLON)) {
+  if (!check_token (data, TOKEN_COLON)) {
     g_object_unref (value);
     g_object_unref (if_statement);
     return TOKEN_COLON;
   }
 
-  expected = parse_assignment_expression (scanner, &else_statement);
-  if (expected != TOKEN_NONE) {
+  status = parse_assignment_expression (data, &else_statement);
+  if (status != STATUS_OK) {
     g_object_unref (value);
     g_object_unref (if_statement);
-    return FAIL (expected);
+    return FAIL (status);
   }
 
   *statement = vivi_code_if_new (value);
@@ -900,14 +915,14 @@ parse_conditional_expression (ViviCompilerScanner *scanner,
   g_object_unref (else_statement);
 #endif
 
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
-static int
-parse_assignment_expression (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_assignment_expression (ParseData *data,
     ViviCodeValue **value, ViviCodeStatement **statement)
 {
-  int expected;
+  ParseStatus status;
   ViviCodeValue *right;
   ViviCodeStatement *assignment, *statement_right;
   const char *operator;
@@ -915,17 +930,17 @@ parse_assignment_expression (ViviCompilerScanner *scanner,
   *value = NULL;
   *statement = NULL;
 
-  expected = parse_conditional_expression (scanner, value, statement);
-  if (expected != TOKEN_NONE)
-    return expected;
+  status = parse_conditional_expression (data, value, statement);
+  if (status != STATUS_OK)
+    return status;
 
   if (!VIVI_IS_CODE_GET (*value))
-    return TOKEN_NONE;
+    return STATUS_OK;
 
   operator = NULL;
 
-  vivi_compiler_scanner_peek_next_token (scanner);
-  switch ((int)scanner->next_token) {
+  vivi_compiler_scanner_peek_next_token (data->scanner);
+  switch ((int)data->scanner->next_token) {
     case TOKEN_ASSIGN_MULTIPLY:
       if (operator == NULL) operator = "*";
     case TOKEN_ASSIGN_DIVIDE:
@@ -949,13 +964,13 @@ parse_assignment_expression (ViviCompilerScanner *scanner,
     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,
+      vivi_compiler_scanner_get_next_token (data->scanner);
+      status = parse_assignment_expression (data, &right,
 	  &statement_right);
-      if (expected != TOKEN_NONE) {
+      if (status != STATUS_OK) {
 	g_object_unref (*value);
 	*value = NULL;
-	return FAIL (expected);
+	return FAIL_CHILD (status);
       }
 
       if (operator != NULL) {
@@ -971,102 +986,102 @@ parse_assignment_expression (ViviCompilerScanner *scanner,
 
       break;
     default:
-      return TOKEN_NONE;
+      return STATUS_OK;
   }
 
 
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
-static int
-parse_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
+static ParseStatus
+parse_expression (ParseData *data, ViviCodeValue **value,
     ViviCodeStatement **statement)
 {
   ViviCodeStatement *statement_one;
-  int expected;
+  ParseStatus status;
 
   *statement = NULL;
   statement_one = NULL;
 
-  expected = parse_assignment_expression (scanner, value, &statement_one);
-  if (expected != TOKEN_NONE)
-    return expected;
+  status = parse_assignment_expression (data, value, &statement_one);
+  if (status != STATUS_OK)
+    return status;
 
   do {
     *statement =
       vivi_compiler_combine_statements (2, *statement, statement_one);
 
-    if (!check_token (scanner, TOKEN_COMMA))
+    if (!check_token (data, TOKEN_COMMA))
       break;
 
     statement_one = NULL;
-    expected = parse_assignment_expression (scanner, value, &statement_one);
-    if (expected != TOKEN_NONE && expected >= 0) {
+    status = parse_assignment_expression (data, value, &statement_one);
+    if (status == STATUS_FAIL) {
       g_object_unref (*value);
       *value = NULL;
       g_object_unref (*statement);
       *statement = NULL;
-      return expected;
+      return status;
     }
-  } while (expected == TOKEN_NONE);
+  } while (status == STATUS_OK);
 
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
 // statement
 
-static int
-parse_statement (ViviCompilerScanner *scanner, ViviCodeStatement **statement);
+static ParseStatus
+parse_statement (ParseData *data, ViviCodeStatement **statement);
 
-static int
-parse_if_statement (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_if_statement (ParseData *data,
     ViviCodeStatement **statement)
 {
-  int expected;
+  ParseStatus status;
   ViviCodeValue *condition;
   ViviCodeStatement *pre_statement, *if_statement, *else_statement;
 
   *statement = NULL;
 
-  if (!check_token (scanner, TOKEN_IF))
-    return -TOKEN_IF;
+  if (!check_token (data, TOKEN_IF))
+    return CANCEL (TOKEN_IF);
 
-  if (!check_token (scanner, TOKEN_PARENTHESIS_LEFT))
-    return TOKEN_PARENTHESIS_LEFT;
+  if (!check_token (data, TOKEN_PARENTHESIS_LEFT))
+    return FAIL (TOKEN_PARENTHESIS_LEFT);
 
-  expected = parse_expression (scanner, &condition, &pre_statement);
-  if (expected != TOKEN_NONE)
-    return FAIL (expected);
+  status = parse_expression (data, &condition, &pre_statement);
+  if (status != STATUS_OK)
+    return FAIL_CHILD (status);
 
-  if (!check_token (scanner, TOKEN_PARENTHESIS_RIGHT)) {
+  if (!check_token (data, TOKEN_PARENTHESIS_RIGHT)) {
     g_object_unref (condition);
     if (pre_statement != NULL) {
       g_object_unref (pre_statement);
       pre_statement = NULL;
     }
-    return TOKEN_PARENTHESIS_RIGHT;
+    return FAIL (TOKEN_PARENTHESIS_RIGHT);
   }
 
-  expected = parse_statement (scanner, &if_statement);
-  if (expected != TOKEN_NONE) {
+  status = parse_statement (data, &if_statement);
+  if (status != STATUS_OK) {
     g_object_unref (condition);
     if (pre_statement != NULL) {
       g_object_unref (pre_statement);
       pre_statement = NULL;
     }
-    return FAIL (expected);
+    return FAIL_CHILD (status);
   }
 
-  if (check_token (scanner, TOKEN_ELSE)) {
-    expected = parse_statement (scanner, &else_statement);
-    if (expected != TOKEN_NONE) {
+  if (check_token (data, TOKEN_ELSE)) {
+    status = parse_statement (data, &else_statement);
+    if (status != STATUS_OK) {
       g_object_unref (condition);
       if (pre_statement != NULL) {
 	g_object_unref (pre_statement);
 	pre_statement = NULL;
       }
       g_object_unref (if_statement);
-      return FAIL (expected);
+      return FAIL_CHILD (status);
     }
   } else {
     else_statement = NULL;
@@ -1087,114 +1102,114 @@ parse_if_statement (ViviCompilerScanner *scanner,
 
   g_assert (*statement != NULL);
 
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
-static int
-parse_expression_statement (ViviCompilerScanner *scanner,
-    ViviCodeStatement **statement)
+static ParseStatus
+parse_expression_statement (ParseData *data, ViviCodeStatement **statement)
 {
-  int expected;
+  ParseStatus status;
   ViviCodeValue *value;
 
   *statement = NULL;
 
-  vivi_compiler_scanner_peek_next_token (scanner);
-  if (scanner->next_token == TOKEN_BRACE_LEFT ||
-      scanner->next_token == TOKEN_FUNCTION)
-    return -ERROR_TOKEN_EXPRESSION_STATEMENT;
+  vivi_compiler_scanner_peek_next_token (data->scanner);
+  if (data->scanner->next_token == TOKEN_BRACE_LEFT ||
+      data->scanner->next_token == TOKEN_FUNCTION)
+    return CANCEL (ERROR_TOKEN_EXPRESSION_STATEMENT);
 
-  expected = parse_expression (scanner, &value, statement);
-  if (expected != TOKEN_NONE)
-    return expected;
+  status = parse_expression (data, &value, statement);
+  if (status != STATUS_OK)
+    return status;
 
-  if (!check_token (scanner, TOKEN_SEMICOLON)) {
+  if (!check_token (data, TOKEN_SEMICOLON)) {
     g_object_unref (value);
     if (*statement != NULL) {
       g_object_unref (*statement);
       *statement = NULL;
     }
-    return TOKEN_SEMICOLON;
+    return FAIL (TOKEN_SEMICOLON);
   }
 
   *statement = vivi_compiler_combine_statements (2, *statement,
       vivi_code_value_statement_new (value));
   g_object_unref (value);
 
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
-static int
-parse_empty_statement (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_empty_statement (ParseData *data,
     ViviCodeStatement **statement)
 {
   *statement = NULL;
 
-  if (!check_token (scanner, TOKEN_SEMICOLON))
-    return -TOKEN_SEMICOLON;
+  if (!check_token (data, TOKEN_SEMICOLON))
+    return CANCEL (TOKEN_SEMICOLON);
 
   *statement = vivi_compiler_empty_statement_new ();
 
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
-static int
-parse_block (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
+static ParseStatus
+parse_block (ParseData *data, ViviCodeStatement **statement)
 {
-  int expected;
+  ParseStatus status;
 
   *statement = NULL;
 
-  if (!check_token (scanner, TOKEN_BRACE_LEFT))
-    return -TOKEN_BRACE_LEFT;
+  if (!check_token (data, TOKEN_BRACE_LEFT))
+    return CANCEL (TOKEN_BRACE_LEFT);
 
-  vivi_compiler_scanner_peek_next_token (scanner);
-  if (scanner->next_token != TOKEN_BRACE_RIGHT) {
-    expected =
-      parse_statement_list (scanner, parse_statement, statement, TOKEN_NONE);
-    if (expected != TOKEN_NONE)
-      return FAIL (expected);
+  vivi_compiler_scanner_peek_next_token (data->scanner);
+  if (data->scanner->next_token != TOKEN_BRACE_RIGHT) {
+    status =
+      parse_statement_list (data, parse_statement, statement, STATUS_OK);
+    if (status != STATUS_OK)
+      return FAIL_CHILD (status);
   } else {
     *statement = vivi_code_block_new ();
   }
 
-  if (!check_token (scanner, TOKEN_BRACE_RIGHT)) {
+  if (!check_token (data, TOKEN_BRACE_RIGHT)) {
     g_object_unref (*statement);
     *statement = NULL;
-    return TOKEN_BRACE_RIGHT;
+    return FAIL (TOKEN_BRACE_RIGHT);
   }
 
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
-static int
-parse_variable_statement (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
+static ParseStatus
+parse_variable_statement (ParseData *data, ViviCodeStatement **statement)
 {
-  int expected;
+  ParseStatus status;
 
   *statement = NULL;
 
-  if (!check_token (scanner, TOKEN_VAR))
-    return -TOKEN_VAR;
+  if (!check_token (data, TOKEN_VAR))
+    return CANCEL (TOKEN_VAR);
 
-  expected = parse_statement_list (scanner, parse_variable_declaration,
+  status = parse_statement_list (data, parse_variable_declaration,
       statement, TOKEN_COMMA);
-  if (expected != TOKEN_NONE)
-    return FAIL (expected);
+  if (status != STATUS_OK)
+    return FAIL (status);
 
-  if (!check_token (scanner, TOKEN_SEMICOLON)) {
+  if (!check_token (data, TOKEN_SEMICOLON)) {
     g_object_unref (*statement);
     *statement = NULL;
-    return TOKEN_SEMICOLON;
+    return FAIL (TOKEN_SEMICOLON);
   }
 
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
-static int
-parse_statement (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
+static ParseStatus
+parse_statement (ParseData *data, ViviCodeStatement **statement)
 {
-  int i, expected;
+  ParseStatus status;
+  int i;
   ParseStatementFunction functions[] = {
     parse_block,
     parse_variable_statement,
@@ -1216,29 +1231,26 @@ parse_statement (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
   *statement = NULL;
 
   for (i = 0; functions[i] != NULL; i++) {
-    expected = functions[i] (scanner, statement);
-    if (expected >= 0) {
-      g_assert ((expected == TOKEN_NONE && *statement != NULL) ||
-	  (expected != TOKEN_NONE && *statement == NULL));
-      return expected;
-    }
+    status = functions[i] (data, statement);
+    if (status != STATUS_CANCEL)
+      return status;
   }
 
-  return -ERROR_TOKEN_STATEMENT;
+  return CANCEL (ERROR_TOKEN_STATEMENT);
 }
 
 // function
 
-static int
-parse_source_element (ViviCompilerScanner *scanner, ViviCodeStatement **statement);
+static ParseStatus
+parse_source_element (ParseData *data, ViviCodeStatement **statement);
 
-static int
-parse_function_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
+static ParseStatus
+parse_function_declaration (ParseData *data, ViviCodeStatement **statement)
 {
   ViviCodeValue *function, *identifier;
   ViviCodeValue **arguments;
   ViviCodeStatement *body;
-  int expected;
+  ParseStatus status;
 
   *statement = NULL;
 
@@ -1246,48 +1258,48 @@ parse_function_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **st
   arguments = NULL;
   body = NULL;
 
-  if (!check_token (scanner, TOKEN_FUNCTION))
-    return -TOKEN_FUNCTION;
+  if (!check_token (data, TOKEN_FUNCTION))
+    return CANCEL (TOKEN_FUNCTION);
 
-  expected = parse_identifier (scanner, &identifier);
-  if (expected != TOKEN_NONE)
-    return FAIL (expected);
+  status = parse_identifier (data, &identifier);
+  if (status != STATUS_OK)
+    return FAIL_CHILD (status);
 
-  if (!check_token (scanner, TOKEN_PARENTHESIS_LEFT)) {
+  if (!check_token (data, TOKEN_PARENTHESIS_LEFT)) {
     g_object_unref (identifier);
-    return TOKEN_PARENTHESIS_LEFT;
+    return FAIL (TOKEN_PARENTHESIS_LEFT);
   }
 
-  expected =
-    parse_value_list (scanner, parse_identifier, &arguments, TOKEN_COMMA);
-  if (expected != TOKEN_NONE && expected >= 0)
-    return expected;
+  status =
+    parse_value_list (data, parse_identifier, &arguments, TOKEN_COMMA);
+  if (status == STATUS_FAIL)
+    return status;
 
-  if (!check_token (scanner, TOKEN_PARENTHESIS_RIGHT)) {
+  if (!check_token (data, TOKEN_PARENTHESIS_RIGHT)) {
     g_object_unref (identifier);
     free_value_list (arguments);
-    return TOKEN_PARENTHESIS_RIGHT;
+    return FAIL (TOKEN_PARENTHESIS_RIGHT);
   }
 
-  if (!check_token (scanner, TOKEN_BRACE_LEFT)) {
+  if (!check_token (data, TOKEN_BRACE_LEFT)) {
     g_object_unref (identifier);
     free_value_list (arguments);
-    return TOKEN_BRACE_LEFT;
+    return FAIL (TOKEN_BRACE_LEFT);
   }
 
-  expected = parse_statement_list (scanner, parse_source_element, &body,
-      TOKEN_NONE);
-  if (expected != TOKEN_NONE && expected >= 0) {
+  status = parse_statement_list (data, parse_source_element, &body,
+      STATUS_OK);
+  if (status == STATUS_FAIL) {
     g_object_unref (identifier);
     free_value_list (arguments);
-    return expected;
+    return status;
   }
 
-  if (!check_token (scanner, TOKEN_BRACE_RIGHT)) {
+  if (!check_token (data, TOKEN_BRACE_RIGHT)) {
     g_object_unref (identifier);
     free_value_list (arguments);
     g_object_unref (body);
-    return TOKEN_BRACE_RIGHT;
+    return FAIL (TOKEN_BRACE_RIGHT);
   }
 
   function = vivi_code_function_new ();
@@ -1299,64 +1311,66 @@ parse_function_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **st
   free_value_list (arguments);
   g_object_unref (body);
 
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
 // top
 
-static int
-parse_source_element (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
+static ParseStatus
+parse_source_element (ParseData *data, ViviCodeStatement **statement)
 {
-  int expected;
+  ParseStatus status;
 
   *statement = NULL;
 
-  expected = parse_function_declaration (scanner, statement);
-  if (expected < 0)
-    expected = parse_statement (scanner, statement);
+  status = parse_function_declaration (data, statement);
+  if (status == STATUS_CANCEL)
+    status = parse_statement (data, statement);
 
-  return expected;
+  return status;
 }
 
-static int
-parse_program (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
+static ParseStatus
+parse_program (ParseData *data, ViviCodeStatement **statement)
 {
-  int expected;
+  ParseStatus status;
 
   *statement = NULL;
 
-  expected = parse_statement_list (scanner, parse_source_element, statement,
-      TOKEN_NONE);
-  if (expected != TOKEN_NONE)
-    return FAIL (expected);
+  status = parse_statement_list (data, parse_source_element, statement,
+      STATUS_OK);
+  if (status != STATUS_OK)
+    return FAIL_CHILD (status);
 
-  if (!check_token (scanner, TOKEN_EOF)) {
+  if (!check_token (data, TOKEN_EOF)) {
+    g_object_unref (*statement);
     *statement = NULL;
-    return FAIL (parse_statement (scanner, statement));
+    status = parse_statement (data, statement);
+    return FAIL_CHILD (status);
   }
 
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
 // parsing
 
-static int
-parse_statement_list (ViviCompilerScanner *scanner,
+static ParseStatus
+parse_statement_list (ParseData *data,
     ParseStatementFunction function, ViviCodeStatement **block,
     guint separator)
 {
   ViviCodeStatement *statement;
-  int expected;
+  ParseStatus status;
 
-  g_assert (scanner != NULL);
+  g_assert (data != NULL);
   g_assert (function != NULL);
   g_assert (block != NULL);
 
   *block = NULL;
 
-  expected = function (scanner, &statement);
-  if (expected != TOKEN_NONE)
-    return expected;
+  status = function (data, &statement);
+  if (status != STATUS_OK)
+    return status;
 
   *block = vivi_code_block_new ();
 
@@ -1364,55 +1378,55 @@ parse_statement_list (ViviCompilerScanner *scanner,
     vivi_code_block_add_statement (VIVI_CODE_BLOCK (*block), statement);
     g_object_unref (statement);
 
-    if (separator != TOKEN_NONE && !check_token (scanner, separator))
+    if (separator != STATUS_OK && !check_token (data, separator))
       break;
 
-    expected = function (scanner, &statement);
-    if (expected != TOKEN_NONE && expected >= 0) {
+    status = function (data, &statement);
+    if (status == STATUS_FAIL) {
       g_object_unref (*block);
       *block = NULL;
-      return expected;
+      return STATUS_FAIL;
     }
-  } while (expected == TOKEN_NONE);
+  } while (status == STATUS_OK);
 
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
-static int
-parse_value_list (ViviCompilerScanner *scanner, ParseValueFunction function,
+static ParseStatus
+parse_value_list (ParseData *data, ParseValueFunction function,
     ViviCodeValue ***list, guint separator)
 {
   GPtrArray *array;
   ViviCodeValue *value;
-  int expected;
+  ParseStatus status;
 
-  g_assert (scanner != NULL);
+  g_assert (data != NULL);
   g_assert (function != NULL);
   g_assert (list != NULL);
 
   *list = NULL;
 
-  expected = function (scanner, &value);
-  if (expected != TOKEN_NONE)
-    return expected;
+  status = function (data, &value);
+  if (status != STATUS_OK)
+    return status;
 
   array = g_ptr_array_new ();
 
   do {
     g_ptr_array_add (array, value);
 
-    if (separator != TOKEN_NONE && !check_token (scanner, separator))
+    if (separator != STATUS_OK && !check_token (data, separator))
       break;
 
-    expected = function (scanner, &value);
-    if (expected != TOKEN_NONE && expected >= 0)
-      return expected;
-  } while (expected == TOKEN_NONE);
+    status = function (data, &value);
+    if (status == STATUS_FAIL)
+      return STATUS_FAIL;
+  } while (status == STATUS_OK);
   g_ptr_array_add (array, NULL);
 
   *list = (ViviCodeValue **)g_ptr_array_free (array, FALSE);
 
-  return TOKEN_NONE;
+  return STATUS_OK;
 }
 
 // public
@@ -1420,30 +1434,34 @@ parse_value_list (ViviCompilerScanner *scanner, ParseValueFunction function,
 ViviCodeStatement *
 vivi_compile_file (FILE *file, const char *input_name)
 {
-  ViviCompilerScanner *scanner;
+  ParseData data;
   ViviCodeStatement *statement;
-  int expected;
+  ParseStatus status;
 
   g_return_val_if_fail (file != NULL, NULL);
 
-  scanner = vivi_compiler_scanner_new (file);
-
-  expected = parse_program (scanner, &statement);
-  g_assert ((expected == TOKEN_NONE && VIVI_IS_CODE_STATEMENT (statement)) ||
-	(expected != TOKEN_NONE && statement == NULL));
-  g_assert (expected >= 0);
-
-  if (expected != TOKEN_NONE) {
-    vivi_compiler_scanner_get_next_token (scanner);
-    if (expected < TOKEN_LAST) {
-      vivi_compiler_scanner_unexp_token (scanner, expected);
+  data.scanner = vivi_compiler_scanner_new (file);
+  data.expected = TOKEN_NONE;
+  data.custom_error = NULL;
+
+  status = parse_program (&data, &statement);
+  g_assert ((status == STATUS_OK && VIVI_IS_CODE_STATEMENT (statement)) ||
+	(status != STATUS_OK && statement == NULL));
+  g_assert (status >= 0);
+
+  if (status != STATUS_OK) {
+    vivi_compiler_scanner_get_next_token (data.scanner);
+    if (data.custom_error != NULL) {
+      g_printerr ("%s\n", data.custom_error);
+    } else if (data.expected < TOKEN_LAST) {
+      vivi_compiler_scanner_unexp_token (data.scanner, data.expected);
     } else {
       guint i;
       const char *name;
 
       name = NULL;
       for (i = 0; error_names[i].token != TOKEN_LAST; i++) {
-	if (error_names[i].token == expected) {
+	if (error_names[i].token == data.expected) {
 	  name = error_names[i].name;
 	  break;
 	}
@@ -1451,11 +1469,11 @@ vivi_compile_file (FILE *file, const char *input_name)
 
       g_assert (name != NULL);
 
-      vivi_compiler_scanner_unexp_token_string (scanner, name);
+      vivi_compiler_scanner_unexp_token_custom (data.scanner, name);
     }
   }
 
-  g_object_unref (scanner);
+  g_object_unref (data.scanner);
 
   return statement;
 }
diff --git a/vivified/code/vivi_compiler_scanner.c b/vivified/code/vivi_compiler_scanner.c
index 55e29b8..8a35437 100644
--- a/vivified/code/vivi_compiler_scanner.c
+++ b/vivified/code/vivi_compiler_scanner.c
@@ -260,7 +260,7 @@ vivi_compiler_scanner_unexp_token (ViviCompilerScanner *scanner,
 }
 
 void
-vivi_compiler_scanner_unexp_token_string (ViviCompilerScanner *scanner,
+vivi_compiler_scanner_unexp_token_custom (ViviCompilerScanner *scanner,
     const char *expected)
 {
   vivi_compiler_scanner_print_unexp_token_message (scanner,
diff --git a/vivified/code/vivi_compiler_scanner.h b/vivified/code/vivi_compiler_scanner.h
index 02721b4..cfd1453 100644
--- a/vivified/code/vivi_compiler_scanner.h
+++ b/vivified/code/vivi_compiler_scanner.h
@@ -168,6 +168,8 @@ struct _ViviCompilerScanner
   ViviCompilerScannerToken	next_token;
   ViviCompilerScannerValue	value;
   ViviCompilerScannerValue	next_value;
+
+  ViviCompilerScannerToken	expected;
 };
 
 struct _ViviCompilerScannerClass
@@ -187,7 +189,7 @@ guint				vivi_compiler_scanner_cur_line		(ViviCompilerScanner *scanner);
 
 void				vivi_compiler_scanner_unexp_token	(ViviCompilerScanner *	scanner,
 									 ViviCompilerScannerToken expected);
-void				vivi_compiler_scanner_unexp_token_string (ViviCompilerScanner *	scanner,
+void				vivi_compiler_scanner_unexp_token_custom (ViviCompilerScanner *	scanner,
 									 const char *		expected);
 
 
commit eb709e112191e9d30e6fcbbbebb723d7408d51a7
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu Apr 3 22:17:47 2008 +0300

    Make ViviCodeFunction not save reference to script, only use it in constructor
    
    Also started fixing function declaration parsing

diff --git a/vivified/code/decompiler.c b/vivified/code/decompiler.c
index 296fa25..078a3fb 100644
--- a/vivified/code/decompiler.c
+++ b/vivified/code/decompiler.c
@@ -39,7 +39,7 @@ decode_script (gpointer scriptp, gpointer unused)
   ViviCodePrinter *printer;
 
   g_print ("/* %s */\n", script->name);
-  fun = vivi_code_function_new (scriptp);
+  fun = vivi_code_function_new_from_script (scriptp);
   printer = vivi_code_text_printer_new ();
 
   vivi_code_printer_print_token (printer, VIVI_CODE_TOKEN (fun));
diff --git a/vivified/code/vivi_code_function.c b/vivified/code/vivi_code_function.c
index 94d282e..518f60c 100644
--- a/vivified/code/vivi_code_function.c
+++ b/vivified/code/vivi_code_function.c
@@ -24,6 +24,7 @@
 #include <swfdec/swfdec_script_internal.h>
 
 #include "vivi_code_function.h"
+#include "vivi_code_constant.h"
 #include "vivi_code_printer.h"
 
 #include "vivi_decompiler.h"
@@ -35,7 +36,6 @@ vivi_code_function_dispose (GObject *object)
 {
   ViviCodeFunction *function = VIVI_CODE_FUNCTION (object);
 
-  swfdec_script_unref (function->script);
   if (function->body)
     g_object_unref (function->body);
 
@@ -49,10 +49,11 @@ vivi_code_function_print (ViviCodeToken *token, ViviCodePrinter*printer)
   guint i;
 
   vivi_code_printer_print (printer, "function (");
-  for (i = 0; i < function->script->n_arguments; i++) {
+  for (i = 0; i < function->n_arguments; i++) {
     if (i != 0)
       vivi_code_printer_print (printer, ", ");
-    vivi_code_printer_print (printer, function->script->arguments[i].name);
+    vivi_code_printer_print_token (printer,
+	VIVI_CODE_TOKEN (&function->arguments[i]));
   }
   vivi_code_printer_print (printer, ") {");
   vivi_code_printer_new_line (printer, FALSE);
@@ -93,16 +94,49 @@ vivi_code_function_init (ViviCodeFunction *function)
 }
 
 ViviCodeValue *
-vivi_code_function_new (SwfdecScript *script)
+vivi_code_function_new (void)
+{
+  return VIVI_CODE_VALUE (g_object_new (VIVI_TYPE_CODE_FUNCTION, NULL));
+}
+
+void
+vivi_code_function_set_body (ViviCodeFunction *function,
+    ViviCodeStatement *body)
+{
+  g_return_if_fail (VIVI_IS_CODE_FUNCTION (function));
+  g_return_if_fail (VIVI_IS_CODE_STATEMENT (body));
+
+  function->body = g_object_ref (body);
+}
+
+void
+vivi_code_function_add_argument (ViviCodeFunction *function,
+    ViviCodeValue *argument)
+{
+  g_return_if_fail (VIVI_IS_CODE_FUNCTION (function));
+  g_return_if_fail (VIVI_IS_CODE_VALUE (argument));
+
+  // TODO
+}
+
+ViviCodeValue *
+vivi_code_function_new_from_script (SwfdecScript *script)
 {
   ViviCodeFunction *function;
+  guint i;
 
   g_return_val_if_fail (script != NULL, NULL);
 
   function = g_object_new (VIVI_TYPE_CODE_FUNCTION, NULL);
-  function->script = swfdec_script_ref (script);
   function->body = vivi_decompile_script (script);
 
+  for (i = 0; i < script->n_arguments; i++) {
+    ViviCodeValue *argument =
+      vivi_code_constant_new_string (script->arguments[i].name);
+    vivi_code_function_add_argument (function, argument);
+    g_object_unref (argument);
+  }
+
   return VIVI_CODE_VALUE (function);
 }
 
diff --git a/vivified/code/vivi_code_function.h b/vivified/code/vivi_code_function.h
index 1b33857..00c1dc1 100644
--- a/vivified/code/vivi_code_function.h
+++ b/vivified/code/vivi_code_function.h
@@ -40,7 +40,8 @@ struct _ViviCodeFunction
 {
   ViviCodeValue		value;
 
-  SwfdecScript *	script;
+  guint			n_arguments;  		/* number of arguments */
+  ViviCodeValue *	arguments;		/* arguments or NULL if none */
   ViviCodeStatement *	body;
 };
 
@@ -51,7 +52,13 @@ struct _ViviCodeFunctionClass
 
 GType			vivi_code_function_get_type   	(void);
 
-ViviCodeValue *		vivi_code_function_new		(SwfdecScript *	script);
+ViviCodeValue *		vivi_code_function_new		(void);
+ViviCodeValue *		vivi_code_function_new_from_script (SwfdecScript *	script);
+
+void			vivi_code_function_set_body	(ViviCodeFunction *	function,
+							 ViviCodeStatement *	body);
+void			vivi_code_function_add_argument	(ViviCodeFunction *	function,
+							 ViviCodeValue *	argument);
 
 
 G_END_DECLS
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 65355ae..d4c5aad 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -1110,8 +1110,10 @@ parse_expression_statement (ViviCompilerScanner *scanner,
 
   if (!check_token (scanner, TOKEN_SEMICOLON)) {
     g_object_unref (value);
-    g_object_unref (*statement);
-    *statement = NULL;
+    if (*statement != NULL) {
+      g_object_unref (*statement);
+      *statement = NULL;
+    }
     return TOKEN_SEMICOLON;
   }
 
@@ -1233,8 +1235,7 @@ parse_source_element (ViviCompilerScanner *scanner, ViviCodeStatement **statemen
 static int
 parse_function_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 {
-  //ViviCodeStatement *function;
-  ViviCodeValue *identifier;
+  ViviCodeValue *function, *identifier;
   ViviCodeValue **arguments;
   ViviCodeStatement *body;
   int expected;
@@ -1289,10 +1290,10 @@ parse_function_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **st
     return TOKEN_BRACE_RIGHT;
   }
 
-  /*function = vivi_code_function_new (arguments, body);
+  function = vivi_code_function_new ();
+  vivi_code_function_set_body (VIVI_CODE_FUNCTION (function), body);
   *statement = vivi_compiler_assignment_new (VIVI_CODE_VALUE (identifier),
-      VIVI_CODE_VALUE (function));*/
-  *statement = vivi_compiler_empty_statement_new ();
+      VIVI_CODE_VALUE (function));
 
   g_object_unref (identifier);
   free_value_list (arguments);
@@ -1389,7 +1390,7 @@ parse_value_list (ViviCompilerScanner *scanner, ParseValueFunction function,
   g_assert (function != NULL);
   g_assert (list != NULL);
 
-  **list = NULL;
+  *list = NULL;
 
   expected = function (scanner, &value);
   if (expected != TOKEN_NONE)
diff --git a/vivified/code/vivi_decompiler.c b/vivified/code/vivi_decompiler.c
index 1914ef5..d4b5759 100644
--- a/vivified/code/vivi_decompiler.c
+++ b/vivified/code/vivi_decompiler.c
@@ -581,7 +581,7 @@ vivi_decompile_define_function (ViviDecompilerBlock *block, ViviDecompilerState
   script->n_arguments = n_args;
   script->arguments = args;
 
-  value = vivi_code_function_new (script);
+  value = vivi_code_function_new_from_script (script);
   /* attach the function */
   if (*function_name == '\0') {
     vivi_decompiler_state_push (state, value);
commit aea5fa38f878c218fd50ec2637c2b918e620381c
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu Apr 3 21:53:36 2008 +0300

    Fix unary/postfix assignments

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index b3d5535..65355ae 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -400,7 +400,7 @@ parse_variable_declaration (ViviCompilerScanner *scanner,
     statement_right = NULL;
   }
 
-  assignment = vivi_code_assignment_new (NULL, identifier, value);
+  assignment = vivi_compiler_assignment_new (identifier, value);
   vivi_code_assignment_set_local (VIVI_CODE_ASSIGNMENT (assignment), TRUE);
 
   *statement =
@@ -601,8 +601,8 @@ parse_postfix_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
 
   temporary = vivi_compiler_get_temporary_new ();
   *statement = vivi_compiler_combine_statements (3, *statement,
-      vivi_code_assignment_new (NULL, temporary, *value),
-      vivi_code_assignment_new (NULL, *value, operation));
+      vivi_compiler_assignment_new (temporary, *value),
+      vivi_compiler_assignment_new (*value, operation));
   g_object_unref (operation);
 
   g_object_unref (*value);
@@ -649,7 +649,7 @@ parse_unary_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
       g_object_unref (one);
 
       *statement = vivi_compiler_combine_statements (2, *statement,
-	  vivi_code_assignment_new (NULL, *value, tmp));
+	  vivi_compiler_assignment_new (*value, tmp));
       g_object_unref (tmp);
 
       return TOKEN_NONE;
@@ -1290,7 +1290,7 @@ parse_function_declaration (ViviCompilerScanner *scanner, ViviCodeStatement **st
   }
 
   /*function = vivi_code_function_new (arguments, body);
-  *statement = vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
+  *statement = vivi_compiler_assignment_new (VIVI_CODE_VALUE (identifier),
       VIVI_CODE_VALUE (function));*/
   *statement = vivi_compiler_empty_statement_new ();
 
commit 541d2b7d1cb5ec6637718ee52412340b7ffdffed
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu Apr 3 21:48:24 2008 +0300

    Fix parsing of expression statements

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index d6da199..b3d5535 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -1115,6 +1115,10 @@ parse_expression_statement (ViviCompilerScanner *scanner,
     return TOKEN_SEMICOLON;
   }
 
+  *statement = vivi_compiler_combine_statements (2, *statement,
+      vivi_code_value_statement_new (value));
+  g_object_unref (value);
+
   return TOKEN_NONE;
 }
 
commit f89e3f0b8ee64a3626558385e8adf593f14bd43a
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu Apr 3 21:45:26 2008 +0300

    Fix bug when parsing else branch

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 67413ac..d6da199 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -1079,7 +1079,7 @@ parse_if_statement (ViviCompilerScanner *scanner,
   g_object_unref (if_statement);
 
   if (else_statement != NULL) {
-    vivi_code_if_set_if (VIVI_CODE_IF (*statement), else_statement);
+    vivi_code_if_set_else (VIVI_CODE_IF (*statement), else_statement);
     g_object_unref (else_statement);
   }
 
commit 77de59344fc4f0b18e987075060fa58687798ba9
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu Apr 3 21:42:35 2008 +0300

    Fixes to unexpected token messages. Implement if-statement parsing

diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 54027c9..67413ac 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -59,7 +59,19 @@ enum {
   ERROR_TOKEN_STATEMENT
 };
 
-#define FAIL(x) ((x) < 0 ? -x : x)
+static const struct {
+  int				token;
+  const char *			name;
+} error_names[] = {
+  { 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" },
+  { TOKEN_LAST, NULL }
+};
+
+#define FAIL(x) ((x) < 0 ? -(x) : (x))
 
 typedef int (*ParseValueFunction) (ViviCompilerScanner *scanner, ViviCodeValue **value);
 typedef int (*ParseValueStatementFunction) (ViviCompilerScanner *scanner, ViviCodeValue **value, ViviCodeStatement **statement);
@@ -497,7 +509,6 @@ parse_member_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
       }
     } 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 {
@@ -1005,6 +1016,81 @@ parse_expression (ViviCompilerScanner *scanner, ViviCodeValue **value,
 // statement
 
 static int
+parse_statement (ViviCompilerScanner *scanner, ViviCodeStatement **statement);
+
+static int
+parse_if_statement (ViviCompilerScanner *scanner,
+    ViviCodeStatement **statement)
+{
+  int expected;
+  ViviCodeValue *condition;
+  ViviCodeStatement *pre_statement, *if_statement, *else_statement;
+
+  *statement = NULL;
+
+  if (!check_token (scanner, TOKEN_IF))
+    return -TOKEN_IF;
+
+  if (!check_token (scanner, TOKEN_PARENTHESIS_LEFT))
+    return TOKEN_PARENTHESIS_LEFT;
+
+  expected = parse_expression (scanner, &condition, &pre_statement);
+  if (expected != TOKEN_NONE)
+    return FAIL (expected);
+
+  if (!check_token (scanner, TOKEN_PARENTHESIS_RIGHT)) {
+    g_object_unref (condition);
+    if (pre_statement != NULL) {
+      g_object_unref (pre_statement);
+      pre_statement = NULL;
+    }
+    return TOKEN_PARENTHESIS_RIGHT;
+  }
+
+  expected = parse_statement (scanner, &if_statement);
+  if (expected != TOKEN_NONE) {
+    g_object_unref (condition);
+    if (pre_statement != NULL) {
+      g_object_unref (pre_statement);
+      pre_statement = NULL;
+    }
+    return FAIL (expected);
+  }
+
+  if (check_token (scanner, TOKEN_ELSE)) {
+    expected = parse_statement (scanner, &else_statement);
+    if (expected != TOKEN_NONE) {
+      g_object_unref (condition);
+      if (pre_statement != NULL) {
+	g_object_unref (pre_statement);
+	pre_statement = NULL;
+      }
+      g_object_unref (if_statement);
+      return FAIL (expected);
+    }
+  } else {
+    else_statement = NULL;
+  }
+
+  *statement = vivi_code_if_new (condition);
+  g_object_unref (condition);
+
+  vivi_code_if_set_if (VIVI_CODE_IF (*statement), if_statement);
+  g_object_unref (if_statement);
+
+  if (else_statement != NULL) {
+    vivi_code_if_set_if (VIVI_CODE_IF (*statement), else_statement);
+    g_object_unref (else_statement);
+  }
+
+  *statement = vivi_compiler_combine_statements (2, pre_statement, *statement);
+
+  g_assert (*statement != NULL);
+
+  return TOKEN_NONE;
+}
+
+static int
 parse_expression_statement (ViviCompilerScanner *scanner,
     ViviCodeStatement **statement)
 {
@@ -1033,7 +1119,8 @@ parse_expression_statement (ViviCompilerScanner *scanner,
 }
 
 static int
-parse_empty_statement (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
+parse_empty_statement (ViviCompilerScanner *scanner,
+    ViviCodeStatement **statement)
 {
   *statement = NULL;
 
@@ -1046,9 +1133,6 @@ parse_empty_statement (ViviCompilerScanner *scanner, ViviCodeStatement **stateme
 }
 
 static int
-parse_statement (ViviCompilerScanner *scanner, ViviCodeStatement **statement);
-
-static int
 parse_block (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 {
   int expected;
@@ -1110,7 +1194,7 @@ parse_statement (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
     parse_variable_statement,
     parse_empty_statement,
     parse_expression_statement,
-    //parse_if_statement,
+    parse_if_statement,
     //parse_iteration_statement,
     //parse_continue_statement,
     //parse_break_statement,
@@ -1127,8 +1211,11 @@ parse_statement (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 
   for (i = 0; functions[i] != NULL; i++) {
     expected = functions[i] (scanner, statement);
-    if (expected >= 0)
+    if (expected >= 0) {
+      g_assert ((expected == TOKEN_NONE && *statement != NULL) ||
+	  (expected != TOKEN_NONE && *statement == NULL));
       return expected;
+    }
   }
 
   return -ERROR_TOKEN_STATEMENT;
@@ -1249,8 +1336,9 @@ parse_program (ViviCompilerScanner *scanner, ViviCodeStatement **statement)
 // parsing
 
 static int
-parse_statement_list (ViviCompilerScanner *scanner, ParseStatementFunction function,
-    ViviCodeStatement **block, guint separator)
+parse_statement_list (ViviCompilerScanner *scanner,
+    ParseStatementFunction function, ViviCodeStatement **block,
+    guint separator)
 {
   ViviCodeStatement *statement;
   int expected;
@@ -1338,10 +1426,28 @@ vivi_compile_file (FILE *file, const char *input_name)
   expected = parse_program (scanner, &statement);
   g_assert ((expected == TOKEN_NONE && VIVI_IS_CODE_STATEMENT (statement)) ||
 	(expected != TOKEN_NONE && statement == NULL));
+  g_assert (expected >= 0);
 
   if (expected != TOKEN_NONE) {
     vivi_compiler_scanner_get_next_token (scanner);
-    vivi_compiler_scanner_unexp_token (scanner, expected);
+    if (expected < TOKEN_LAST) {
+      vivi_compiler_scanner_unexp_token (scanner, expected);
+    } else {
+      guint i;
+      const char *name;
+
+      name = NULL;
+      for (i = 0; error_names[i].token != TOKEN_LAST; i++) {
+	if (error_names[i].token == expected) {
+	  name = error_names[i].name;
+	  break;
+	}
+      }
+
+      g_assert (name != NULL);
+
+      vivi_compiler_scanner_unexp_token_string (scanner, name);
+    }
   }
 
   g_object_unref (scanner);
diff --git a/vivified/code/vivi_compiler_scanner.c b/vivified/code/vivi_compiler_scanner.c
index a350529..55e29b8 100644
--- a/vivified/code/vivi_compiler_scanner.c
+++ b/vivified/code/vivi_compiler_scanner.c
@@ -242,12 +242,27 @@ vivi_compiler_scanner_cur_line (ViviCompilerScanner *scanner)
   return yylineno;
 }
 
+static void
+vivi_compiler_scanner_print_unexp_token_message (ViviCompilerScanner *scanner,
+    const char *unexpected, const char *expected)
+{
+  g_printerr ("%i: Unexpected token %s expected %s\n",
+      vivi_compiler_scanner_cur_line (scanner), unexpected, expected);
+}
+
 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_print_unexp_token_message (scanner,
       vivi_compiler_scanner_token_name (scanner->token),
       vivi_compiler_scanner_token_name (expected));
 }
+
+void
+vivi_compiler_scanner_unexp_token_string (ViviCompilerScanner *scanner,
+    const char *expected)
+{
+  vivi_compiler_scanner_print_unexp_token_message (scanner,
+      vivi_compiler_scanner_token_name (scanner->token), expected);
+}
diff --git a/vivified/code/vivi_compiler_scanner.h b/vivified/code/vivi_compiler_scanner.h
index f782a3a..02721b4 100644
--- a/vivified/code/vivi_compiler_scanner.h
+++ b/vivified/code/vivi_compiler_scanner.h
@@ -187,6 +187,8 @@ guint				vivi_compiler_scanner_cur_line		(ViviCompilerScanner *scanner);
 
 void				vivi_compiler_scanner_unexp_token	(ViviCompilerScanner *	scanner,
 									 ViviCompilerScannerToken expected);
+void				vivi_compiler_scanner_unexp_token_string (ViviCompilerScanner *	scanner,
+									 const char *		expected);
 
 
 G_END_DECLS


More information about the Swfdec-commits mailing list