[Swfdec-commits] 7 commits - vivified/code

Pekka Lampila medar at kemper.freedesktop.org
Fri Apr 11 09:17:00 PDT 2008


 vivified/code/Makefile.am                       |    1 
 vivified/code/vivi_parser.c                     |  199 ++++++++++++-
 vivified/code/vivi_parser_scanner.c             |   58 +++-
 vivified/code/vivi_parser_scanner.h             |   28 +
 vivified/code/vivi_parser_scanner_lex.l         |  345 +++++++++++++-----------
 vivified/code/vivi_parser_scanner_lex_include.h |   28 -
 6 files changed, 455 insertions(+), 204 deletions(-)

New commits:
commit 2396fe86278e3c18a7a7ac34486ac88f65d7dfb5
Merge: 540d52b... 6d3e6f2...
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Apr 11 19:11:48 2008 +0300

    Merge branch 'master' of ssh://medar@git.freedesktop.org/git/swfdec/swfdec

commit 540d52b07c6ca4048c46079e3a8188fe6aa2fa46
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Apr 11 19:10:29 2008 +0300

    Fix errors from lex code being fired one token too early

diff --git a/vivified/code/vivi_parser_scanner.c b/vivified/code/vivi_parser_scanner.c
index 68f2fe7..a26a5cc 100644
--- a/vivified/code/vivi_parser_scanner.c
+++ b/vivified/code/vivi_parser_scanner.c
@@ -235,6 +235,16 @@ vivi_parser_scanner_advance (ViviParserScanner *scanner)
   scanner->column = scanner->next_column;
   scanner->position = scanner->next_position;
 
+  while (scanner->waiting_errors != NULL) {
+    if (scanner->error_handler != NULL) {
+      scanner->error_handler (scanner->waiting_errors->data,
+	  scanner->error_handler_data);
+      g_free (scanner->waiting_errors->data);
+    }
+    scanner->waiting_errors = g_slist_delete_link (scanner->waiting_errors,
+	scanner->waiting_errors);
+  }
+
   if (scanner->file == NULL) {
     scanner->next_token = TOKEN_EOF;
     scanner->next_value.v_string = NULL;
@@ -243,12 +253,11 @@ vivi_parser_scanner_advance (ViviParserScanner *scanner)
       scanner->next_token = yylex ();
       if (scanner->next_token == TOKEN_LINE_TERMINATOR) {
 	scanner->next_line_terminator = TRUE;
-      } else if (scanner->next_token == TOKEN_ERROR) {
-	if (scanner->error_handler != NULL) {
-	  scanner->error_handler (lex_value.v_error,
-	      scanner->error_handler_data);
-	}
 	vivi_parser_scanner_free_type_value (&lex_value);
+      } else if (scanner->next_token == TOKEN_ERROR) {
+	scanner->waiting_errors = g_slist_prepend (scanner->waiting_errors,
+	    lex_value.v_error);
+	lex_value.type = VALUE_TYPE_NONE;
       }
     } while (scanner->next_token == TOKEN_LINE_TERMINATOR ||
 	scanner->next_token == TOKEN_ERROR);
diff --git a/vivified/code/vivi_parser_scanner.h b/vivified/code/vivi_parser_scanner.h
index d020fa0..5b1e96b 100644
--- a/vivified/code/vivi_parser_scanner.h
+++ b/vivified/code/vivi_parser_scanner.h
@@ -188,8 +188,7 @@ struct _ViviParserScanner
 
   ViviParserScannerFunction	error_handler;
   gpointer			error_handler_data;
-  ViviParserScannerFunction	comment_handler;
-  gpointer			comment_handler_data;
+  GSList *			waiting_errors;
 
   ViviParserScannerToken	token;
   ViviParserScannerToken	next_token;
commit 8621df9150691c87d2fb4176bc9ec03f6bb2df98
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Apr 11 17:04:40 2008 +0300

    Handle parsing errors coming from the lex code properly

diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index 5741dae..12c90a1 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -553,6 +553,14 @@ vivi_parser_duplicate_code_token (ParseData *data)
   data->positions = g_slist_prepend (data->positions, position);
 }
 
+static void
+vivi_parser_error_handler (const char *text, gpointer user_data)
+{
+  ParseData *data = user_data;
+
+  vivi_parser_error (data, text);
+}
+
 // values
 
 /* ActionScript specific */
@@ -2380,6 +2388,8 @@ vivi_parse_file (FILE *file, const char *input_name)
   g_return_val_if_fail (file != NULL, NULL);
 
   data.scanner = vivi_parser_scanner_new (file);
+  vivi_parser_scanner_set_error_handler (data.scanner,
+      vivi_parser_error_handler, &data);
   data.levels = NULL;
   data.level = NULL;
   data.error_count = 0;
diff --git a/vivified/code/vivi_parser_scanner.c b/vivified/code/vivi_parser_scanner.c
index 2b39569..68f2fe7 100644
--- a/vivified/code/vivi_parser_scanner.c
+++ b/vivified/code/vivi_parser_scanner.c
@@ -42,6 +42,9 @@ vivi_parser_scanner_free_type_value (ViviParserScannerValue *value)
     case VALUE_TYPE_IDENTIFIER:
       g_free (value->v_identifier);
       break;
+    case VALUE_TYPE_ERROR:
+      g_free (value->v_error);
+      break;
     case VALUE_TYPE_NONE:
     case VALUE_TYPE_BOOLEAN:
     case VALUE_TYPE_NUMBER:
@@ -236,17 +239,21 @@ vivi_parser_scanner_advance (ViviParserScanner *scanner)
     scanner->next_token = TOKEN_EOF;
     scanner->next_value.v_string = NULL;
   } else {
-    scanner->next_token = yylex ();
-    if (scanner->next_token == TOKEN_LINE_TERMINATOR) {
-      scanner->next_line_terminator = TRUE;
-    } else {
-      scanner->next_line_terminator = FALSE;
-    }
-    while (scanner->next_token == TOKEN_LINE_TERMINATOR) {
+    do {
       scanner->next_token = yylex ();
-    }
-    scanner->next_value = lex_value;
+      if (scanner->next_token == TOKEN_LINE_TERMINATOR) {
+	scanner->next_line_terminator = TRUE;
+      } else if (scanner->next_token == TOKEN_ERROR) {
+	if (scanner->error_handler != NULL) {
+	  scanner->error_handler (lex_value.v_error,
+	      scanner->error_handler_data);
+	}
+	vivi_parser_scanner_free_type_value (&lex_value);
+      }
+    } while (scanner->next_token == TOKEN_LINE_TERMINATOR ||
+	scanner->next_token == TOKEN_ERROR);
 
+    scanner->next_value = lex_value;
     scanner->next_line_number = lex_line_number;
     scanner->next_column = lex_column;
     scanner->next_position = lex_position;
@@ -275,6 +282,14 @@ vivi_parser_scanner_new (FILE *file)
   return scanner;
 }
 
+void
+vivi_parser_scanner_set_error_handler (ViviParserScanner *scanner,
+    ViviParserScannerFunction error_handler, gpointer user_data)
+{
+  scanner->error_handler = error_handler;
+  scanner->error_handler_data = user_data;
+}
+
 ViviParserScannerToken
 vivi_parser_scanner_get_next_token (ViviParserScanner *scanner)
 {
diff --git a/vivified/code/vivi_parser_scanner.h b/vivified/code/vivi_parser_scanner.h
index 2d40af0..d020fa0 100644
--- a/vivified/code/vivi_parser_scanner.h
+++ b/vivified/code/vivi_parser_scanner.h
@@ -153,7 +153,8 @@ typedef enum {
   VALUE_TYPE_BOOLEAN,
   VALUE_TYPE_NUMBER,
   VALUE_TYPE_STRING,
-  VALUE_TYPE_IDENTIFIER
+  VALUE_TYPE_IDENTIFIER,
+  VALUE_TYPE_ERROR
 } ViviParserScannerValueType;
 
 typedef struct {
@@ -163,9 +164,12 @@ typedef struct {
     double	v_number;
     char *	v_string;
     char *	v_identifier;
+    char *	v_error;
   };
 } ViviParserScannerValue;
 
+typedef void (*ViviParserScannerFunction) (const char *text, gpointer user_data);
+
 typedef struct _ViviParserScanner ViviParserScanner;
 typedef struct _ViviParserScannerClass ViviParserScannerClass;
 
@@ -182,6 +186,11 @@ struct _ViviParserScanner
 
   FILE *			file;
 
+  ViviParserScannerFunction	error_handler;
+  gpointer			error_handler_data;
+  ViviParserScannerFunction	comment_handler;
+  gpointer			comment_handler_data;
+
   ViviParserScannerToken	token;
   ViviParserScannerToken	next_token;
 
@@ -211,6 +220,10 @@ struct _ViviParserScannerClass
 GType				vivi_parser_scanner_get_type   	(void);
 
 ViviParserScanner *		vivi_parser_scanner_new		(FILE *		file);
+void				vivi_parser_scanner_set_error_handler (ViviParserScanner *	scanner,
+								 ViviParserScannerFunction	error_handler,
+								 gpointer			user_data);
+
 ViviParserScannerToken	vivi_parser_scanner_get_next_token	(ViviParserScanner *	scanner);
 ViviParserScannerToken	vivi_parser_scanner_peek_next_token	(ViviParserScanner *	scanner);
 
diff --git a/vivified/code/vivi_parser_scanner_lex.l b/vivified/code/vivi_parser_scanner_lex.l
index 78c80d3..f042a4f 100644
--- a/vivified/code/vivi_parser_scanner_lex.l
+++ b/vivified/code/vivi_parser_scanner_lex.l
@@ -27,6 +27,8 @@ gsize lex_position = 0;
 
 static void new_line (void);
 static void count (void);
+
+static GString *string = NULL;
 %}
 
 %option			noyywrap
@@ -41,8 +43,6 @@ identifier_part		[$_a-zA-Z0-9]
 
 %%
 
-			GString *string = NULL;
-
 "/*"			{ count (); BEGIN(comment); }
 <comment>{
   [^*\n]*		{ count (); /* skip */ }
@@ -51,9 +51,13 @@ identifier_part		[$_a-zA-Z0-9]
   <<EOF>>		{
 			  count ();
 			  BEGIN(INITIAL);
+			  lex_value.type = VALUE_TYPE_ERROR;
+			  lex_value.v_error =
+			    g_strdup ("Unterminated comment");
 			  return TOKEN_ERROR;
 			}
 }
+
 "//"[^\r\n]*		{
 			  count ();
 			  new_line ();
@@ -249,35 +253,41 @@ identifier_part		[$_a-zA-Z0-9]
 			  count ();
 			  BEGIN(INITIAL);
 			  g_string_free (string, TRUE);
+			  lex_value.type = VALUE_TYPE_ERROR;
+			  lex_value.v_error = g_strdup (
+			      "Unterminated string constant");
 			  return TOKEN_ERROR;
 			}
-  \\0			{ count (); g_string_append_c (string, '0'); }
   \\[0-7]{1,3}		{
 			  guint64 result;
 			  count ();
 			  result = g_ascii_strtoull (yytext + 1, NULL, 8);
-			  if (result > 0xff || result == 0) { count ();
-			    BEGIN(INITIAL);
-			    g_string_free (string, TRUE);
+			  if (result > 0xff || result == 0) {
+			    lex_value.type = VALUE_TYPE_ERROR;
+			    lex_value.v_error = g_strdup_printf (
+				"Invalid escape sequence %s", yytext);
 			    return TOKEN_ERROR;
-			  } else { count ();
+			  } else {
 			    g_string_append_c (string, result);
 			  }
 			}
   \\[0-9]+		{
 			  count ();
-			  g_string_free (string, TRUE);
+			  lex_value.type = VALUE_TYPE_ERROR;
+			  lex_value.v_error = g_strdup_printf (
+			      "Invalid escape sequence %s", yytext);
 			  return TOKEN_ERROR;
 			}
   \\x[0-9a-fA-F]{2}	{
 			  guint64 result;
 			  count ();
 			  result = g_ascii_strtoull (yytext + 2, NULL, 16);
-			  if (result == 0) { count ();
-			    BEGIN(INITIAL);
-			    g_string_free (string, TRUE);
+			  if (result == 0) {
+			    lex_value.type = VALUE_TYPE_ERROR;
+			    lex_value.v_error = g_strdup_printf (
+				"Invalid escape sequence %s", yytext);
 			    return TOKEN_ERROR;
-			  } else { count ();
+			  } else {
 			    g_string_append_c (string, result);
 			  }
 			}
@@ -304,7 +314,13 @@ identifier_part		[$_a-zA-Z0-9]
 			  return TOKEN_IDENTIFIER;
 			}
 
-.			{ count (); return TOKEN_ERROR; }
+.			{
+			  count ();
+			  lex_value.type = VALUE_TYPE_ERROR;
+			  lex_value.v_error = g_strdup_printf (
+			      "Unknown character '%c'", yytext[0]);
+			  return TOKEN_ERROR;
+			}
 
 %%
 
@@ -315,6 +331,5 @@ static void new_line (void)
 
 static void count (void)
 {
-  g_print (">> %s >> %li + %i\n", yytext, lex_position, yyleng);
   lex_position += yyleng;
 }
commit 17c4e94cadc86353321b65ecede626e4c837231b
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Apr 11 13:45:09 2008 +0300

    Keep track on what text position each ViviCodeToken was created
    
    Actually the information is not saved to anywhere yet, but it is parsed

diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index 1ce87dd..d0f9c0a 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -95,7 +95,6 @@ noinst_HEADERS = \
 	vivi_parser.h \
 	vivi_parser_scanner.h \
 	vivi_parser_scanner_lex.h \
-	vivi_parser_scanner_lex_include.h \
 	vivified-compiler.h
 
 noinst_PROGRAMS = vivi-decompile vivi-compile
diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index 17fdc60..5741dae 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -93,6 +93,8 @@ typedef struct {
 typedef struct {
   ViviParserScanner *		scanner;
 
+  GSList *			positions;
+
   GSList *			levels; // ParseLevel, earlier levels
   ParseLevel *			level;  // current level
 
@@ -501,6 +503,56 @@ vivi_parser_add_label (ParseData *data, ViviCodeLabel *label)
   return TRUE;
 }
 
+static gsize
+vivi_parser_get_position (ParseData *data)
+{
+  return data->scanner->position;
+}
+
+static void
+vivi_parser_start_code_token (ParseData *data)
+{
+  gsize *position;
+
+  g_return_if_fail (data != NULL);
+
+  position = g_new (gsize, 1);
+  *position = vivi_parser_get_position (data);
+
+  data->positions = g_slist_prepend (data->positions, position);
+}
+
+static void
+vivi_parser_end_code_token (ParseData *data, ViviCodeToken *token)
+{
+  gsize start;
+
+  g_return_if_fail (data != NULL);
+  g_return_if_fail (token == NULL || VIVI_IS_CODE_TOKEN (token));
+  g_return_if_fail (data->positions != NULL);
+
+  start = *(gsize *)data->positions->data;
+  g_free (data->positions->data);
+  data->positions = g_slist_delete_link (data->positions, data->positions);
+
+  if (token != NULL)
+    g_print (":: %li - %li\n", start, vivi_parser_get_position (data));
+}
+
+static void
+vivi_parser_duplicate_code_token (ParseData *data)
+{
+  gsize *position;
+
+  g_return_if_fail (data != NULL);
+  g_return_if_fail (data->positions != NULL);
+
+  position = g_new (gsize, 1);
+  *position = *(gsize *)data->positions->data;
+
+  data->positions = g_slist_prepend (data->positions, position);
+}
+
 // values
 
 /* ActionScript specific */
@@ -513,9 +565,13 @@ peek_undefined_literal (ParseData *data)
 static void
 parse_undefined_literal (ParseData *data, ViviCodeValue **value)
 {
+  vivi_parser_start_code_token (data);
+
   parse_token (data, TOKEN_UNDEFINED);
 
   *value = vivi_code_constant_new_undefined ();
+
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
 }
 
 static gboolean
@@ -527,9 +583,13 @@ peek_null_literal (ParseData *data)
 static void
 parse_null_literal (ParseData *data, ViviCodeValue **value)
 {
+  vivi_parser_start_code_token (data);
+
   parse_token (data, TOKEN_NULL);
 
   *value = vivi_code_constant_new_null ();
+
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
 }
 
 static gboolean
@@ -541,12 +601,16 @@ peek_boolean_literal (ParseData *data)
 static void
 parse_boolean_literal (ParseData *data, ViviCodeValue **value)
 {
+  vivi_parser_start_code_token (data);
+
   if (!try_parse_token (data, TOKEN_BOOLEAN)) {
     vivi_parser_error_unexpected (data, TOKEN_BOOLEAN);
     *value = vivi_code_constant_new_boolean (0);
   } else {
     *value = vivi_code_constant_new_boolean (data->scanner->value.v_boolean);
   }
+
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
 }
 
 static gboolean
@@ -558,12 +622,16 @@ peek_numeric_literal (ParseData *data)
 static void
 parse_numeric_literal (ParseData *data, ViviCodeValue **value)
 {
+  vivi_parser_start_code_token (data);
+
   if (!try_parse_token (data, TOKEN_NUMBER)) {
     vivi_parser_error_unexpected (data, TOKEN_NUMBER);
     *value = vivi_code_constant_new_number (0);
   } else {
     *value = vivi_code_constant_new_number (data->scanner->value.v_number);
   }
+
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
 }
 
 static gboolean
@@ -575,12 +643,16 @@ peek_string_literal (ParseData *data)
 static void
 parse_string_literal (ParseData *data, ViviCodeValue **value)
 {
+  vivi_parser_start_code_token (data);
+
   if (!try_parse_token (data, TOKEN_STRING)) {
     vivi_parser_error_unexpected (data, TOKEN_STRING);
     *value = vivi_code_constant_new_string ("undefined");
   } else {
     *value = vivi_code_constant_new_string (data->scanner->value.v_string);
   }
+
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
 }
 
 static const struct {
@@ -621,7 +693,9 @@ parse_literal (ParseData *data, ViviCodeValue **value)
   }
 
   vivi_parser_error_unexpected (data, ERROR_TOKEN_LITERAL);
+  vivi_parser_start_code_token (data);
   *value = vivi_code_constant_new_undefined ();
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
 }
 
 static gboolean
@@ -633,12 +707,16 @@ peek_identifier (ParseData *data)
 static void
 parse_identifier (ParseData *data, ViviCodeValue **value)
 {
+  vivi_parser_start_code_token (data);
+
   if (!try_parse_token (data, TOKEN_IDENTIFIER)) {
     vivi_parser_error_unexpected (data, TOKEN_IDENTIFIER);
     *value = vivi_code_get_new_name ("undefined");
   } else {
     *value = vivi_code_get_new_name (data->scanner->value.v_identifier);
   }
+
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
 }
 
 static const struct {
@@ -677,13 +755,9 @@ parse_property_name (ParseData *data, ViviCodeValue **value)
   }
 
   vivi_parser_error_unexpected (data, ERROR_TOKEN_PROPERTY_NAME);
+  vivi_parser_start_code_token (data);
   *value = vivi_code_constant_new_undefined ();
-}
-
-static gboolean
-peek_array_literal (ParseData *data)
-{
-  return peek_token (data, TOKEN_BRACKET_LEFT);
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
 }
 
 static gboolean
@@ -693,6 +767,12 @@ static void
 parse_assignment_expression (ParseData *data, ViviCodeValue **value,
     ViviCodeStatement **statement);
 
+static gboolean
+peek_array_literal (ParseData *data)
+{
+  return peek_token (data, TOKEN_BRACKET_LEFT);
+}
+
 static void
 parse_array_literal (ParseData *data, ViviCodeValue **value,
     ViviCodeStatement **statement)
@@ -700,6 +780,8 @@ parse_array_literal (ParseData *data, ViviCodeValue **value,
   ViviCodeValue *member;
   ViviCodeStatement *statement_new;
 
+  vivi_parser_start_code_token (data);
+
   *value = vivi_code_init_array_new ();
   *statement = NULL;
 
@@ -737,6 +819,8 @@ parse_array_literal (ParseData *data, ViviCodeValue **value,
       break;
     }
   }
+
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
 }
 
 static gboolean
@@ -749,6 +833,8 @@ static void
 parse_object_literal (ParseData *data, ViviCodeValue **value,
     ViviCodeStatement **statement)
 {
+  vivi_parser_start_code_token (data);
+
   *value = vivi_code_init_object_new ();
   *statement = NULL;
 
@@ -771,6 +857,8 @@ parse_object_literal (ParseData *data, ViviCodeValue **value,
   }
 
   parse_token (data, TOKEN_BRACE_RIGHT);
+
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
 }
 
 // misc
@@ -787,18 +875,26 @@ parse_variable_declaration (ParseData *data, ViviCodeStatement **statement)
   ViviCodeValue *identifier, *value;
   ViviCodeStatement *assignment, *statement_right;
 
+  vivi_parser_start_code_token (data);
+
   parse_identifier (data, &identifier);
 
   if (try_parse_token (data, TOKEN_ASSIGN)) {
     parse_assignment_expression (data, &value, &statement_right);
   } else {
+    vivi_parser_start_code_token (data);
+
     value = vivi_code_constant_new_undefined ();
     statement_right = NULL;
+
+    vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (value));
   }
 
   assignment = vivi_parser_assignment_new (identifier, value);
   vivi_code_assignment_set_local (VIVI_CODE_ASSIGNMENT (assignment), TRUE);
 
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (assignment));
+
   *statement = vivi_parser_join_statements (statement_right, assignment);
 }
 
@@ -843,15 +939,21 @@ parse_primary_expression (ParseData *data, ViviCodeValue **value,
 {
   guint i;
 
+  vivi_parser_start_code_token (data);
+
   if (try_parse_token (data, TOKEN_THIS)) {
     *value = vivi_code_get_new_name ("this");
     *statement = NULL;
+
+    vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
     return;
   }
 
   if (try_parse_token (data, TOKEN_PARENTHESIS_LEFT)) {
     parse_expression (data, value, statement);
     parse_token (data, TOKEN_PARENTHESIS_RIGHT);
+
+    vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
     return;
   }
 
@@ -864,6 +966,7 @@ parse_primary_expression (ParseData *data, ViviCodeValue **value,
 	primary_expression_functions[i].parse_value_statement (data, value,
 	    statement);
       }
+      vivi_parser_end_code_token (data, NULL);
       return;
     }
   }
@@ -871,6 +974,7 @@ parse_primary_expression (ParseData *data, ViviCodeValue **value,
   vivi_parser_error_unexpected (data, ERROR_TOKEN_PRIMARY_EXPRESSION);
   *value = vivi_code_constant_new_undefined ();
   *statement = NULL;
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
 }
 
 static gboolean
@@ -893,6 +997,8 @@ parse_member_expression (ParseData *data, ViviCodeValue **value,
   ViviCodeValue *member;
   ViviCodeStatement *statement_member;
 
+  vivi_parser_start_code_token (data);
+
   if (peek_primary_expression (data)) {
     parse_primary_expression (data, value, statement);
   } else if (peek_function_expression (data)) {
@@ -902,6 +1008,9 @@ parse_member_expression (ParseData *data, ViviCodeValue **value,
 	ERROR_TOKEN_FUNCTION_EXPRESSION, TOKEN_NONE);
     *value = vivi_code_constant_new_undefined ();
     *statement = NULL;
+
+    vivi_parser_duplicate_code_token (data);
+    vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
   }
 
   while (TRUE) {
@@ -916,6 +1025,7 @@ parse_member_expression (ParseData *data, ViviCodeValue **value,
     } else if (try_parse_token (data, TOKEN_DOT)) {
       parse_identifier (data, &member);
     } else {
+      vivi_parser_end_code_token (data, NULL);
       return;
     }
 
@@ -923,6 +1033,9 @@ parse_member_expression (ParseData *data, ViviCodeValue **value,
     *value = vivi_parser_get_new (tmp, member);
     g_object_unref (tmp);
     g_object_unref (member);
+
+    vivi_parser_duplicate_code_token (data);
+    vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
   }
 
   g_assert_not_reached ();
@@ -944,6 +1057,8 @@ parse_left_hand_side_expression (ParseData *data, ViviCodeValue **value,
   ViviCodeStatement *argument_statement;
   guint i;
 
+  vivi_parser_start_code_token (data);
+
   if (try_parse_token (data, TOKEN_NEW)) {
     parse_left_hand_side_expression (data, value, statement);
 
@@ -955,6 +1070,8 @@ parse_left_hand_side_expression (ParseData *data, ViviCodeValue **value,
 
     vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*value),
 	TRUE);
+
+    vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
     return;
   }
 
@@ -985,7 +1102,12 @@ parse_left_hand_side_expression (ParseData *data, ViviCodeValue **value,
       }
       free_value_list (arguments);
     }
+
+    vivi_parser_duplicate_code_token (data);
+    vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
   }
+
+  vivi_parser_end_code_token (data, NULL);
 }
 
 static gboolean
@@ -998,19 +1120,25 @@ static void
 parse_postfix_expression (ParseData *data, ViviCodeValue **value,
     ViviCodeStatement **statement)
 {
+  ViviCodeStatement *assignment;
   ViviCodeValue *operation, *one, *temporary;
   const char *operator;
 
+  vivi_parser_start_code_token (data);
+
   parse_left_hand_side_expression (data, value, statement);
 
-  if (peek_line_terminator (data))
+  if (peek_line_terminator (data)) {
+    vivi_parser_end_code_token (data, NULL);
     return;
+  }
 
   if (try_parse_token (data, TOKEN_INCREASE)) {
     operator = "+";
   } else if (try_parse_token (data, TOKEN_DESCREASE)) {
     operator = "-";
   } else {
+    vivi_parser_end_code_token (data, NULL);
     return;
   }
 
@@ -1024,12 +1152,18 @@ parse_postfix_expression (ParseData *data, ViviCodeValue **value,
   operation = vivi_code_binary_new_name (*value, one, operator);
   g_object_unref (one);
 
+  vivi_parser_duplicate_code_token (data);
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (operation));
+
+  assignment = vivi_parser_assignment_new (*value, operation);
+  g_object_unref (operation);
+
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (assignment));
+
   temporary = vivi_compiler_get_temporary_new ();
   *statement = vivi_parser_join_statements (*statement,
-      vivi_parser_join_statements (
-	vivi_parser_assignment_new (temporary, *value),
-	vivi_parser_assignment_new (*value, operation)));
-  g_object_unref (operation);
+     vivi_parser_join_statements (
+       vivi_parser_assignment_new (temporary, *value), assignment));
 
   g_object_unref (*value);
   *value = temporary;
@@ -1077,6 +1211,8 @@ parse_unary_expression (ParseData *data, ViviCodeValue **value,
     case TOKEN_DESCREASE:
       if (!operator) operator = "-";
 
+      vivi_parser_start_code_token (data);
+
       vivi_parser_scanner_get_next_token (data->scanner);
 
       parse_unary_expression (data, value, statement);
@@ -1091,6 +1227,8 @@ parse_unary_expression (ParseData *data, ViviCodeValue **value,
       tmp = vivi_code_binary_new_name (*value, one, operator);
       g_object_unref (one);
 
+      vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (tmp));
+
       *statement = vivi_parser_join_statements (*statement,
 	  vivi_parser_assignment_new (*value, tmp));
       g_object_unref (tmp);
@@ -1099,6 +1237,8 @@ parse_unary_expression (ParseData *data, ViviCodeValue **value,
     case TOKEN_MINUS:
     case TOKEN_BITWISE_NOT:*/
     case TOKEN_LOGICAL_NOT:
+      vivi_parser_start_code_token (data);
+
       vivi_parser_scanner_get_next_token (data->scanner);
 
       parse_unary_expression (data, value, statement);
@@ -1106,6 +1246,8 @@ parse_unary_expression (ParseData *data, ViviCodeValue **value,
       tmp = VIVI_CODE_VALUE (*value);
       *value = vivi_code_unary_new (tmp, '!');
       g_object_unref (tmp);
+
+      vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (tmp));
       break;
     default:
       parse_postfix_expression (data, value, statement);
@@ -1128,6 +1270,8 @@ parse_operator_expression (ParseData *data, ViviCodeValue **value,
   ViviCodeStatement *statement_right;
   guint i;
 
+  vivi_parser_start_code_token (data);
+
   next_parse_function (data, value, statement);
 
 again:
@@ -1167,9 +1311,14 @@ again:
       g_object_unref (left);
       g_object_unref (right);
 
+      vivi_parser_duplicate_code_token (data);
+      vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*value));
+
       goto again;
     }
   }
+
+  vivi_parser_end_code_token (data, NULL);
 }
 
 static gboolean
@@ -1408,11 +1557,15 @@ parse_assignment_expression (ParseData *data, ViviCodeValue **value,
   ViviCodeStatement *assignment, *statement_right;
   const char *operator;
 
+  vivi_parser_start_code_token (data);
+
   parse_conditional_expression (data, value, statement);
 
   // FIXME: Correct?
-  if (!vivi_parser_value_is_left_hand_side (*value))
+  if (!vivi_parser_value_is_left_hand_side (*value)) {
+    vivi_parser_end_code_token (data, NULL);
     return;
+  }
 
   operator = NULL;
 
@@ -1453,6 +1606,8 @@ parse_assignment_expression (ParseData *data, ViviCodeValue **value,
       }
       g_object_unref (right);
 
+      vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (assignment));
+
       *statement = vivi_parser_join_statements (*statement,
 	  vivi_parser_join_statements (statement_right, assignment));
       break;
@@ -1498,6 +1653,8 @@ parse_trace_statement (ParseData *data, ViviCodeStatement **statement)
   ViviCodeValue *value;
   ViviCodeStatement *expression_statement;
 
+  vivi_parser_start_code_token (data);
+
   parse_token (data, TOKEN_TRACE);
   parse_token (data, TOKEN_PARENTHESIS_LEFT);
   parse_expression (data, &value, &expression_statement);
@@ -1507,6 +1664,8 @@ parse_trace_statement (ParseData *data, ViviCodeStatement **statement)
   *statement = vivi_code_trace_new (value);
   g_object_unref (value);
 
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*statement));
+
   *statement = vivi_parser_join_statements (expression_statement, *statement);
 }
 
@@ -1514,6 +1673,8 @@ static void
 parse_continue_or_break_statement (ParseData *data,
     ViviCodeStatement **statement, ViviParserScannerToken token)
 {
+  vivi_parser_start_code_token (data);
+
   parse_token (data, token);
 
   if (!try_parse_restricted_semicolon (data)) {
@@ -1534,6 +1695,8 @@ parse_continue_or_break_statement (ParseData *data,
     // FIXME
     *statement = vivi_code_break_new ();
   }
+
+  vivi_parser_end_code_token (data, VIVI_CODE_TOKEN (*statement));
 }
 
 static gboolean
diff --git a/vivified/code/vivi_parser_scanner.c b/vivified/code/vivi_parser_scanner.c
index 978275a..2b39569 100644
--- a/vivified/code/vivi_parser_scanner.c
+++ b/vivified/code/vivi_parser_scanner.c
@@ -24,7 +24,11 @@
 #include "vivi_parser_scanner.h"
 
 #include "vivi_parser_scanner_lex.h"
-#include "vivi_parser_scanner_lex_include.h"
+
+extern ViviParserScannerValue lex_value;
+extern guint lex_line_number;
+extern guint lex_column;
+extern gsize lex_position;
 
 G_DEFINE_TYPE (ViviParserScanner, vivi_parser_scanner, G_TYPE_OBJECT)
 
@@ -223,8 +227,10 @@ vivi_parser_scanner_advance (ViviParserScanner *scanner)
 
   scanner->token = scanner->next_token;
   scanner->value = scanner->next_value;
-  scanner->line_number = scanner->next_line_number;
   scanner->line_terminator = scanner->next_line_terminator;
+  scanner->line_number = scanner->next_line_number;
+  scanner->column = scanner->next_column;
+  scanner->position = scanner->next_position;
 
   if (scanner->file == NULL) {
     scanner->next_token = TOKEN_EOF;
@@ -240,7 +246,11 @@ vivi_parser_scanner_advance (ViviParserScanner *scanner)
       scanner->next_token = yylex ();
     }
     scanner->next_value = lex_value;
+
     scanner->next_line_number = lex_line_number;
+    scanner->next_column = lex_column;
+    scanner->next_position = lex_position;
+
     lex_value.type = VALUE_TYPE_NONE;
   }
 }
@@ -255,6 +265,8 @@ vivi_parser_scanner_new (FILE *file)
   scanner = g_object_new (VIVI_TYPE_PARSER_SCANNER, NULL);
   scanner->file = file;
   scanner->line_number = scanner->next_line_number = lex_line_number = 1;
+  scanner->column = scanner->next_column = lex_column = 0;
+  scanner->position = scanner->next_position = lex_position = 0;
 
   yyrestart (file);
 
diff --git a/vivified/code/vivi_parser_scanner.h b/vivified/code/vivi_parser_scanner.h
index 4e7bd30..2d40af0 100644
--- a/vivified/code/vivi_parser_scanner.h
+++ b/vivified/code/vivi_parser_scanner.h
@@ -184,14 +184,22 @@ struct _ViviParserScanner
 
   ViviParserScannerToken	token;
   ViviParserScannerToken	next_token;
-  guint				line_number;
-  gboolean			line_terminator;
 
   ViviParserScannerValue	value;
   ViviParserScannerValue	next_value;
-  guint				next_line_number;
+
+  gboolean			line_terminator;
   gboolean			next_line_terminator;
 
+  guint				line_number;
+  guint				next_line_number;
+
+  guint				column;
+  guint				next_column;
+
+  gsize				position;
+  gsize				next_position;
+
   ViviParserScannerToken	expected;
 };
 
diff --git a/vivified/code/vivi_parser_scanner_lex.l b/vivified/code/vivi_parser_scanner_lex.l
index 3a0586c..78c80d3 100644
--- a/vivified/code/vivi_parser_scanner_lex.l
+++ b/vivified/code/vivi_parser_scanner_lex.l
@@ -18,7 +18,15 @@
  * Boston, MA  02110-1301  USA
  */
 
-#include "vivi_parser_scanner_lex_include.h"
+#include "vivi_parser_scanner.h"
+
+ViviParserScannerValue lex_value;
+guint lex_line_number = 0;
+guint lex_column = 0;
+gsize lex_position = 0;
+
+static void new_line (void);
+static void count (void);
 %}
 
 %option			noyywrap
@@ -35,167 +43,174 @@ identifier_part		[$_a-zA-Z0-9]
 
 			GString *string = NULL;
 
-"/*"			{ BEGIN(comment); }
+"/*"			{ count (); BEGIN(comment); }
 <comment>{
-  [^*\n]*		/* skip */
-  \n			{ lex_line_number++; }
-  "*/"			{ BEGIN(INITIAL); }
+  [^*\n]*		{ count (); /* skip */ }
+  \n			{ count (); new_line (); }
+  "*/"			{ count (); BEGIN(INITIAL); }
   <<EOF>>		{
+			  count ();
 			  BEGIN(INITIAL);
 			  return TOKEN_ERROR;
 			}
 }
 "//"[^\r\n]*		{
-			  lex_line_number++;
+			  count ();
+			  new_line ();
 			  return TOKEN_LINE_TERMINATOR;
 			}
 
 <<EOF>>			{ return TOKEN_EOF; }
 
-[ \t]			/* skip */
+[ \t]			{ count (); /* skip */ }
 
 \r\n			{
-			  lex_line_number++;
+			  count ();
+			  new_line ();
 			  return TOKEN_LINE_TERMINATOR;
 			}
 [\r\n]			{
-			  lex_line_number++;
+			  count ();
+			  new_line ();
 			  return TOKEN_LINE_TERMINATOR;
 			}
 
-"{"			{ return TOKEN_BRACE_LEFT; }
-"}"			{ return TOKEN_BRACE_RIGHT; }
-"["			{ return TOKEN_BRACKET_LEFT; }
-"]"			{ return TOKEN_BRACKET_RIGHT; }
-"("			{ return TOKEN_PARENTHESIS_LEFT; }
-")"			{ return TOKEN_PARENTHESIS_RIGHT; }
-
-"."			{ return TOKEN_DOT; }
-";"			{ return TOKEN_SEMICOLON; }
-","			{ return TOKEN_COMMA; }
-
-"<"			{ return TOKEN_LESS_THAN; }
-">"			{ return TOKEN_GREATER_THAN; }
-"<="			{ return TOKEN_LESS_THAN_OR_EQUAL; }
-">="			{ return TOKEN_EQUAL_OR_GREATER_THAN; }
-
-"=="			{ return TOKEN_EQUAL; }
-"!="			{ return TOKEN_NOT_EQUAL; }
-"==="			{ return TOKEN_STRICT_EQUAL; }
-"!=="			{ return TOKEN_NOT_STRICT_EQUAL; }
-
-"+"			{ return TOKEN_PLUS; }
-"-"			{ return TOKEN_MINUS; }
-"*"			{ return TOKEN_MULTIPLY; }
-"/"			{ return TOKEN_DIVIDE; }
-"%"			{ return TOKEN_REMAINDER; }
-
-"<<"			{ return TOKEN_SHIFT_LEFT; }
-">>"			{ return TOKEN_SHIFT_RIGHT; }
-">>>"			{ return TOKEN_SHIFT_RIGHT_UNSIGNED; }
-
-"&"			{ return TOKEN_BITWISE_AND; }
-"|"			{ return TOKEN_BITWISE_OR; }
-"^"			{ return TOKEN_BITWISE_XOR; }
-
-"!"			{ return TOKEN_LOGICAL_NOT; }
-"~"			{ return TOKEN_BITWISE_NOT; }
-"++"			{ return TOKEN_INCREASE; }
-"--"			{ return TOKEN_DESCREASE; }
-
-"?"			{ return TOKEN_QUESTION_MARK; }
-":"			{ return TOKEN_COLON; }
-
-"&&"			{ return TOKEN_LOGICAL_AND; }
-"||"			{ return TOKEN_LOGICAL_OR; }
-
-"="			{ return TOKEN_ASSIGN; }
-"*="			{ return TOKEN_ASSIGN_MULTIPLY; }
-"/="			{ return TOKEN_ASSIGN_DIVIDE; }
-"%="			{ return TOKEN_ASSIGN_REMAINDER; }
-"+="			{ return TOKEN_ASSIGN_ADD; }
-"-="			{ return TOKEN_ASSIGN_MINUS; }
-"<<="			{ return TOKEN_ASSIGN_SHIFT_LEFT; }
-">>="			{ return TOKEN_ASSIGN_SHIFT_RIGHT; }
-">>>="			{ return TOKEN_ASSIGN_SHIFT_RIGHT_ZERO; }
-"&="			{ return TOKEN_ASSIGN_BITWISE_AND; }
-"^="			{ return TOKEN_ASSIGN_BITWISE_XOR; }
-"|="			{ return TOKEN_ASSIGN_BITWISE_OR; }
-
-"break"			{ return TOKEN_BREAK; }
-"case"			{ return TOKEN_CASE; }
-"catch"			{ return TOKEN_CATCH; }
-"continue"		{ return TOKEN_CONTINUE; }
-"default"		{ return TOKEN_DEFAULT; }
-"delete"		{ return TOKEN_DELETE; }
-"do"			{ return TOKEN_DO; }
-"else"			{ return TOKEN_ELSE; }
-"finally"		{ return TOKEN_FINALLY; }
-"for"			{ return TOKEN_FOR; }
-"function"		{ return TOKEN_FUNCTION; }
-"if"			{ return TOKEN_IF; }
-"in"			{ return TOKEN_IN; }
-"instanceof"		{ return TOKEN_INSTANCEOF; }
-"new"			{ return TOKEN_NEW; }
-"return"		{ return TOKEN_RETURN; }
-"switch"		{ return TOKEN_SWITCH; }
-"this"			{ return TOKEN_THIS; }
-"throw"			{ return TOKEN_THROW; }
-"try"			{ return TOKEN_TRY; }
-"typeof"		{ return TOKEN_TYPEOF; }
-"var"			{ return TOKEN_VAR; }
-"void"			{ return TOKEN_VOID; }
-"while"			{ return TOKEN_WHILE; }
-"with"			{ return TOKEN_WITH; }
-
-"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; }
-
-"undefined"		{ return TOKEN_UNDEFINED; }
-"trace"			{ return TOKEN_TRACE; }
-
-"null"			{ return TOKEN_NULL; }
+"{"			{ count (); return TOKEN_BRACE_LEFT; }
+"}"			{ count (); return TOKEN_BRACE_RIGHT; }
+"["			{ count (); return TOKEN_BRACKET_LEFT; }
+"]"			{ count (); return TOKEN_BRACKET_RIGHT; }
+"("			{ count (); return TOKEN_PARENTHESIS_LEFT; }
+")"			{ count (); return TOKEN_PARENTHESIS_RIGHT; }
+
+"."			{ count (); return TOKEN_DOT; }
+";"			{ count (); return TOKEN_SEMICOLON; }
+","			{ count (); return TOKEN_COMMA; }
+
+"<"			{ count (); return TOKEN_LESS_THAN; }
+">"			{ count (); return TOKEN_GREATER_THAN; }
+"<="			{ count (); return TOKEN_LESS_THAN_OR_EQUAL; }
+">="			{ count (); return TOKEN_EQUAL_OR_GREATER_THAN; }
+
+"=="			{ count (); return TOKEN_EQUAL; }
+"!="			{ count (); return TOKEN_NOT_EQUAL; }
+"==="			{ count (); return TOKEN_STRICT_EQUAL; }
+"!=="			{ count (); return TOKEN_NOT_STRICT_EQUAL; }
+
+"+"			{ count (); return TOKEN_PLUS; }
+"-"			{ count (); return TOKEN_MINUS; }
+"*"			{ count (); return TOKEN_MULTIPLY; }
+"/"			{ count (); return TOKEN_DIVIDE; }
+"%"			{ count (); return TOKEN_REMAINDER; }
+
+"<<"			{ count (); return TOKEN_SHIFT_LEFT; }
+">>"			{ count (); return TOKEN_SHIFT_RIGHT; }
+">>>"			{ count (); return TOKEN_SHIFT_RIGHT_UNSIGNED; }
+
+"&"			{ count (); return TOKEN_BITWISE_AND; }
+"|"			{ count (); return TOKEN_BITWISE_OR; }
+"^"			{ count (); return TOKEN_BITWISE_XOR; }
+
+"!"			{ count (); return TOKEN_LOGICAL_NOT; }
+"~"			{ count (); return TOKEN_BITWISE_NOT; }
+"++"			{ count (); return TOKEN_INCREASE; }
+"--"			{ count (); return TOKEN_DESCREASE; }
+
+"?"			{ count (); return TOKEN_QUESTION_MARK; }
+":"			{ count (); return TOKEN_COLON; }
+
+"&&"			{ count (); return TOKEN_LOGICAL_AND; }
+"||"			{ count (); return TOKEN_LOGICAL_OR; }
+
+"="			{ count (); return TOKEN_ASSIGN; }
+"*="			{ count (); return TOKEN_ASSIGN_MULTIPLY; }
+"/="			{ count (); return TOKEN_ASSIGN_DIVIDE; }
+"%="			{ count (); return TOKEN_ASSIGN_REMAINDER; }
+"+="			{ count (); return TOKEN_ASSIGN_ADD; }
+"-="			{ count (); return TOKEN_ASSIGN_MINUS; }
+"<<="			{ count (); return TOKEN_ASSIGN_SHIFT_LEFT; }
+">>="			{ count (); return TOKEN_ASSIGN_SHIFT_RIGHT; }
+">>>="			{ count (); return TOKEN_ASSIGN_SHIFT_RIGHT_ZERO; }
+"&="			{ count (); return TOKEN_ASSIGN_BITWISE_AND; }
+"^="			{ count (); return TOKEN_ASSIGN_BITWISE_XOR; }
+"|="			{ count (); return TOKEN_ASSIGN_BITWISE_OR; }
+
+"break"			{ count (); return TOKEN_BREAK; }
+"case"			{ count (); return TOKEN_CASE; }
+"catch"			{ count (); return TOKEN_CATCH; }
+"continue"		{ count (); return TOKEN_CONTINUE; }
+"default"		{ count (); return TOKEN_DEFAULT; }
+"delete"		{ count (); return TOKEN_DELETE; }
+"do"			{ count (); return TOKEN_DO; }
+"else"			{ count (); return TOKEN_ELSE; }
+"finally"		{ count (); return TOKEN_FINALLY; }
+"for"			{ count (); return TOKEN_FOR; }
+"function"		{ count (); return TOKEN_FUNCTION; }
+"if"			{ count (); return TOKEN_IF; }
+"in"			{ count (); return TOKEN_IN; }
+"instanceof"		{ count (); return TOKEN_INSTANCEOF; }
+"new"			{ count (); return TOKEN_NEW; }
+"return"		{ count (); return TOKEN_RETURN; }
+"switch"		{ count (); return TOKEN_SWITCH; }
+"this"			{ count (); return TOKEN_THIS; }
+"throw"			{ count (); return TOKEN_THROW; }
+"try"			{ count (); return TOKEN_TRY; }
+"typeof"		{ count (); return TOKEN_TYPEOF; }
+"var"			{ count (); return TOKEN_VAR; }
+"void"			{ count (); return TOKEN_VOID; }
+"while"			{ count (); return TOKEN_WHILE; }
+"with"			{ count (); return TOKEN_WITH; }
+
+"abstract"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"boolean"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"byte"			{ count (); return TOKEN_RESERVED_KEYWORD; }
+"char"			{ count (); return TOKEN_RESERVED_KEYWORD; }
+"class"			{ count (); return TOKEN_RESERVED_KEYWORD; }
+"const"			{ count (); return TOKEN_RESERVED_KEYWORD; }
+"debugger"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"double"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"enum"			{ count (); return TOKEN_RESERVED_KEYWORD; }
+"export"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"extends"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"final"			{ count (); return TOKEN_RESERVED_KEYWORD; }
+"float"			{ count (); return TOKEN_RESERVED_KEYWORD; }
+"goto"			{ count (); return TOKEN_RESERVED_KEYWORD; }
+"implements"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"import"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"int"			{ count (); return TOKEN_RESERVED_KEYWORD; }
+"interface"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"long"			{ count (); return TOKEN_RESERVED_KEYWORD; }
+"native"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"package"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"private"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"protected"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"public"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"short"			{ count (); return TOKEN_RESERVED_KEYWORD; }
+"static"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"super"			{ count (); return TOKEN_RESERVED_KEYWORD; }
+"synchronized"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"throws"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"transient"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+"volatile"		{ count (); return TOKEN_RESERVED_KEYWORD; }
+
+"undefined"		{ count (); return TOKEN_UNDEFINED; }
+"trace"			{ count (); return TOKEN_TRACE; }
+
+"null"			{ count (); return TOKEN_NULL; }
 "true"			{
+			  count ();
 			  lex_value.type = VALUE_TYPE_BOOLEAN;
 			  lex_value.v_boolean = 1;
 			  return TOKEN_BOOLEAN;
 			}
 "false"			{
+			  count ();
 			  lex_value.type = VALUE_TYPE_BOOLEAN;
 			  lex_value.v_boolean = 0;
 			  return TOKEN_BOOLEAN;
 			}
 
 0[xX][0-9a-fA-F]+	{
+			  count ();
 			  lex_value.type = VALUE_TYPE_NUMBER;
 			  lex_value.v_number =
 			    g_ascii_strtoull (yytext, NULL, 16);
@@ -203,70 +218,79 @@ identifier_part		[$_a-zA-Z0-9]
 			}
 
 ([1-9][0-9]*|0)(\.[0-9]*)?([eE][+-]?[0-9]+)? {
+			  count ();
 			  lex_value.type = VALUE_TYPE_NUMBER;
 			  lex_value.v_number = g_ascii_strtod (yytext, NULL);
 			  return TOKEN_NUMBER;
 			}
 
 \.[0-9]+([eE][+-]?[0-9]+)? {
+			  count ();
 			  lex_value.type = VALUE_TYPE_NUMBER;
 			  lex_value.v_number = g_ascii_strtod (yytext, NULL);
 			  return TOKEN_NUMBER;
 			}
 
 \"			{
+			  count ();
 			  string = g_string_new ("");
 			  BEGIN(str);
 			}
 
 <str>{
   \"			{
+			  count ();
 			  BEGIN(INITIAL);
 			  lex_value.type = VALUE_TYPE_STRING;
 			  lex_value.v_string = g_string_free (string, FALSE);
 			  return TOKEN_STRING;
 			}
   \n			{
+			  count ();
 			  BEGIN(INITIAL);
 			  g_string_free (string, TRUE);
 			  return TOKEN_ERROR;
 			}
-  \\0			{ g_string_append_c (string, '0'); }
+  \\0			{ count (); g_string_append_c (string, '0'); }
   \\[0-7]{1,3}		{
 			  guint64 result;
+			  count ();
 			  result = g_ascii_strtoull (yytext + 1, NULL, 8);
-			  if (result > 0xff || result == 0) {
+			  if (result > 0xff || result == 0) { count ();
 			    BEGIN(INITIAL);
 			    g_string_free (string, TRUE);
 			    return TOKEN_ERROR;
-			  } else {
+			  } else { count ();
 			    g_string_append_c (string, result);
 			  }
 			}
   \\[0-9]+		{
+			  count ();
 			  g_string_free (string, TRUE);
 			  return TOKEN_ERROR;
 			}
   \\x[0-9a-fA-F]{2}	{
 			  guint64 result;
+			  count ();
 			  result = g_ascii_strtoull (yytext + 2, NULL, 16);
-			  if (result == 0) {
+			  if (result == 0) { count ();
 			    BEGIN(INITIAL);
 			    g_string_free (string, TRUE);
 			    return TOKEN_ERROR;
-			  } else {
+			  } else { count ();
 			    g_string_append_c (string, result);
 			  }
 			}
-  \\b			{ g_string_append_c (string, '\b'); }
-  \\f			{ g_string_append_c (string, '\f'); }
-  \\n			{ g_string_append_c (string, '\n'); }
-  \\r			{ g_string_append_c (string, '\r'); }
-  \\t			{ g_string_append_c (string, '\t'); }
-  \\v			{ g_string_append_c (string, '\v'); }
-  \\.			{ g_string_append_c (string, yytext[1]); }
+  \\b			{ count (); g_string_append_c (string, '\b'); }
+  \\f			{ count (); g_string_append_c (string, '\f'); }
+  \\n			{ count (); g_string_append_c (string, '\n'); }
+  \\r			{ count (); g_string_append_c (string, '\r'); }
+  \\t			{ count (); g_string_append_c (string, '\t'); }
+  \\v			{ count (); g_string_append_c (string, '\v'); }
+  \\.			{ count (); g_string_append_c (string, yytext[1]); }
   [^\\\n\"]+		{
 			  char *p;
+			  count ();
 			  for (p = yytext; *p != '\0'; p++) {
 			    g_string_append_c (string, *p);
 			  }
@@ -274,11 +298,23 @@ identifier_part		[$_a-zA-Z0-9]
 }
 
 {identifier_start}({identifier_part})* {
-  			  lex_value.type = VALUE_TYPE_IDENTIFIER;
+			  count ();
+			  lex_value.type = VALUE_TYPE_IDENTIFIER;
 			  lex_value.v_identifier = g_strdup (yytext);
 			  return TOKEN_IDENTIFIER;
 			}
 
-.			{ return TOKEN_ERROR; }
+.			{ count (); return TOKEN_ERROR; }
 
 %%
+
+static void new_line (void)
+{
+  lex_line_number++;
+}
+
+static void count (void)
+{
+  g_print (">> %s >> %li + %i\n", yytext, lex_position, yyleng);
+  lex_position += yyleng;
+}
diff --git a/vivified/code/vivi_parser_scanner_lex_include.h b/vivified/code/vivi_parser_scanner_lex_include.h
deleted file mode 100644
index 1c2dabc..0000000
--- a/vivified/code/vivi_parser_scanner_lex_include.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Vivified
- * Copyright (C) 2008 Pekka Lampila <pekka.lampila at iki.fi>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
- * Boston, MA  02110-1301  USA
- */
-
-#ifndef _VIVI_PARSER_SCANNER_LEX_INCLUDE_H_
-#define _VIVI_PARSER_SCANNER_LEX_INCLUDE_H_
-
-#include "vivi_parser_scanner.h"
-
-ViviParserScannerValue lex_value;
-guint lex_line_number;
-
-#endif // _VIVI_PARSER_SCANNER_LEX_INCLUDE_H_
commit 552e46725099c3373624d994382b4ad3d5293f6d
Merge: f3fd0c7... 89945b8...
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Fri Apr 11 10:37:55 2008 +0300

    Merge branch 'master' of ssh://medar@git.freedesktop.org/git/swfdec/swfdec

commit f3fd0c756cafff1b5d839879f16141bd7e757cb3
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Thu Apr 10 00:46:11 2008 +0300

    Oops, broke number parsing earlier

diff --git a/vivified/code/vivi_parser.c b/vivified/code/vivi_parser.c
index 7ec3a0b..17fdc60 100644
--- a/vivified/code/vivi_parser.c
+++ b/vivified/code/vivi_parser.c
@@ -562,7 +562,7 @@ parse_numeric_literal (ParseData *data, ViviCodeValue **value)
     vivi_parser_error_unexpected (data, TOKEN_NUMBER);
     *value = vivi_code_constant_new_number (0);
   } else {
-    *value = vivi_code_constant_new_number (data->scanner->value.v_boolean);
+    *value = vivi_code_constant_new_number (data->scanner->value.v_number);
   }
 }
 
commit 55f6a773f8a297b7d97275dc5459e17c832718e8
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date:   Wed Apr 9 21:23:19 2008 +0300

    Fix equality operators

diff --git a/vivified/code/vivi_parser_scanner.c b/vivified/code/vivi_parser_scanner.c
index 092cefa..978275a 100644
--- a/vivified/code/vivi_parser_scanner.c
+++ b/vivified/code/vivi_parser_scanner.c
@@ -106,7 +106,7 @@ static const struct {
   { TOKEN_EQUAL_OR_GREATER_THAN, ">=" },
 
   // equality
-  { TOKEN_EQUAL, "=" },
+  { TOKEN_EQUAL, "==" },
   { TOKEN_NOT_EQUAL, "!=" },
   { TOKEN_STRICT_EQUAL, "===" },
   { TOKEN_NOT_STRICT_EQUAL, "!==" },
diff --git a/vivified/code/vivi_parser_scanner_lex.l b/vivified/code/vivi_parser_scanner_lex.l
index 34c4f61..3a0586c 100644
--- a/vivified/code/vivi_parser_scanner_lex.l
+++ b/vivified/code/vivi_parser_scanner_lex.l
@@ -79,10 +79,10 @@ identifier_part		[$_a-zA-Z0-9]
 "<="			{ return TOKEN_LESS_THAN_OR_EQUAL; }
 ">="			{ return TOKEN_EQUAL_OR_GREATER_THAN; }
 
-"==",			{ return TOKEN_EQUAL; }
-"!=",			{ return TOKEN_NOT_EQUAL; }
-"===",			{ return TOKEN_STRICT_EQUAL; }
-"!==",			{ return TOKEN_NOT_STRICT_EQUAL; }
+"=="			{ return TOKEN_EQUAL; }
+"!="			{ return TOKEN_NOT_EQUAL; }
+"==="			{ return TOKEN_STRICT_EQUAL; }
+"!=="			{ return TOKEN_NOT_STRICT_EQUAL; }
 
 "+"			{ return TOKEN_PLUS; }
 "-"			{ return TOKEN_MINUS; }


More information about the Swfdec-commits mailing list