[Swfdec-commits] 33 commits - AUTHORS swfdec/swfdec_as_strings.c swfdec/swfdec_font.c swfdec/swfdec_font.h swfdec/swfdec_player.c swfdec/swfdec_tag.c swfdec/swfdec_text_format.c vivified/code
Pekka Lampila
medar at kemper.freedesktop.org
Tue Apr 1 10:45:17 PDT 2008
AUTHORS | 1
swfdec/swfdec_as_strings.c | 4
swfdec/swfdec_font.c | 20
swfdec/swfdec_font.h | 6
swfdec/swfdec_player.c | 2
swfdec/swfdec_tag.c | 2
swfdec/swfdec_text_format.c | 72 +
vivified/code/.gitignore | 1
vivified/code/Makefile.am | 12
vivified/code/compiler.c | 59 +
vivified/code/vivi_code_assignment.c | 16
vivified/code/vivi_compiler.c | 1062 ++++++++++++++++++++++++++
vivified/code/vivi_compiler.h | 35
vivified/code/vivi_compiler_empty_statement.c | 69 +
vivified/code/vivi_compiler_empty_statement.h | 56 +
15 files changed, 1408 insertions(+), 9 deletions(-)
New commits:
commit f75836b3695f28b87a3067cfdd61581697adc7ac
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Tue Apr 1 20:43:54 2008 +0300
Add James Bowes to the AUTHORS file
diff --git a/AUTHORS b/AUTHORS
index 51e5a0e..0bb0266 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -3,6 +3,7 @@ Benjamin Otte <otte at gnome.org>
Cristian Grada <krigenator at gmail.com>
David Schleef <ds at schleef.org>
Eric Anholt <eric at anholt.net>
+James Bowes <jbowes at dangerouslyinc.com>
Nguyá»
n Thái Ngá»c Duy <pclouds at gmail.com>
Pavel Roskin <proski at gnu.org>
Pekka Lampila <pekka.lampila at iki.fi>
commit eed47549e6bb802a6d5039cb6ba1da06278bcb01
Author: James Bowes <jbowes at dangerouslyinc.com>
Date: Tue Apr 1 20:42:42 2008 +0300
Implement TextFormat.getTextExtent
diff --git a/swfdec/swfdec_as_strings.c b/swfdec/swfdec_as_strings.c
index 8e6cb9c..2170366 100644
--- a/swfdec/swfdec_as_strings.c
+++ b/swfdec/swfdec_as_strings.c
@@ -496,5 +496,9 @@ const char swfdec_as_strings[] =
SWFDEC_AS_CONSTANT_STRING ("Selection")
SWFDEC_AS_CONSTANT_STRING ("tabEnabled")
SWFDEC_AS_CONSTANT_STRING ("focusEnabled")
+ SWFDEC_AS_CONSTANT_STRING ("ascent")
+ SWFDEC_AS_CONSTANT_STRING ("descent")
+ SWFDEC_AS_CONSTANT_STRING ("textFieldHeight")
+ SWFDEC_AS_CONSTANT_STRING ("textFieldWidth")
/* add more here */
;
diff --git a/swfdec/swfdec_text_format.c b/swfdec/swfdec_text_format.c
index 79e82ee..fcc4b85 100644
--- a/swfdec/swfdec_text_format.c
+++ b/swfdec/swfdec_text_format.c
@@ -24,6 +24,7 @@
#include <math.h>
#include <string.h>
+#include <pango/pangocairo.h>
#include "swfdec_text_format.h"
#include "swfdec_as_native_function.h"
@@ -852,7 +853,76 @@ static void
swfdec_text_format_getTextExtent (SwfdecAsContext *cx, SwfdecAsObject *object,
guint argc, SwfdecAsValue *argv, SwfdecAsValue *ret)
{
- SWFDEC_STUB ("TextFormat.getTextExtent");
+ SwfdecTextFormat *format;
+ SwfdecAsObject *obj = swfdec_as_object_new_empty (cx);
+ SwfdecAsValue val;
+ const gchar *text;
+ GList *item_list;
+ PangoAnalysis analysis;
+ PangoFontMap *fontmap;
+ PangoContext *pcontext;
+ PangoAttrList *attrs;
+ PangoGlyphString *glyph_string = pango_glyph_string_new();
+ PangoRectangle ink_rect;
+ PangoFontDescription *desc;
+ PangoFont *font;
+
+ SWFDEC_AS_CHECK (SWFDEC_TYPE_TEXT_FORMAT, &format, "s", &text);
+
+ fontmap = pango_cairo_font_map_get_default ();
+ pcontext =
+ pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap));
+
+ attrs = pango_attr_list_new ();
+ item_list = pango_itemize (pcontext, text, 0, strlen(text), attrs, NULL);
+ pango_attr_list_unref (attrs);
+
+ analysis = ((PangoItem *)(item_list[0].data))->analysis;
+ pango_shape (text, strlen(text), &analysis, glyph_string);
+
+ desc = pango_font_description_new ();
+ pango_font_description_set_family_static (desc, format->font);
+ pango_font_description_set_size (desc, format->size * PANGO_SCALE);
+ if (format->bold){
+ pango_font_description_set_weight (desc, PANGO_WEIGHT_BOLD);
+ }
+ if (format->italic)
+ pango_font_description_set_style (desc, PANGO_STYLE_ITALIC);
+
+ font = pango_font_map_load_font (fontmap, pcontext, desc);
+ pango_glyph_string_extents (glyph_string, font, &ink_rect, NULL);
+
+ pango_glyph_string_free (glyph_string);
+ g_list_foreach (item_list, (GFunc) pango_item_free, NULL);
+ g_list_free (item_list);
+ pango_font_description_free (desc);
+ g_object_unref (G_OBJECT (pcontext));
+ g_object_unref (G_OBJECT (fontmap));
+ g_object_unref (G_OBJECT (font));
+
+ SWFDEC_AS_VALUE_SET_INT (&val, ink_rect.width / PANGO_SCALE +
+ format->left_margin + format->right_margin);
+ swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_width, &val);
+
+ SWFDEC_AS_VALUE_SET_INT (&val, (ink_rect.height / PANGO_SCALE +
+ format->leading));
+ swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_height, &val);
+
+ SWFDEC_AS_VALUE_SET_INT (&val, PANGO_ASCENT(ink_rect) / PANGO_SCALE);
+ swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_ascent, &val);
+
+ SWFDEC_AS_VALUE_SET_INT (&val, PANGO_DESCENT (ink_rect) / PANGO_SCALE);
+ swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_descent, &val);
+
+ SWFDEC_AS_VALUE_SET_INT (&val, ink_rect.width / PANGO_SCALE +
+ format->left_margin + format->right_margin + 4);
+ swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_textFieldWidth, &val);
+
+ SWFDEC_AS_VALUE_SET_INT (&val, ink_rect.height / PANGO_SCALE + 4 +
+ format->leading);
+ swfdec_as_object_set_variable (obj, SWFDEC_AS_STR_textFieldHeight, &val);
+
+ SWFDEC_AS_VALUE_SET_OBJECT (ret, obj);
}
void
commit 581b3f7f25670732159f506b28441e3631bf5bdd
Author: James Bowes <jbowes at dangerouslyinc.com>
Date: Tue Apr 1 20:42:04 2008 +0300
Implement the DefineFontName tag
diff --git a/swfdec/swfdec_font.c b/swfdec/swfdec_font.c
index a1dc936..82314f2 100644
--- a/swfdec/swfdec_font.c
+++ b/swfdec/swfdec_font.c
@@ -362,3 +362,23 @@ tag_func_define_font_2 (SwfdecSwfDecoder * s, guint tag)
return SWFDEC_STATUS_OK;
}
+
+int
+tag_func_define_font_name (SwfdecSwfDecoder * s, guint tag)
+{
+ guint id;
+ SwfdecFont *font;
+
+ id = swfdec_bits_get_u16 (&s->b);
+ font = swfdec_swf_decoder_get_character (s, id);
+
+ if (!SWFDEC_IS_FONT (font)) {
+ SWFDEC_ERROR ("didn't find a font with id %u", id);
+ return SWFDEC_STATUS_OK;
+ }
+
+ font->name = swfdec_bits_get_string (&s->b, s->version);
+ font->copyright = swfdec_bits_get_string (&s->b, s->version);
+
+ return SWFDEC_STATUS_OK;
+}
diff --git a/swfdec/swfdec_font.h b/swfdec/swfdec_font.h
index e1425e0..01bbbba 100644
--- a/swfdec/swfdec_font.h
+++ b/swfdec/swfdec_font.h
@@ -59,7 +59,8 @@ struct _SwfdecFont
{
SwfdecCharacter character;
- char * name; /* name of the font (FIXME: what name?) */
+ char * name; /* name of the font */
+ char * copyright; /* copyright of the font */
PangoFontDescription *desc;
gboolean bold; /* font is bold */
gboolean italic; /* font is italic */
@@ -89,5 +90,8 @@ int tag_func_define_font (SwfdecSwfDecoder * s,
int tag_func_define_font_2 (SwfdecSwfDecoder * s,
guint tag);
+int tag_func_define_font_name (SwfdecSwfDecoder * s,
+ guint tag);
+
G_END_DECLS
#endif
diff --git a/swfdec/swfdec_tag.c b/swfdec/swfdec_tag.c
index 16582e9..1d83bd0 100644
--- a/swfdec/swfdec_tag.c
+++ b/swfdec/swfdec_tag.c
@@ -432,7 +432,7 @@ static struct tag_func_struct tag_funcs[] = {
[SWFDEC_TAG_PRIVATE_IMAGE] = { "PrivateImage", NULL, 0},
[SWFDEC_TAG_DEFINESCENEDATA] = { "DefineSceneData", NULL, 0},
[SWFDEC_TAG_DEFINEBINARYDATA] = { "DefineBinaryData", NULL, 0},
- [SWFDEC_TAG_DEFINEFONTNAME] = { "DefineFontName", NULL, 0},
+ [SWFDEC_TAG_DEFINEFONTNAME] = { "DefineFontName", tag_func_define_font_name, 0},
[SWFDEC_TAG_STARTSOUND2] = {"StartSound2", NULL, SWFDEC_TAG_DEFINE_SPRITE }
};
commit 53a3f86bda5d594661e5efc0737907b000369000
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Tue Apr 1 20:40:33 2008 +0300
Silence a compiler warning
diff --git a/swfdec/swfdec_player.c b/swfdec/swfdec_player.c
index ba7a880..641fc1d 100644
--- a/swfdec/swfdec_player.c
+++ b/swfdec/swfdec_player.c
@@ -1424,7 +1424,7 @@ static gboolean
swfdec_player_handle_tab_list (SwfdecPlayer *player, SwfdecMovie *movie, SwfdecMovie *stop, gboolean forward)
{
SwfdecPlayerPrivate *priv;
- SwfdecMovie *cur;
+ SwfdecMovie *cur = NULL;
GList *list, *walk;
priv = player->priv;
commit 85ec4fad8cd001abf9caaa1bfddaa6523dc5e413
Merge: 3e44bd6... d672757...
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Tue Apr 1 20:36:47 2008 +0300
Merge branch 'master' of ssh://medar@git.freedesktop.org/git/swfdec/swfdec
Conflicts:
vivified/code/Makefile.am
commit 3e44bd6c9570450180540525b3903bbdf487e1cb
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Mon Mar 31 19:22:14 2008 +0300
Add support for giving error messages in the compiler
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index e759536..760c14e 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -47,12 +47,6 @@
#include "vivi_code_text_printer.h"
-typedef enum {
- STATUS_FAIL = -1,
- STATUS_OK = 0,
- STATUS_CANCEL = 1
-} ParseStatus;
-
enum {
// keywords
TOKEN_BREAK = G_TOKEN_LAST + 1,
@@ -87,7 +81,14 @@ enum {
TOKEN_NULL,
// misc
TOKEN_PLUSPLUS,
- TOKEN_MINUSMINUS
+ TOKEN_MINUSMINUS,
+ // errors
+ ERROR_TOKEN_BOOLEAN,
+ ERROR_TOKEN_LITERAL,
+ ERROR_TOKEN_PROPERTY_NAME,
+ ERROR_TOKEN_PRIMARY_EXPRESSION,
+ ERROR_TOKEN_EXPRESSION_STATEMENT,
+ ERROR_TOKEN_STATEMENT
};
typedef struct {
@@ -163,13 +164,26 @@ static const TokenDescription custom_tokens[] = {
{ G_TOKEN_NONE, NULL }
};
-typedef ParseStatus (*ParseStatementFunction) (GScanner *scanner, ViviCodeStatement **statement);
-typedef ParseStatus (*ParseValueFunction) (GScanner *scanner, ViviCodeValue **value);
+static const TokenDescription error_tokens[] = {
+ // errors
+ { ERROR_TOKEN_BOOLEAN, "boolean" },
+ { ERROR_TOKEN_LITERAL, "literal" },
+ { ERROR_TOKEN_PROPERTY_NAME, "property name" },
+ { ERROR_TOKEN_PRIMARY_EXPRESSION, "primary expression" },
+ { ERROR_TOKEN_EXPRESSION_STATEMENT, "expression statement" },
+ { ERROR_TOKEN_STATEMENT, "statement" },
+ { G_TOKEN_NONE, NULL }
+};
+
+#define FAIL(x) ((x) < 0 ? -x : x)
+
+typedef int (*ParseStatementFunction) (GScanner *scanner, ViviCodeStatement **statement);
+typedef int (*ParseValueFunction) (GScanner *scanner, ViviCodeValue **value);
-static ParseStatus
+static int
parse_statement_list (GScanner *scanner, ParseStatementFunction function,
ViviCodeStatement **statement, guint separator);
-static ParseStatus
+static int
parse_value_list (GScanner *scanner, ParseValueFunction function,
ViviCodeValue ***list, guint separator);
@@ -198,63 +212,62 @@ free_value_list (ViviCodeValue **list)
// values
-static ParseStatus
+static int
parse_null_literal (GScanner *scanner, ViviCodeValue **value)
{
*value = NULL;
if (!check_token (scanner, TOKEN_NULL))
- return STATUS_CANCEL;
+ return -TOKEN_NULL;
*value = vivi_code_constant_new_null ();
- return STATUS_OK;
+ return G_TOKEN_NONE;
}
-static ParseStatus
+static int
parse_boolean_literal (GScanner *scanner, ViviCodeValue **value)
{
*value = NULL;
if (check_token (scanner, TOKEN_TRUE)) {
*value = vivi_code_constant_new_boolean (TRUE);
- return STATUS_OK;
+ return G_TOKEN_NONE;
} else if (check_token (scanner, TOKEN_FALSE)) {
*value = vivi_code_constant_new_boolean (FALSE);
- return STATUS_OK;
+ return G_TOKEN_NONE;
} else {
- return STATUS_CANCEL;
+ return -ERROR_TOKEN_BOOLEAN;
}
}
-static ParseStatus
+static int
parse_numeric_literal (GScanner *scanner, ViviCodeValue **value)
{
*value = NULL;
if (!check_token (scanner, G_TOKEN_FLOAT))
- return STATUS_CANCEL;
+ return -G_TOKEN_FLOAT;
*value = vivi_code_constant_new_number (scanner->value.v_float);
- return STATUS_OK;
+ return G_TOKEN_NONE;
}
-static ParseStatus
+static int
parse_string_literal (GScanner *scanner, ViviCodeValue **value)
{
*value = NULL;
if (!check_token (scanner, G_TOKEN_STRING))
- return STATUS_CANCEL;
+ return -G_TOKEN_STRING;
*value = vivi_code_constant_new_string (scanner->value.v_string);
- return STATUS_OK;
+ return G_TOKEN_NONE;
}
-static ParseStatus
+static int
parse_literal (GScanner *scanner, ViviCodeValue **value)
{
- int i;
- ParseStatus status;
+ int i, expected;
ParseValueFunction functions[] = {
parse_null_literal,
parse_boolean_literal,
@@ -266,32 +279,31 @@ parse_literal (GScanner *scanner, ViviCodeValue **value)
*value = NULL;
for (i = 0; functions[i] != NULL; i++) {
- status = functions[i] (scanner, value);
- if (status != STATUS_CANCEL)
- return status;
+ expected = functions[i] (scanner, value);
+ if (expected >= 0)
+ return expected;
}
- return STATUS_CANCEL;
+ return -ERROR_TOKEN_LITERAL;
}
-static ParseStatus
+static int
parse_identifier (GScanner *scanner, ViviCodeValue **value)
{
*value = NULL;
if (!check_token (scanner, G_TOKEN_IDENTIFIER))
- return STATUS_CANCEL;
+ return -G_TOKEN_IDENTIFIER;
*value = vivi_code_get_new_name (scanner->value.v_identifier);
- return STATUS_OK;
+ return G_TOKEN_NONE;
}
-static ParseStatus
+static int
parse_property_name (GScanner *scanner, ViviCodeValue **value)
{
- int i;
- ParseStatus status;
+ int i, expected;
ParseValueFunction functions[] = {
parse_identifier,
parse_string_literal,
@@ -302,24 +314,26 @@ parse_property_name (GScanner *scanner, ViviCodeValue **value)
*value = NULL;
for (i = 0; functions[i] != NULL; i++) {
- status = functions[i] (scanner, value);
- if (status != STATUS_CANCEL)
- return status;
+ expected = functions[i] (scanner, value);
+ if (expected >= 0)
+ return expected;
}
- return STATUS_CANCEL;
+ return -ERROR_TOKEN_PROPERTY_NAME;
}
-static ParseStatus
+static int
parse_operator_expression (GScanner *scanner, ViviCodeValue **value);
-static ParseStatus
+static int
parse_object_literal (GScanner *scanner, ViviCodeValue **value)
{
+ int expected;
+
*value = NULL;
if (!check_token (scanner, '{'))
- return STATUS_CANCEL;
+ return -'{';
*value = vivi_code_init_object_new ();
@@ -327,53 +341,62 @@ parse_object_literal (GScanner *scanner, ViviCodeValue **value)
do {
ViviCodeValue *property, *initializer;
- if (parse_property_name (scanner, &property) != STATUS_OK)
- goto fail;
+ expected = parse_property_name (scanner, &property);
+ if (expected != G_TOKEN_NONE) {
+ g_object_unref (*value);
+ *value = NULL;
+ return FAIL (expected);
+ }
- if (!check_token (scanner, ':'))
- goto fail;
+ if (!check_token (scanner, ':')) {
+ g_object_unref (*value);
+ *value = NULL;
+ return ':';
+ }
// FIXME: assignment expression
- if (parse_operator_expression (scanner, &initializer) != STATUS_OK)
- goto fail;
+ expected = parse_operator_expression (scanner, &initializer);
+ if (expected != G_TOKEN_NONE) {
+ g_object_unref (*value);
+ *value = NULL;
+ return FAIL (expected);
+ }
vivi_code_init_object_add_variable (VIVI_CODE_INIT_OBJECT (*value),
property, initializer);
} while (check_token (scanner, ','));
}
- if (!check_token (scanner, '}'))
- goto fail;
-
- return STATUS_OK;
-
-fail:
+ if (!check_token (scanner, '}')) {
+ g_object_unref (*value);
+ *value = NULL;
+ return '}';
+ }
- g_object_unref (*value);
- *value = NULL;
- return STATUS_FAIL;
+ return G_TOKEN_NONE;
}
// misc
-static ParseStatus
+static int
parse_variable_declaration (GScanner *scanner, ViviCodeStatement **statement)
{
- ParseStatus status;
+ int expected;
ViviCodeValue *identifier;
ViviCodeValue *value;
*statement = NULL;
- status = parse_identifier (scanner, &identifier);
- if (status != STATUS_OK)
- return status;
+ expected = parse_identifier (scanner, &identifier);
+ if (expected != G_TOKEN_NONE)
+ return expected;
if (check_token (scanner, '=')) {
// FIXME: assignment expression
- if (parse_operator_expression (scanner, &value) != STATUS_OK) {
+ expected = parse_operator_expression (scanner, &value);
+ if (expected != G_TOKEN_NONE) {
g_object_unref (identifier);
- return STATUS_FAIL;
+ return FAIL (expected);
}
} else {
value = vivi_code_constant_new_undefined ();
@@ -382,16 +405,15 @@ parse_variable_declaration (GScanner *scanner, ViviCodeStatement **statement)
*statement = vivi_code_assignment_new (NULL, identifier, value);
vivi_code_assignment_set_local (VIVI_CODE_ASSIGNMENT (*statement), TRUE);
- return STATUS_OK;
+ return G_TOKEN_NONE;
}
// expression
-static ParseStatus
+static int
parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
{
- int i;
- ParseStatus status;
+ int i, expected;
ParseValueFunction functions[] = {
parse_identifier,
parse_literal,
@@ -404,59 +426,62 @@ parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
if (check_token (scanner, TOKEN_THIS)) {
*value = vivi_code_get_new_name ("this");
- return STATUS_OK;
+ return G_TOKEN_NONE;
}
if (check_token (scanner, '(')) {
// FIXME: assignment expression
- if (parse_operator_expression (scanner, value) != STATUS_OK)
- return STATUS_FAIL;
+ expected = parse_operator_expression (scanner, value);
+ if (expected != G_TOKEN_NONE)
+ return FAIL (expected);
if (!check_token (scanner, ')')) {
g_object_unref (*value);
*value = NULL;
- return STATUS_FAIL;
+ return ')';
}
- return STATUS_OK;
+ return G_TOKEN_NONE;
}
for (i = 0; functions[i] != NULL; i++) {
- status = functions[i] (scanner, value);
- if (status != STATUS_CANCEL)
- return status;
+ expected = functions[i] (scanner, value);
+ if (expected >= 0)
+ return expected;
}
- return STATUS_CANCEL;
+ return -ERROR_TOKEN_PRIMARY_EXPRESSION;
}
-static ParseStatus
+static int
parse_member_expression (GScanner *scanner, ViviCodeValue **value)
{
- ParseStatus status;
+ int expected;
ViviCodeValue *member;
// TODO: new MemberExpression Arguments
- status = parse_primary_expression (scanner, value);
- //if (status == STATUS_CANCEL)
- // status = parse_function_expression (scanner, value);
+ expected = parse_primary_expression (scanner, value);
+ //if (expected == STATUS_CANCEL)
+ // expected = parse_function_expression (scanner, value);
- if (status != 0)
- return status;
+ if (expected != G_TOKEN_NONE)
+ return expected;
do {
ViviCodeValue *tmp;
if (check_token (scanner, '[')) {
// FIXME: expression
- if (parse_operator_expression (scanner, &member) != STATUS_OK)
- return STATUS_FAIL;
+ expected = parse_operator_expression (scanner, &member);
+ if (expected != G_TOKEN_NONE)
+ return FAIL (expected);
if (!check_token (scanner, ']'))
- return STATUS_FAIL;
+ return ']';
} else if (check_token (scanner, '.')) {
- if (parse_identifier (scanner, &member) != STATUS_OK)
- return STATUS_FAIL;
+ expected = parse_identifier (scanner, &member);
+ if (expected != G_TOKEN_NONE)
+ return FAIL (expected);
} else {
- return STATUS_OK;
+ return G_TOKEN_NONE;
}
tmp = *value;
@@ -466,17 +491,19 @@ parse_member_expression (GScanner *scanner, ViviCodeValue **value)
} while (TRUE);
g_assert_not_reached ();
- return STATUS_FAIL;
}
-static ParseStatus
+static int
parse_new_expression (GScanner *scanner, ViviCodeValue **value)
{
+ int expected;
+
*value = NULL;
if (check_token (scanner, TOKEN_NEW)) {
- if (parse_new_expression (scanner, value) != STATUS_OK)
- return STATUS_FAIL;
+ expected = parse_new_expression (scanner, value);
+ if (expected != G_TOKEN_NONE)
+ return FAIL (expected);
if (!VIVI_IS_CODE_FUNCTION_CALL (*value)) {
ViviCodeValue *tmp = VIVI_CODE_VALUE (*value);
*value = vivi_code_function_call_new (NULL, tmp);
@@ -484,47 +511,60 @@ parse_new_expression (GScanner *scanner, ViviCodeValue **value)
}
vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*value),
TRUE);
- return STATUS_OK;
+ return G_TOKEN_NONE;
} else {
return parse_member_expression (scanner, value);
}
}
-static ParseStatus
+static int
parse_left_hand_side_expression (GScanner *scanner, ViviCodeValue **value)
{
- ParseStatus status;
+ int expected;
*value = NULL;
- status = parse_new_expression (scanner, value);
- //if (status == STATUS_CANCEL)
- // status = parse_call_expression (scanner, value);
+ expected = parse_new_expression (scanner, value);
+ //if (expected == STATUS_CANCEL)
+ // expected = parse_call_expression (scanner, value);
- return status;
+ return expected;
}
-static ParseStatus
+static int
parse_postfix_expression (GScanner *scanner, ViviCodeValue **value)
{
- ParseStatus status;
+ int expected;
+ ViviCodeValue *tmp, *one;
+ const char *operator;
- status = parse_left_hand_side_expression (scanner, value);
- if (status != STATUS_OK)
- return status;
+ expected = parse_left_hand_side_expression (scanner, value);
+ if (expected != G_TOKEN_NONE)
+ return expected;
// FIXME: Don't allow new line here
- /*if (check_token (scanner, TOKEN_PLUSPLUS)) {
- ViviCodeValue *tmp = *value;
- *value = vivi_code_postfix_new (tmp, "++");
- g_object_unref (tmp);
- } else {*/
- return STATUS_OK;
- //}
+ if (check_token (scanner, TOKEN_PLUSPLUS)) {
+ operator = "+";
+ } else if (check_token (scanner, TOKEN_MINUSMINUS)) {
+ operator = "-";
+ } else {
+ return G_TOKEN_NONE;
+ }
+
+ one = vivi_code_constant_new_number (1);
+
+ // FIXME: Side effect!
+ tmp = *value;
+ *value = vivi_code_binary_new_name (tmp, one, operator);
+ g_object_unref (tmp);
+
+ g_object_unref (one);
+
+ return G_TOKEN_NONE;
}
-static ParseStatus
+static int
parse_unary_expression (GScanner *scanner, ViviCodeValue **value)
{
ViviCodeValue *tmp;
@@ -532,82 +572,88 @@ parse_unary_expression (GScanner *scanner, ViviCodeValue **value)
*value = NULL;
if (check_token (scanner, '!')) {
- parse_unary_expression (scanner, value);
+ int expected = parse_unary_expression (scanner, value);
+ if (expected != G_TOKEN_NONE)
+ return FAIL (expected);
tmp = VIVI_CODE_VALUE (*value);
*value = vivi_code_unary_new (tmp, '!');
g_object_unref (tmp);
- return STATUS_OK;
+ return G_TOKEN_NONE;
} else {
return parse_postfix_expression (scanner, value);
}
}
-static ParseStatus
+static int
parse_operator_expression (GScanner *scanner, ViviCodeValue **value)
{
- ParseStatus status;
+ int expected;
ViviCodeValue *left;
ViviCodeValue *right;
*value = NULL;
- status = parse_unary_expression (scanner, value);
- if (status != STATUS_OK)
- return status;
+ expected = parse_unary_expression (scanner, value);
+ if (expected != G_TOKEN_NONE)
+ return expected;
- do {
- if (!check_token (scanner, '+'))
- return STATUS_OK;
-
- if (parse_unary_expression (scanner, &right) != STATUS_OK) {
+ while (check_token (scanner, '+')) {
+ expected = parse_unary_expression (scanner, &right);
+ if (expected != G_TOKEN_NONE) {
g_object_unref (*value);
*value = NULL;
- return STATUS_FAIL;
+ return FAIL (expected);
}
left = VIVI_CODE_VALUE (*value);
*value = vivi_code_binary_new_name (left, VIVI_CODE_VALUE (right), "+");
g_object_unref (left);
g_object_unref (right);
- } while (TRUE);
-
- g_object_unref (*value);
- *value = NULL;
+ };
- return STATUS_FAIL;
+ return G_TOKEN_NONE;
}
-static ParseStatus
+static int
parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement);
-static ParseStatus
+static int
parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
{
- ParseStatus status;
+ int expected;
ViviCodeValue *value;
ViviCodeStatement *if_statement, *else_statement;
*statement = NULL;
- if_statement = NULL;
- status = parse_operator_expression (scanner, &value);
- if (status != STATUS_OK)
- return status;
+ expected = parse_operator_expression (scanner, &value);
+ if (expected != G_TOKEN_NONE)
+ return expected;
if (!check_token (scanner, '?')) {
*statement = vivi_code_value_statement_new (VIVI_CODE_VALUE (value));
g_object_unref (value);
- return STATUS_OK;
+ return G_TOKEN_NONE;
}
- if (parse_assignment_expression (scanner, &if_statement) != STATUS_OK)
- goto fail;
+ expected = parse_assignment_expression (scanner, &if_statement);
+ if (expected != G_TOKEN_NONE) {
+ g_object_unref (value);
+ return FAIL (expected);
+ }
- if (!check_token (scanner, ':'))
- goto fail;
+ if (!check_token (scanner, ':')) {
+ g_object_unref (value);
+ g_object_unref (if_statement);
+ return ':';
+ }
- if (parse_assignment_expression (scanner, &else_statement) != STATUS_OK)
- goto fail;
+ expected = parse_assignment_expression (scanner, &else_statement);
+ if (expected != G_TOKEN_NONE) {
+ g_object_unref (value);
+ g_object_unref (if_statement);
+ return FAIL (expected);
+ }
*statement = vivi_code_if_new (value);
vivi_code_if_set_if (VIVI_CODE_IF (*statement), if_statement);
@@ -617,18 +663,10 @@ parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
g_object_unref (if_statement);
g_object_unref (else_statement);
- return STATUS_OK;
-
-fail:
-
- g_object_unref (value);
- if (if_statement != NULL)
- g_object_unref (if_statement);
-
- return STATUS_FAIL;
+ return G_TOKEN_NONE;
}
-static ParseStatus
+static int
parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement)
{
*statement = NULL;
@@ -638,7 +676,7 @@ parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement)
return parse_conditional_expression (scanner, statement);
}
-static ParseStatus
+static int
parse_expression (GScanner *scanner, ViviCodeStatement **statement)
{
*statement = NULL;
@@ -649,59 +687,62 @@ parse_expression (GScanner *scanner, ViviCodeStatement **statement)
// statement
-static ParseStatus
+static int
parse_expression_statement (GScanner *scanner, ViviCodeStatement **statement)
{
- ParseStatus status;
+ int expected;
*statement = NULL;
g_scanner_peek_next_token (scanner);
if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
- return STATUS_CANCEL;
+ return -ERROR_TOKEN_EXPRESSION_STATEMENT;
- status = parse_expression (scanner, statement);
- if (status != STATUS_OK)
- return status;
+ expected = parse_expression (scanner, statement);
+ if (expected != G_TOKEN_NONE)
+ return expected;
if (!check_token (scanner, ';')) {
g_object_unref (*statement);
*statement = NULL;
- return STATUS_FAIL;
+ return ';';
}
- return STATUS_OK;
+ return G_TOKEN_NONE;
}
-static ParseStatus
+static int
parse_empty_statement (GScanner *scanner, ViviCodeStatement **statement)
{
*statement = NULL;
if (!check_token (scanner, ';'))
- return STATUS_CANCEL;
+ return -';';
*statement = vivi_compiler_empty_statement_new ();
- return STATUS_OK;
+ return G_TOKEN_NONE;
}
-static ParseStatus
+static int
parse_statement (GScanner *scanner, ViviCodeStatement **statement);
-static ParseStatus
+static int
parse_block (GScanner *scanner, ViviCodeStatement **statement)
{
+ int expected;
+
*statement = NULL;
if (!check_token (scanner, '{'))
- return STATUS_CANCEL;
+ return -'{';
g_scanner_peek_next_token (scanner);
if (scanner->next_token != '}') {
- if (parse_statement_list (scanner, parse_statement, statement,
- G_TOKEN_NONE) != STATUS_OK)
- return STATUS_FAIL;
+ expected =
+ parse_statement_list (scanner, parse_statement, statement, G_TOKEN_NONE);
+ if (expected != G_TOKEN_NONE)
+ return FAIL (expected);
} else {
*statement = vivi_code_block_new ();
}
@@ -709,37 +750,40 @@ parse_block (GScanner *scanner, ViviCodeStatement **statement)
if (!check_token (scanner, '}')) {
g_object_unref (*statement);
*statement = NULL;
- return STATUS_FAIL;
+ return '}';
}
- return STATUS_OK;
+ return G_TOKEN_NONE;
}
-static ParseStatus
+static int
parse_variable_statement (GScanner *scanner, ViviCodeStatement **statement)
{
+ int expected;
+
*statement = NULL;
if (!check_token (scanner, TOKEN_VAR))
- return STATUS_CANCEL;
+ return -TOKEN_VAR;
- if (parse_statement_list (scanner, parse_variable_declaration, statement,
- ',') != STATUS_OK)
- return STATUS_FAIL;
+ expected =
+ parse_statement_list (scanner, parse_variable_declaration, statement, ',');
+ if (expected != G_TOKEN_NONE)
+ return FAIL (expected);
if (!check_token (scanner, ';')) {
g_object_unref (*statement);
*statement = NULL;
- return STATUS_FAIL;
+ return ';';
}
- return STATUS_OK;
+ return G_TOKEN_NONE;
}
-static ParseStatus
+static int
parse_statement (GScanner *scanner, ViviCodeStatement **statement)
{
- int i, status;
+ int i, expected;
ParseStatementFunction functions[] = {
parse_block,
parse_variable_statement,
@@ -761,26 +805,27 @@ parse_statement (GScanner *scanner, ViviCodeStatement **statement)
*statement = NULL;
for (i = 0; functions[i] != NULL; i++) {
- status = functions[i] (scanner, statement);
- if (status != STATUS_CANCEL)
- return status;
+ expected = functions[i] (scanner, statement);
+ if (expected >= 0)
+ return expected;
}
- return STATUS_CANCEL;
+ return -ERROR_TOKEN_STATEMENT;
}
// function
-static ParseStatus
+static int
parse_source_element (GScanner *scanner, ViviCodeStatement **statement);
-static ParseStatus
+static int
parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
{
//ViviCodeStatement *function;
ViviCodeValue *identifier;
ViviCodeValue **arguments;
ViviCodeStatement *body;
+ int expected;
*statement = NULL;
@@ -789,30 +834,47 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
body = NULL;
if (!check_token (scanner, TOKEN_FUNCTION))
- return STATUS_CANCEL;
+ return -TOKEN_FUNCTION;
- if (parse_identifier (scanner, &identifier) != STATUS_OK)
- return STATUS_FAIL;
+ expected = parse_identifier (scanner, &identifier);
+ if (expected != G_TOKEN_NONE)
+ return FAIL (expected);
- if (!check_token (scanner, '('))
- goto fail;
+ if (!check_token (scanner, '(')) {
+ g_object_unref (identifier);
+ return '(';
+ }
- if (parse_value_list (scanner, parse_identifier, &arguments, ',') ==
- STATUS_FAIL)
- goto fail;
+ expected = parse_value_list (scanner, parse_identifier, &arguments, ',');
+ if (expected != G_TOKEN_NONE && expected >= 0)
+ return expected;
- if (!check_token (scanner, ')'))
- goto fail;
+ if (!check_token (scanner, ')')) {
+ g_object_unref (identifier);
+ free_value_list (arguments);
+ return ')';
+ }
- if (!check_token (scanner, '{'))
- goto fail;
+ if (!check_token (scanner, '{')) {
+ g_object_unref (identifier);
+ free_value_list (arguments);
+ return '{';
+ }
- if (parse_statement_list (scanner, parse_source_element, &body, G_TOKEN_NONE)
- == STATUS_FAIL)
- goto fail;
+ expected = parse_statement_list (scanner, parse_source_element, &body,
+ G_TOKEN_NONE);
+ if (expected != G_TOKEN_NONE && expected >= 0) {
+ g_object_unref (identifier);
+ free_value_list (arguments);
+ return expected;
+ }
- if (!check_token (scanner, '}'))
- goto fail;
+ if (!check_token (scanner, '}')) {
+ g_object_unref (identifier);
+ free_value_list (arguments);
+ g_object_unref (body);
+ return '}';
+ }
/*function = vivi_code_function_new (arguments, body);
*statement = vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
@@ -820,67 +882,66 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
*statement = vivi_compiler_empty_statement_new ();
g_object_unref (identifier);
- if (arguments != NULL)
- free_value_list (arguments);
- if (body != NULL)
- g_object_unref (body);
-
- return STATUS_OK;
-
-fail:
- if (identifier != NULL)
- g_object_unref (identifier);
- if (arguments != NULL)
- free_value_list (arguments);
- if (body != NULL)
- g_object_unref (body);
+ free_value_list (arguments);
+ g_object_unref (body);
- return STATUS_FAIL;
+ return G_TOKEN_NONE;
}
// top
-static ParseStatus
+static int
parse_source_element (GScanner *scanner, ViviCodeStatement **statement)
{
- ParseStatus status;
+ int expected;
*statement = NULL;
- status = parse_function_declaration (scanner, statement);
- if (status == STATUS_CANCEL)
- status = parse_statement (scanner, statement);
+ expected = parse_function_declaration (scanner, statement);
+ if (expected < 0)
+ expected = parse_statement (scanner, statement);
- return status;
+ return expected;
}
-static ParseStatus
+static int
parse_program (GScanner *scanner, ViviCodeStatement **statement)
{
+ int expected;
+
*statement = NULL;
- return parse_statement_list (scanner, parse_source_element, statement,
+ expected = parse_statement_list (scanner, parse_source_element, statement,
G_TOKEN_NONE);
+ if (expected != G_TOKEN_NONE)
+ return FAIL (expected);
+
+ if (!check_token (scanner, G_TOKEN_EOF)) {
+ *statement = NULL;
+ return FAIL (parse_statement (scanner, statement));
+ }
+
+ return G_TOKEN_NONE;
}
// parsing
-static ParseStatus
+static int
parse_statement_list (GScanner *scanner, ParseStatementFunction function,
ViviCodeStatement **block, guint separator)
{
ViviCodeStatement *statement;
- ParseStatus status;
+ int expected;
- g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
- g_return_val_if_fail (function != NULL, STATUS_FAIL);
- g_return_val_if_fail (block != NULL, STATUS_FAIL);
+ g_assert (scanner != NULL);
+ g_assert (function != NULL);
+ g_assert (block != NULL);
*block = NULL;
- status = function (scanner, &statement);
- if (status != STATUS_OK)
- return status;
+ expected = function (scanner, &statement);
+ if (expected != G_TOKEN_NONE)
+ return expected;
*block = vivi_code_block_new ();
@@ -891,32 +952,32 @@ parse_statement_list (GScanner *scanner, ParseStatementFunction function,
if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
break;
- status = function (scanner, &statement);
- if (status == STATUS_FAIL) {
+ expected = function (scanner, &statement);
+ if (expected != G_TOKEN_NONE && expected >= 0) {
g_object_unref (*block);
*block = NULL;
- return STATUS_FAIL;
+ return expected;
}
- } while (status == STATUS_OK);
+ } while (expected == G_TOKEN_NONE);
- return STATUS_OK;
+ return G_TOKEN_NONE;
}
-static ParseStatus
+static int
parse_value_list (GScanner *scanner, ParseValueFunction function,
ViviCodeValue ***list, guint separator)
{
GPtrArray *array;
ViviCodeValue *value;
- ParseStatus status;
+ int expected;
- g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
- g_return_val_if_fail (function != NULL, STATUS_FAIL);
- g_return_val_if_fail (list != NULL, STATUS_FAIL);
+ g_assert (scanner != NULL);
+ g_assert (function != NULL);
+ g_assert (list != NULL);
- status = function (scanner, &value);
- if (status != STATUS_OK)
- return status;
+ expected = function (scanner, &value);
+ if (expected != G_TOKEN_NONE)
+ return expected;
array = g_ptr_array_new ();
@@ -926,15 +987,15 @@ parse_value_list (GScanner *scanner, ParseValueFunction function,
if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
break;
- status = function (scanner, &value);
- if (status == STATUS_FAIL)
- return STATUS_FAIL;
- } while (status == STATUS_OK);
+ expected = function (scanner, &value);
+ if (expected != G_TOKEN_NONE && expected >= 0)
+ return expected;
+ } while (expected == G_TOKEN_NONE);
g_ptr_array_add (array, NULL);
*list = (ViviCodeValue **)g_ptr_array_free (array, FALSE);
- return STATUS_OK;
+ return G_TOKEN_NONE;
}
// public
@@ -944,8 +1005,7 @@ vivi_compile_text (const char *text, gsize len, const char *input_name)
{
GScanner *scanner;
ViviCodeStatement *statement;
- ParseStatus status;
- int i;
+ int expected, i;
g_return_val_if_fail (text != NULL, NULL);
@@ -970,9 +1030,31 @@ vivi_compile_text (const char *text, gsize len, const char *input_name)
scanner->input_name = input_name;
g_scanner_input_text (scanner, text, len);
- status = parse_program (scanner, &statement);
- g_assert ((status == STATUS_OK && VIVI_IS_CODE_STATEMENT (statement)) ||
- (status != STATUS_OK && statement == NULL));
+ expected = parse_program (scanner, &statement);
+ g_assert ((expected == G_TOKEN_NONE && VIVI_IS_CODE_STATEMENT (statement)) ||
+ (expected != G_TOKEN_NONE && statement == NULL));
+ if (expected != G_TOKEN_NONE) {
+ char *name = NULL;
+
+ for (i = 0; custom_tokens[i].token != G_TOKEN_NONE; i++) {
+ if (custom_tokens[i].token == FAIL (expected)) {
+ name = g_ascii_strup (custom_tokens[i].symbol, -1);
+ break;
+ }
+ }
+ if (custom_tokens[i].token == G_TOKEN_NONE) {
+ for (i = 0; error_tokens[i].token != G_TOKEN_NONE; i++) {
+ if (error_tokens[i].token == FAIL (expected)) {
+ name = g_ascii_strup (error_tokens[i].symbol, -1);
+ break;
+ }
+ }
+ }
+
+ g_scanner_get_next_token (scanner);
+ g_scanner_unexp_token (scanner, FAIL (expected), NULL, name, NULL, NULL,
+ TRUE);
+ }
g_scanner_destroy (scanner);
commit 7fea8b48db4b0d01358805860b97df4b37a8b1fc
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Sun Mar 30 04:04:49 2008 +0300
Use operator expression in some places, instead of (assignment) expression
Just temporarily, since we don't support side-effects properly yet
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 3d31c30..e759536 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -310,7 +310,6 @@ parse_property_name (GScanner *scanner, ViviCodeValue **value)
return STATUS_CANCEL;
}
-// FIXME
static ParseStatus
parse_operator_expression (GScanner *scanner, ViviCodeValue **value);
@@ -334,7 +333,7 @@ parse_object_literal (GScanner *scanner, ViviCodeValue **value)
if (!check_token (scanner, ':'))
goto fail;
- // FIXME
+ // FIXME: assignment expression
if (parse_operator_expression (scanner, &initializer) != STATUS_OK)
goto fail;
@@ -371,8 +370,11 @@ parse_variable_declaration (GScanner *scanner, ViviCodeStatement **statement)
return status;
if (check_token (scanner, '=')) {
- // TODO
- return STATUS_FAIL;
+ // FIXME: assignment expression
+ if (parse_operator_expression (scanner, &value) != STATUS_OK) {
+ g_object_unref (identifier);
+ return STATUS_FAIL;
+ }
} else {
value = vivi_code_constant_new_undefined ();
}
@@ -405,9 +407,17 @@ parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
return STATUS_OK;
}
- /*if (check_token (scanner, '(')) {
+ if (check_token (scanner, '(')) {
+ // FIXME: assignment expression
+ if (parse_operator_expression (scanner, value) != STATUS_OK)
+ return STATUS_FAIL;
+ if (!check_token (scanner, ')')) {
+ g_object_unref (*value);
+ *value = NULL;
+ return STATUS_FAIL;
+ }
return STATUS_OK;
- }*/
+ }
for (i = 0; functions[i] != NULL; i++) {
status = functions[i] (scanner, value);
@@ -436,13 +446,13 @@ parse_member_expression (GScanner *scanner, ViviCodeValue **value)
do {
ViviCodeValue *tmp;
- /*if (check_token (scanner, '[')) {
- if (parse_expression (scanner, &member) != STATUS_OK)
+ if (check_token (scanner, '[')) {
+ // FIXME: expression
+ if (parse_operator_expression (scanner, &member) != STATUS_OK)
return STATUS_FAIL;
if (!check_token (scanner, ']'))
return STATUS_FAIL;
- } else*/
- if (check_token (scanner, '.')) {
+ } else if (check_token (scanner, '.')) {
if (parse_identifier (scanner, &member) != STATUS_OK)
return STATUS_FAIL;
} else {
commit d79a2eeb0ed4014ca408ba612d537b78e83cf0d1
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Sun Mar 30 02:51:42 2008 +0200
Parse object literals, except for side effects in initializers
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index ca66429..3d31c30 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -199,35 +199,82 @@ free_value_list (ViviCodeValue **list)
// values
static ParseStatus
-parse_literal (GScanner *scanner, ViviCodeValue **value)
+parse_null_literal (GScanner *scanner, ViviCodeValue **value)
{
*value = NULL;
- if (check_token (scanner, G_TOKEN_STRING)) {
- *value = vivi_code_constant_new_string (scanner->value.v_string);
- return STATUS_OK;
- } else if (check_token (scanner, G_TOKEN_FLOAT)) {
- *value = vivi_code_constant_new_number (scanner->value.v_float);
- return STATUS_OK;
- } else if (check_token (scanner, TOKEN_TRUE)) {
+ if (!check_token (scanner, TOKEN_NULL))
+ return STATUS_CANCEL;
+
+ *value = vivi_code_constant_new_null ();
+ return STATUS_OK;
+}
+
+static ParseStatus
+parse_boolean_literal (GScanner *scanner, ViviCodeValue **value)
+{
+ *value = NULL;
+
+ if (check_token (scanner, TOKEN_TRUE)) {
*value = vivi_code_constant_new_boolean (TRUE);
return STATUS_OK;
} else if (check_token (scanner, TOKEN_FALSE)) {
*value = vivi_code_constant_new_boolean (FALSE);
return STATUS_OK;
- } else if (check_token (scanner, TOKEN_NULL)) {
- *value = vivi_code_constant_new_null ();
- return STATUS_OK;
} else {
return STATUS_CANCEL;
}
+}
- *value = vivi_code_get_new_name (scanner->value.v_identifier);
+static ParseStatus
+parse_numeric_literal (GScanner *scanner, ViviCodeValue **value)
+{
+ *value = NULL;
+
+ if (!check_token (scanner, G_TOKEN_FLOAT))
+ return STATUS_CANCEL;
+ *value = vivi_code_constant_new_number (scanner->value.v_float);
return STATUS_OK;
}
static ParseStatus
+parse_string_literal (GScanner *scanner, ViviCodeValue **value)
+{
+ *value = NULL;
+
+ if (!check_token (scanner, G_TOKEN_STRING))
+ return STATUS_CANCEL;
+
+ *value = vivi_code_constant_new_string (scanner->value.v_string);
+ return STATUS_OK;
+}
+
+static ParseStatus
+parse_literal (GScanner *scanner, ViviCodeValue **value)
+{
+ int i;
+ ParseStatus status;
+ ParseValueFunction functions[] = {
+ parse_null_literal,
+ parse_boolean_literal,
+ parse_numeric_literal,
+ parse_string_literal,
+ NULL
+ };
+
+ *value = NULL;
+
+ for (i = 0; functions[i] != NULL; i++) {
+ status = functions[i] (scanner, value);
+ if (status != STATUS_CANCEL)
+ return status;
+ }
+
+ return STATUS_CANCEL;
+}
+
+static ParseStatus
parse_identifier (GScanner *scanner, ViviCodeValue **value)
{
*value = NULL;
@@ -240,6 +287,74 @@ parse_identifier (GScanner *scanner, ViviCodeValue **value)
return STATUS_OK;
}
+static ParseStatus
+parse_property_name (GScanner *scanner, ViviCodeValue **value)
+{
+ int i;
+ ParseStatus status;
+ ParseValueFunction functions[] = {
+ parse_identifier,
+ parse_string_literal,
+ parse_numeric_literal,
+ NULL
+ };
+
+ *value = NULL;
+
+ for (i = 0; functions[i] != NULL; i++) {
+ status = functions[i] (scanner, value);
+ if (status != STATUS_CANCEL)
+ return status;
+ }
+
+ return STATUS_CANCEL;
+}
+
+// FIXME
+static ParseStatus
+parse_operator_expression (GScanner *scanner, ViviCodeValue **value);
+
+static ParseStatus
+parse_object_literal (GScanner *scanner, ViviCodeValue **value)
+{
+ *value = NULL;
+
+ if (!check_token (scanner, '{'))
+ return STATUS_CANCEL;
+
+ *value = vivi_code_init_object_new ();
+
+ if (!check_token (scanner, '}')) {
+ do {
+ ViviCodeValue *property, *initializer;
+
+ if (parse_property_name (scanner, &property) != STATUS_OK)
+ goto fail;
+
+ if (!check_token (scanner, ':'))
+ goto fail;
+
+ // FIXME
+ if (parse_operator_expression (scanner, &initializer) != STATUS_OK)
+ goto fail;
+
+ vivi_code_init_object_add_variable (VIVI_CODE_INIT_OBJECT (*value),
+ property, initializer);
+ } while (check_token (scanner, ','));
+ }
+
+ if (!check_token (scanner, '}'))
+ goto fail;
+
+ return STATUS_OK;
+
+fail:
+
+ g_object_unref (*value);
+ *value = NULL;
+ return STATUS_FAIL;
+}
+
// misc
static ParseStatus
@@ -279,7 +394,7 @@ parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
parse_identifier,
parse_literal,
//parse_array_literal,
- //parse_object_literal,
+ parse_object_literal,
NULL
};
commit 0ac05be76f6d160b1f51f4096e8b16a71f267c6e
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Sun Mar 30 02:35:56 2008 +0200
Oops, fix a missing asterisk
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index c4b60c2..ca66429 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -760,7 +760,7 @@ parse_statement_list (GScanner *scanner, ParseStatementFunction function,
*block = vivi_code_block_new ();
do {
- vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), statement);
+ vivi_code_block_add_statement (VIVI_CODE_BLOCK (*block), statement);
g_object_unref (statement);
if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
commit cb9d2d4c8a957872e1219c4a96f6c2a3c169cc9c
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Sun Mar 30 02:27:54 2008 +0200
Make parse_statement_list give ViviCodeBlock instead of an array of statements
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index fa7f2dd..c4b60c2 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -168,7 +168,7 @@ typedef ParseStatus (*ParseValueFunction) (GScanner *scanner, ViviCodeValue **va
static ParseStatus
parse_statement_list (GScanner *scanner, ParseStatementFunction function,
- ViviCodeStatement ***list, guint separator);
+ ViviCodeStatement **statement, guint separator);
static ParseStatus
parse_value_list (GScanner *scanner, ParseValueFunction function,
ViviCodeValue ***list, guint separator);
@@ -186,17 +186,6 @@ check_token (GScanner *scanner, guint token)
}
static void
-free_statement_list (ViviCodeStatement **list)
-{
- int i;
-
- for (i = 0; list[i] != NULL; i++) {
- g_object_unref (list[i]);
- }
- g_free (list);
-}
-
-static void
free_value_list (ViviCodeValue **list)
{
int i;
@@ -207,21 +196,6 @@ free_value_list (ViviCodeValue **list)
g_free (list);
}
-static ViviCodeStatement *
-create_block (ViviCodeStatement **list)
-{
- ViviCodeBlock *block;
- int i;
-
- block = VIVI_CODE_BLOCK (vivi_code_block_new ());
-
- for (i = 0; list[i] != NULL; i++) {
- vivi_code_block_add_statement (block, list[i]);
- }
-
- return VIVI_CODE_STATEMENT (block);
-}
-
// values
static ParseStatus
@@ -542,20 +516,10 @@ parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement)
static ParseStatus
parse_expression (GScanner *scanner, ViviCodeStatement **statement)
{
- ViviCodeStatement **list;
- ParseStatus status;
-
*statement = NULL;
- status =
- parse_statement_list (scanner, parse_assignment_expression, &list, ',');
- if (status != STATUS_OK)
- return status;
-
- *statement = create_block (list);
- free_statement_list (list);
-
- return STATUS_OK;
+ return parse_statement_list (scanner, parse_assignment_expression, statement,
+ ',');
}
// statement
@@ -603,8 +567,6 @@ parse_statement (GScanner *scanner, ViviCodeStatement **statement);
static ParseStatus
parse_block (GScanner *scanner, ViviCodeStatement **statement)
{
- ViviCodeStatement **list;
-
*statement = NULL;
if (!check_token (scanner, '{'))
@@ -612,49 +574,40 @@ parse_block (GScanner *scanner, ViviCodeStatement **statement)
g_scanner_peek_next_token (scanner);
if (scanner->next_token != '}') {
- if (parse_statement_list (scanner, parse_statement, &list, G_TOKEN_NONE)
- != STATUS_OK)
+ if (parse_statement_list (scanner, parse_statement, statement,
+ G_TOKEN_NONE) != STATUS_OK)
return STATUS_FAIL;
} else {
- list = g_new0 (ViviCodeStatement *, 1);
+ *statement = vivi_code_block_new ();
}
if (!check_token (scanner, '}')) {
- free_statement_list (list);
+ g_object_unref (*statement);
+ *statement = NULL;
return STATUS_FAIL;
}
- *statement = create_block (list);
- free_statement_list (list);
-
return STATUS_OK;
}
static ParseStatus
parse_variable_statement (GScanner *scanner, ViviCodeStatement **statement)
{
- ViviCodeStatement **list;
- ParseStatus status;
-
*statement = NULL;
- if (!check_token (scanner, TOKEN_VAR)) {
+ if (!check_token (scanner, TOKEN_VAR))
return STATUS_CANCEL;
- }
- status =
- parse_statement_list (scanner, parse_variable_declaration, &list, ',');
- if (status != STATUS_OK)
- return status;
+ if (parse_statement_list (scanner, parse_variable_declaration, statement,
+ ',') != STATUS_OK)
+ return STATUS_FAIL;
if (!check_token (scanner, ';')) {
- free_statement_list (list);
+ g_object_unref (*statement);
+ *statement = NULL;
return STATUS_FAIL;
}
- *statement = create_block (list);
- free_statement_list (list);
-
return STATUS_OK;
}
@@ -702,7 +655,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
//ViviCodeStatement *function;
ViviCodeValue *identifier;
ViviCodeValue **arguments;
- ViviCodeStatement **body;
+ ViviCodeStatement *body;
*statement = NULL;
@@ -745,7 +698,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
if (arguments != NULL)
free_value_list (arguments);
if (body != NULL)
- free_statement_list (body);
+ g_object_unref (body);
return STATUS_OK;
@@ -755,7 +708,7 @@ fail:
if (arguments != NULL)
free_value_list (arguments);
if (body != NULL)
- free_statement_list (body);
+ g_object_unref (body);
return STATUS_FAIL;
}
@@ -779,54 +732,47 @@ parse_source_element (GScanner *scanner, ViviCodeStatement **statement)
static ParseStatus
parse_program (GScanner *scanner, ViviCodeStatement **statement)
{
- ParseStatus status;
- ViviCodeStatement **list;
-
*statement = NULL;
- status = parse_statement_list (scanner, parse_source_element, &list,
+ return parse_statement_list (scanner, parse_source_element, statement,
G_TOKEN_NONE);
- if (status != STATUS_OK)
- return status;
-
- *statement = create_block (list);
-
- return STATUS_OK;
}
// parsing
static ParseStatus
parse_statement_list (GScanner *scanner, ParseStatementFunction function,
- ViviCodeStatement ***list, guint separator)
+ ViviCodeStatement **block, guint separator)
{
- GPtrArray *array;
ViviCodeStatement *statement;
ParseStatus status;
g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
g_return_val_if_fail (function != NULL, STATUS_FAIL);
- g_return_val_if_fail (list != NULL, STATUS_FAIL);
+ g_return_val_if_fail (block != NULL, STATUS_FAIL);
+
+ *block = NULL;
status = function (scanner, &statement);
if (status != STATUS_OK)
return status;
- array = g_ptr_array_new ();
+ *block = vivi_code_block_new ();
do {
- g_ptr_array_add (array, statement);
+ vivi_code_block_add_statement (VIVI_CODE_BLOCK (block), statement);
+ g_object_unref (statement);
if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
break;
status = function (scanner, &statement);
- if (status == STATUS_FAIL)
+ if (status == STATUS_FAIL) {
+ g_object_unref (*block);
+ *block = NULL;
return STATUS_FAIL;
+ }
} while (status == STATUS_OK);
- g_ptr_array_add (array, NULL);
-
- *list = (ViviCodeStatement **)g_ptr_array_free (array, FALSE);
return STATUS_OK;
}
commit 110f3e73417235ea2a30f826b3368bd7df82d77d
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Sun Mar 30 02:15:03 2008 +0200
parse_statement_symbol can now be called parse_statement
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 481b487..fa7f2dd 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -598,7 +598,7 @@ parse_empty_statement (GScanner *scanner, ViviCodeStatement **statement)
}
static ParseStatus
-parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement);
+parse_statement (GScanner *scanner, ViviCodeStatement **statement);
static ParseStatus
parse_block (GScanner *scanner, ViviCodeStatement **statement)
@@ -612,8 +612,8 @@ parse_block (GScanner *scanner, ViviCodeStatement **statement)
g_scanner_peek_next_token (scanner);
if (scanner->next_token != '}') {
- if (parse_statement_list (scanner, parse_statement_symbol, &list,
- G_TOKEN_NONE) != STATUS_OK)
+ if (parse_statement_list (scanner, parse_statement, &list, G_TOKEN_NONE)
+ != STATUS_OK)
return STATUS_FAIL;
} else {
list = g_new0 (ViviCodeStatement *, 1);
@@ -659,7 +659,7 @@ parse_variable_statement (GScanner *scanner, ViviCodeStatement **statement)
}
static ParseStatus
-parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement)
+parse_statement (GScanner *scanner, ViviCodeStatement **statement)
{
int i, status;
ParseStatementFunction functions[] = {
@@ -771,7 +771,7 @@ parse_source_element (GScanner *scanner, ViviCodeStatement **statement)
status = parse_function_declaration (scanner, statement);
if (status == STATUS_CANCEL)
- status = parse_statement_symbol (scanner, statement);
+ status = parse_statement (scanner, statement);
return status;
}
commit db25fcdf7b424e81a9ada1cae588d5e54f9a6f54
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Sun Mar 30 02:13:52 2008 +0200
Make parse_value_list and parse_statement_list take function instead of symbol
Got rid of the whole symbol definitions
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index c9c7f24..481b487 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -163,69 +163,14 @@ static const TokenDescription custom_tokens[] = {
{ G_TOKEN_NONE, NULL }
};
-typedef enum {
- SYMBOL_NONE,
- // top
- SYMBOL_PROGRAM,
- SYMBOL_SOURCE_ELEMENT,
- // function
- SYMBOL_FUNCTION_DECLARATION,
- // statement
- SYMBOL_STATEMENT,
- SYMBOL_BLOCK,
- SYMBOL_VARIABLE_STATEMENT,
- SYMBOL_EMPTY_STATEMENT,
- SYMBOL_EXPRESSION_STATEMENT,
- SYMBOL_IF_STATEMENT,
- SYMBOL_ITERATION_STATEMENT,
- SYMBOL_CONTINUE_STATEMENT,
- SYMBOL_BREAK_STATEMENT,
- SYMBOL_RETURN_STATEMENT,
- SYMBOL_WITH_STATEMENT,
- SYMBOL_LABELLED_STATEMENT,
- SYMBOL_SWITCH_STATEMENT,
- SYMBOL_THROW_STATEMENT,
- SYMBOL_TRY_STATEMENT,
- // expression
- SYMBOL_EXPRESSION,
- SYMBOL_ASSIGNMENT_EXPRESSION,
- SYMBOL_CONDITIONAL_EXPRESSION,
- SYMBOL_LEFT_HAND_SIDE_EXPRESSION,
- SYMBOL_OPERATOR_EXPRESSION,
- SYMBOL_UNARY_EXPRESSION,
- SYMBOL_POSTFIX_EXPRESSION,
- SYMBOL_NEW_EXPRESSION,
- SYMBOL_CALL_EXPRESSION,
- SYMBOL_MEMBER_EXPRESSION,
- SYMBOL_FUNCTION_EXPRESSION,
- SYMBOL_PRIMARY_EXPRESSION,
- // values
- SYMBOL_IDENTIFIER,
- SYMBOL_LITERAL,
- SYMBOL_ARRAY_LITERAL,
- SYMBOL_OBJECT_LITERAL,
- // misc
- SYMBOL_VARIABLE_DECLARATION,
- SYMBOL_ASSIGNMENT_OPERATOR,
- SYMBOL_ARGUMENTS,
-} ParseSymbol;
-
typedef ParseStatus (*ParseStatementFunction) (GScanner *scanner, ViviCodeStatement **statement);
typedef ParseStatus (*ParseValueFunction) (GScanner *scanner, ViviCodeValue **value);
static ParseStatus
-parse_statement (GScanner *scanner, ParseSymbol symbol,
- ViviCodeStatement **statement);
-
-static ParseStatus
-parse_value (GScanner *scanner, ParseSymbol symbol, ViviCodeValue **value);
-
-static ParseStatus
-parse_statement_list (GScanner *scanner, ParseSymbol symbol,
+parse_statement_list (GScanner *scanner, ParseStatementFunction function,
ViviCodeStatement ***list, guint separator);
-
static ParseStatus
-parse_value_list (GScanner *scanner, ParseSymbol symbol,
+parse_value_list (GScanner *scanner, ParseValueFunction function,
ViviCodeValue ***list, guint separator);
// helpers
@@ -603,7 +548,7 @@ parse_expression (GScanner *scanner, ViviCodeStatement **statement)
*statement = NULL;
status =
- parse_statement_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
+ parse_statement_list (scanner, parse_assignment_expression, &list, ',');
if (status != STATUS_OK)
return status;
@@ -653,6 +598,9 @@ parse_empty_statement (GScanner *scanner, ViviCodeStatement **statement)
}
static ParseStatus
+parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement);
+
+static ParseStatus
parse_block (GScanner *scanner, ViviCodeStatement **statement)
{
ViviCodeStatement **list;
@@ -664,8 +612,8 @@ parse_block (GScanner *scanner, ViviCodeStatement **statement)
g_scanner_peek_next_token (scanner);
if (scanner->next_token != '}') {
- if (parse_statement_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
- != STATUS_OK)
+ if (parse_statement_list (scanner, parse_statement_symbol, &list,
+ G_TOKEN_NONE) != STATUS_OK)
return STATUS_FAIL;
} else {
list = g_new0 (ViviCodeStatement *, 1);
@@ -695,7 +643,7 @@ parse_variable_statement (GScanner *scanner, ViviCodeStatement **statement)
}
status =
- parse_statement_list (scanner, SYMBOL_VARIABLE_DECLARATION, &list, ',');
+ parse_statement_list (scanner, parse_variable_declaration, &list, ',');
if (status != STATUS_OK)
return status;
@@ -746,6 +694,9 @@ parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement)
// function
static ParseStatus
+parse_source_element (GScanner *scanner, ViviCodeStatement **statement);
+
+static ParseStatus
parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
{
//ViviCodeStatement *function;
@@ -768,7 +719,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
if (!check_token (scanner, '('))
goto fail;
- if (parse_value_list (scanner, SYMBOL_IDENTIFIER, &arguments, ',') ==
+ if (parse_value_list (scanner, parse_identifier, &arguments, ',') ==
STATUS_FAIL)
goto fail;
@@ -778,7 +729,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
if (!check_token (scanner, '{'))
goto fail;
- if (parse_statement_list (scanner, SYMBOL_SOURCE_ELEMENT, &body, G_TOKEN_NONE)
+ if (parse_statement_list (scanner, parse_source_element, &body, G_TOKEN_NONE)
== STATUS_FAIL)
goto fail;
@@ -833,7 +784,7 @@ parse_program (GScanner *scanner, ViviCodeStatement **statement)
*statement = NULL;
- status = parse_statement_list (scanner, SYMBOL_SOURCE_ELEMENT, &list,
+ status = parse_statement_list (scanner, parse_source_element, &list,
G_TOKEN_NONE);
if (status != STATUS_OK)
return status;
@@ -845,119 +796,8 @@ parse_program (GScanner *scanner, ViviCodeStatement **statement)
// parsing
-typedef struct {
- ParseSymbol id;
- const char * name;
- ParseStatementFunction parse;
-} SymbolStatementFunctionList;
-
-static const SymbolStatementFunctionList statement_symbols[] = {
- // top
- { SYMBOL_PROGRAM, "Program", parse_program },
- { SYMBOL_SOURCE_ELEMENT, "SourceElement", parse_source_element },
- // function
- { SYMBOL_FUNCTION_DECLARATION, "FunctionDeclaration",
- parse_function_declaration },
- // statement
- { SYMBOL_STATEMENT, "Statement", parse_statement_symbol },
- { SYMBOL_BLOCK, "Block", parse_block },
- { SYMBOL_VARIABLE_STATEMENT, "VariableStatement", parse_variable_statement },
- { SYMBOL_EMPTY_STATEMENT, "EmptyStatement", parse_empty_statement },
- { SYMBOL_EXPRESSION_STATEMENT, "ExpressionStatement",
- parse_expression_statement },
- /*{ SYMBOL_IF_STATEMENT, "IfStatement", parse_if_statement },
- { SYMBOL_ITERATION_STATEMENT, "IterationStatement",
- parse_iteration_statement },
- { SYMBOL_CONTINUE_STATEMENT, "ContinueStatement", parse_continue_statement },
- { SYMBOL_BREAK_STATEMENT, "BreakStatement", parse_break_statement },
- { SYMBOL_RETURN_STATEMENT, "ReturnStatement", parse_return_statement },
- { SYMBOL_WITH_STATEMENT, "WithStatement", parse_with_statement },
- { SYMBOL_LABELLED_STATEMENT, "LabelledStatement", parse_labelled_statement },
- { SYMBOL_SWITCH_STATEMENT, "SwitchStatement", parse_switch_statement },
- { SYMBOL_THROW_STATEMENT, "ThrowStatement", parse_throw_statement },
- { SYMBOL_TRY_STATEMENT, "TryStatement", parse_try_statement },*/
- // expression
- { SYMBOL_EXPRESSION, "Expression", parse_expression },
- { SYMBOL_ASSIGNMENT_EXPRESSION, "AssigmentExpression",
- parse_assignment_expression },
- { SYMBOL_CONDITIONAL_EXPRESSION, "ConditionalExpression",
- parse_conditional_expression },
- // misc
- { SYMBOL_VARIABLE_DECLARATION, "VariableDeclaration",
- parse_variable_declaration },
- { SYMBOL_NONE, NULL, NULL }
-};
-
-typedef struct {
- ParseSymbol id;
- const char * name;
- ParseValueFunction parse;
-} SymbolValueFunctionList;
-
-static const SymbolValueFunctionList value_symbols[] = {
- // expression
- { SYMBOL_OPERATOR_EXPRESSION, "OperatorExpression",
- parse_operator_expression },
- { SYMBOL_UNARY_EXPRESSION, "UnaryExpression", parse_unary_expression },
- { SYMBOL_POSTFIX_EXPRESSION, "PostfixExpression", parse_postfix_expression },
- { SYMBOL_LEFT_HAND_SIDE_EXPRESSION, "LeftHandSideExpression",
- parse_left_hand_side_expression },
- { SYMBOL_NEW_EXPRESSION, "NewExpression", parse_new_expression },
- { SYMBOL_MEMBER_EXPRESSION, "MemberExpression", parse_member_expression },
- { SYMBOL_PRIMARY_EXPRESSION, "PrimaryExpression", parse_primary_expression },
- // value
- { SYMBOL_IDENTIFIER, "Identifier", parse_identifier },
- { SYMBOL_LITERAL, "Literal", parse_literal },
- { SYMBOL_NONE, NULL, NULL }
-};
-
-static ParseStatus
-parse_statement (GScanner *scanner, ParseSymbol symbol,
- ViviCodeStatement **statement)
-{
- int i;
-
- g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
- g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
- g_return_val_if_fail (statement != NULL, STATUS_FAIL);
-
- for (i = 0; statement_symbols[i].id != SYMBOL_NONE; i++) {
- if (statement_symbols[i].id == symbol) {
- ParseStatus status = statement_symbols[i].parse (scanner, statement);
- g_assert ((status == STATUS_OK && VIVI_IS_CODE_TOKEN (*statement)) ||
- (status != STATUS_OK && *statement == NULL));
- return status;
- }
- }
-
- //g_assert_not_reached ();
- return STATUS_CANCEL;
-}
-
-static ParseStatus
-parse_value (GScanner *scanner, ParseSymbol symbol, ViviCodeValue **value)
-{
- int i;
-
- g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
- g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
- g_return_val_if_fail (value != NULL, STATUS_FAIL);
-
- for (i = 0; value_symbols[i].id != SYMBOL_NONE; i++) {
- if (value_symbols[i].id == symbol) {
- ParseStatus status = value_symbols[i].parse (scanner, value);
- g_assert ((status == STATUS_OK && VIVI_IS_CODE_TOKEN (*value)) ||
- (status != STATUS_OK && *value == NULL));
- return status;
- }
- }
-
- //g_assert_not_reached ();
- return STATUS_CANCEL;
-}
-
static ParseStatus
-parse_statement_list (GScanner *scanner, ParseSymbol symbol,
+parse_statement_list (GScanner *scanner, ParseStatementFunction function,
ViviCodeStatement ***list, guint separator)
{
GPtrArray *array;
@@ -965,10 +805,10 @@ parse_statement_list (GScanner *scanner, ParseSymbol symbol,
ParseStatus status;
g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
- g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
+ g_return_val_if_fail (function != NULL, STATUS_FAIL);
g_return_val_if_fail (list != NULL, STATUS_FAIL);
- status = parse_statement (scanner, symbol, &statement);
+ status = function (scanner, &statement);
if (status != STATUS_OK)
return status;
@@ -980,7 +820,7 @@ parse_statement_list (GScanner *scanner, ParseSymbol symbol,
if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
break;
- status = parse_statement (scanner, symbol, &statement);
+ status = function (scanner, &statement);
if (status == STATUS_FAIL)
return STATUS_FAIL;
} while (status == STATUS_OK);
@@ -992,18 +832,18 @@ parse_statement_list (GScanner *scanner, ParseSymbol symbol,
}
static ParseStatus
-parse_value_list (GScanner *scanner, ParseSymbol symbol, ViviCodeValue ***list,
- guint separator)
+parse_value_list (GScanner *scanner, ParseValueFunction function,
+ ViviCodeValue ***list, guint separator)
{
GPtrArray *array;
ViviCodeValue *value;
ParseStatus status;
g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
- g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
+ g_return_val_if_fail (function != NULL, STATUS_FAIL);
g_return_val_if_fail (list != NULL, STATUS_FAIL);
- status = parse_value (scanner, symbol, &value);
+ status = function (scanner, &value);
if (status != STATUS_OK)
return status;
@@ -1015,7 +855,7 @@ parse_value_list (GScanner *scanner, ParseSymbol symbol, ViviCodeValue ***list,
if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
break;
- status = parse_value (scanner, symbol, &value);
+ status = function (scanner, &value);
if (status == STATUS_FAIL)
return STATUS_FAIL;
} while (status == STATUS_OK);
@@ -1059,7 +899,7 @@ vivi_compile_text (const char *text, gsize len, const char *input_name)
scanner->input_name = input_name;
g_scanner_input_text (scanner, text, len);
- status = parse_statement (scanner, SYMBOL_PROGRAM, &statement);
+ status = parse_program (scanner, &statement);
g_assert ((status == STATUS_OK && VIVI_IS_CODE_STATEMENT (statement)) ||
(status != STATUS_OK && statement == NULL));
commit 8daea1d58c670d413e26640187741b359c6c5dc0
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Sun Mar 30 02:06:49 2008 +0200
Don't use the parse_statment and parse_value functions, but call directly
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 6746ff6..c9c7f24 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -332,7 +332,7 @@ parse_variable_declaration (GScanner *scanner, ViviCodeStatement **statement)
*statement = NULL;
- status = parse_value (scanner, SYMBOL_IDENTIFIER, &identifier);
+ status = parse_identifier (scanner, &identifier);
if (status != STATUS_OK)
return status;
@@ -356,12 +356,12 @@ parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
{
int i;
ParseStatus status;
- ParseSymbol options[] = {
- SYMBOL_IDENTIFIER,
- SYMBOL_LITERAL,
- SYMBOL_ARRAY_LITERAL,
- SYMBOL_OBJECT_LITERAL,
- SYMBOL_NONE
+ ParseValueFunction functions[] = {
+ parse_identifier,
+ parse_literal,
+ //parse_array_literal,
+ //parse_object_literal,
+ NULL
};
*value = NULL;
@@ -375,8 +375,8 @@ parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
return STATUS_OK;
}*/
- for (i = 0; options[i] != SYMBOL_NONE; i++) {
- status = parse_value (scanner, options[i], value);
+ for (i = 0; functions[i] != NULL; i++) {
+ status = functions[i] (scanner, value);
if (status != STATUS_CANCEL)
return status;
}
@@ -392,9 +392,9 @@ parse_member_expression (GScanner *scanner, ViviCodeValue **value)
// TODO: new MemberExpression Arguments
- status = parse_value (scanner, SYMBOL_PRIMARY_EXPRESSION, value);
- if (status == STATUS_CANCEL)
- status = parse_value (scanner, SYMBOL_FUNCTION_EXPRESSION, value);
+ status = parse_primary_expression (scanner, value);
+ //if (status == STATUS_CANCEL)
+ // status = parse_function_expression (scanner, value);
if (status != 0)
return status;
@@ -402,13 +402,14 @@ parse_member_expression (GScanner *scanner, ViviCodeValue **value)
do {
ViviCodeValue *tmp;
- if (check_token (scanner, '[')) {
- if (parse_value (scanner, SYMBOL_EXPRESSION, &member) != STATUS_OK)
+ /*if (check_token (scanner, '[')) {
+ if (parse_expression (scanner, &member) != STATUS_OK)
return STATUS_FAIL;
if (!check_token (scanner, ']'))
return STATUS_FAIL;
- } else if (check_token (scanner, '.')) {
- if (parse_value (scanner, SYMBOL_IDENTIFIER, &member) != STATUS_OK)
+ } else*/
+ if (check_token (scanner, '.')) {
+ if (parse_identifier (scanner, &member) != STATUS_OK)
return STATUS_FAIL;
} else {
return STATUS_OK;
@@ -430,7 +431,7 @@ parse_new_expression (GScanner *scanner, ViviCodeValue **value)
*value = NULL;
if (check_token (scanner, TOKEN_NEW)) {
- if (parse_value (scanner, SYMBOL_NEW_EXPRESSION, value) != STATUS_OK)
+ if (parse_new_expression (scanner, value) != STATUS_OK)
return STATUS_FAIL;
if (!VIVI_IS_CODE_FUNCTION_CALL (*value)) {
ViviCodeValue *tmp = VIVI_CODE_VALUE (*value);
@@ -441,7 +442,7 @@ parse_new_expression (GScanner *scanner, ViviCodeValue **value)
TRUE);
return STATUS_OK;
} else {
- return parse_value (scanner, SYMBOL_MEMBER_EXPRESSION, value);
+ return parse_member_expression (scanner, value);
}
}
@@ -452,9 +453,9 @@ parse_left_hand_side_expression (GScanner *scanner, ViviCodeValue **value)
*value = NULL;
- status = parse_value (scanner, SYMBOL_NEW_EXPRESSION, value);
- if (status == STATUS_CANCEL)
- status = parse_value (scanner, SYMBOL_CALL_EXPRESSION, value);
+ status = parse_new_expression (scanner, value);
+ //if (status == STATUS_CANCEL)
+ // status = parse_call_expression (scanner, value);
return status;
}
@@ -464,7 +465,7 @@ parse_postfix_expression (GScanner *scanner, ViviCodeValue **value)
{
ParseStatus status;
- status = parse_value (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION, value);
+ status = parse_left_hand_side_expression (scanner, value);
if (status != STATUS_OK)
return status;
@@ -487,13 +488,13 @@ parse_unary_expression (GScanner *scanner, ViviCodeValue **value)
*value = NULL;
if (check_token (scanner, '!')) {
- parse_value (scanner, SYMBOL_UNARY_EXPRESSION, value);
+ parse_unary_expression (scanner, value);
tmp = VIVI_CODE_VALUE (*value);
*value = vivi_code_unary_new (tmp, '!');
g_object_unref (tmp);
return STATUS_OK;
} else {
- return parse_value (scanner, SYMBOL_POSTFIX_EXPRESSION, value);
+ return parse_postfix_expression (scanner, value);
}
}
@@ -506,7 +507,7 @@ parse_operator_expression (GScanner *scanner, ViviCodeValue **value)
*value = NULL;
- status = parse_value (scanner, SYMBOL_UNARY_EXPRESSION, value);
+ status = parse_unary_expression (scanner, value);
if (status != STATUS_OK)
return status;
@@ -514,7 +515,7 @@ parse_operator_expression (GScanner *scanner, ViviCodeValue **value)
if (!check_token (scanner, '+'))
return STATUS_OK;
- if (parse_value (scanner, SYMBOL_UNARY_EXPRESSION, &right) != STATUS_OK) {
+ if (parse_unary_expression (scanner, &right) != STATUS_OK) {
g_object_unref (*value);
*value = NULL;
return STATUS_FAIL;
@@ -533,6 +534,9 @@ parse_operator_expression (GScanner *scanner, ViviCodeValue **value)
}
static ParseStatus
+parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement);
+
+static ParseStatus
parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
{
ParseStatus status;
@@ -542,7 +546,7 @@ parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
*statement = NULL;
if_statement = NULL;
- status = parse_value (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
+ status = parse_operator_expression (scanner, &value);
if (status != STATUS_OK)
return status;
@@ -552,15 +556,13 @@ parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
return STATUS_OK;
}
- if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &if_statement) !=
- STATUS_OK)
+ if (parse_assignment_expression (scanner, &if_statement) != STATUS_OK)
goto fail;
if (!check_token (scanner, ':'))
goto fail;
- if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION,
- &else_statement) != STATUS_OK)
+ if (parse_assignment_expression (scanner, &else_statement) != STATUS_OK)
goto fail;
*statement = vivi_code_if_new (value);
@@ -589,7 +591,7 @@ parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement)
// TODO
- return parse_statement (scanner, SYMBOL_CONDITIONAL_EXPRESSION, statement);
+ return parse_conditional_expression (scanner, statement);
}
static ParseStatus
@@ -624,7 +626,7 @@ parse_expression_statement (GScanner *scanner, ViviCodeStatement **statement)
if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
return STATUS_CANCEL;
- status = parse_statement (scanner, SYMBOL_EXPRESSION, statement);
+ status = parse_expression (scanner, statement);
if (status != STATUS_OK)
return status;
@@ -712,28 +714,28 @@ static ParseStatus
parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement)
{
int i, status;
- ParseSymbol options[] = {
- SYMBOL_BLOCK,
- SYMBOL_VARIABLE_STATEMENT,
- SYMBOL_EMPTY_STATEMENT,
- SYMBOL_EXPRESSION_STATEMENT,
- SYMBOL_IF_STATEMENT,
- SYMBOL_ITERATION_STATEMENT,
- SYMBOL_CONTINUE_STATEMENT,
- SYMBOL_BREAK_STATEMENT,
- SYMBOL_RETURN_STATEMENT,
- SYMBOL_WITH_STATEMENT,
- SYMBOL_LABELLED_STATEMENT,
- SYMBOL_SWITCH_STATEMENT,
- SYMBOL_THROW_STATEMENT,
- SYMBOL_TRY_STATEMENT,
- SYMBOL_NONE
+ ParseStatementFunction functions[] = {
+ parse_block,
+ parse_variable_statement,
+ parse_empty_statement,
+ parse_expression_statement,
+ //parse_if_statement,
+ //parse_iteration_statement,
+ //parse_continue_statement,
+ //parse_break_statement,
+ //parse_return_statement,
+ //parse_with_statement,
+ //parse_labelled_statement,
+ //parse_switch_statement,
+ //parse_throw_statement,
+ //parse_try_statement,
+ NULL
};
*statement = NULL;
- for (i = 0; options[i] != SYMBOL_NONE; i++) {
- status = parse_statement (scanner, options[i], statement);
+ for (i = 0; functions[i] != NULL; i++) {
+ status = functions[i] (scanner, statement);
if (status != STATUS_CANCEL)
return status;
}
@@ -760,7 +762,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
if (!check_token (scanner, TOKEN_FUNCTION))
return STATUS_CANCEL;
- if (parse_value (scanner, SYMBOL_IDENTIFIER, &identifier) != STATUS_OK)
+ if (parse_identifier (scanner, &identifier) != STATUS_OK)
return STATUS_FAIL;
if (!check_token (scanner, '('))
@@ -816,10 +818,9 @@ parse_source_element (GScanner *scanner, ViviCodeStatement **statement)
*statement = NULL;
- status = parse_statement (scanner, SYMBOL_FUNCTION_DECLARATION, statement);
-
+ status = parse_function_declaration (scanner, statement);
if (status == STATUS_CANCEL)
- status = parse_statement (scanner, SYMBOL_STATEMENT, statement);
+ status = parse_statement_symbol (scanner, statement);
return status;
}
commit a31beb32b65b89b5944df8ea40bdd4d7a2c2710b
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Sun Mar 30 01:54:40 2008 +0200
Reorder some more functions in the compiler code
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 12db713..6746ff6 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -321,6 +321,296 @@ parse_identifier (GScanner *scanner, ViviCodeValue **value)
return STATUS_OK;
}
+// misc
+
+static ParseStatus
+parse_variable_declaration (GScanner *scanner, ViviCodeStatement **statement)
+{
+ ParseStatus status;
+ ViviCodeValue *identifier;
+ ViviCodeValue *value;
+
+ *statement = NULL;
+
+ status = parse_value (scanner, SYMBOL_IDENTIFIER, &identifier);
+ if (status != STATUS_OK)
+ return status;
+
+ if (check_token (scanner, '=')) {
+ // TODO
+ return STATUS_FAIL;
+ } else {
+ value = vivi_code_constant_new_undefined ();
+ }
+
+ *statement = vivi_code_assignment_new (NULL, identifier, value);
+ vivi_code_assignment_set_local (VIVI_CODE_ASSIGNMENT (*statement), TRUE);
+
+ return STATUS_OK;
+}
+
+// expression
+
+static ParseStatus
+parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
+{
+ int i;
+ ParseStatus status;
+ ParseSymbol options[] = {
+ SYMBOL_IDENTIFIER,
+ SYMBOL_LITERAL,
+ SYMBOL_ARRAY_LITERAL,
+ SYMBOL_OBJECT_LITERAL,
+ SYMBOL_NONE
+ };
+
+ *value = NULL;
+
+ if (check_token (scanner, TOKEN_THIS)) {
+ *value = vivi_code_get_new_name ("this");
+ return STATUS_OK;
+ }
+
+ /*if (check_token (scanner, '(')) {
+ return STATUS_OK;
+ }*/
+
+ for (i = 0; options[i] != SYMBOL_NONE; i++) {
+ status = parse_value (scanner, options[i], value);
+ if (status != STATUS_CANCEL)
+ return status;
+ }
+
+ return STATUS_CANCEL;
+}
+
+static ParseStatus
+parse_member_expression (GScanner *scanner, ViviCodeValue **value)
+{
+ ParseStatus status;
+ ViviCodeValue *member;
+
+ // TODO: new MemberExpression Arguments
+
+ status = parse_value (scanner, SYMBOL_PRIMARY_EXPRESSION, value);
+ if (status == STATUS_CANCEL)
+ status = parse_value (scanner, SYMBOL_FUNCTION_EXPRESSION, value);
+
+ if (status != 0)
+ return status;
+
+ do {
+ ViviCodeValue *tmp;
+
+ if (check_token (scanner, '[')) {
+ if (parse_value (scanner, SYMBOL_EXPRESSION, &member) != STATUS_OK)
+ return STATUS_FAIL;
+ if (!check_token (scanner, ']'))
+ return STATUS_FAIL;
+ } else if (check_token (scanner, '.')) {
+ if (parse_value (scanner, SYMBOL_IDENTIFIER, &member) != STATUS_OK)
+ return STATUS_FAIL;
+ } else {
+ return STATUS_OK;
+ }
+
+ tmp = *value;
+ *value = vivi_code_get_new (tmp, VIVI_CODE_VALUE (member));
+ g_object_unref (tmp);
+ g_object_unref (member);
+ } while (TRUE);
+
+ g_assert_not_reached ();
+ return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_new_expression (GScanner *scanner, ViviCodeValue **value)
+{
+ *value = NULL;
+
+ if (check_token (scanner, TOKEN_NEW)) {
+ if (parse_value (scanner, SYMBOL_NEW_EXPRESSION, value) != STATUS_OK)
+ return STATUS_FAIL;
+ if (!VIVI_IS_CODE_FUNCTION_CALL (*value)) {
+ ViviCodeValue *tmp = VIVI_CODE_VALUE (*value);
+ *value = vivi_code_function_call_new (NULL, tmp);
+ g_object_unref (tmp);
+ }
+ vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*value),
+ TRUE);
+ return STATUS_OK;
+ } else {
+ return parse_value (scanner, SYMBOL_MEMBER_EXPRESSION, value);
+ }
+}
+
+static ParseStatus
+parse_left_hand_side_expression (GScanner *scanner, ViviCodeValue **value)
+{
+ ParseStatus status;
+
+ *value = NULL;
+
+ status = parse_value (scanner, SYMBOL_NEW_EXPRESSION, value);
+ if (status == STATUS_CANCEL)
+ status = parse_value (scanner, SYMBOL_CALL_EXPRESSION, value);
+
+ return status;
+}
+
+static ParseStatus
+parse_postfix_expression (GScanner *scanner, ViviCodeValue **value)
+{
+ ParseStatus status;
+
+ status = parse_value (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION, value);
+ if (status != STATUS_OK)
+ return status;
+
+ // FIXME: Don't allow new line here
+
+ /*if (check_token (scanner, TOKEN_PLUSPLUS)) {
+ ViviCodeValue *tmp = *value;
+ *value = vivi_code_postfix_new (tmp, "++");
+ g_object_unref (tmp);
+ } else {*/
+ return STATUS_OK;
+ //}
+}
+
+static ParseStatus
+parse_unary_expression (GScanner *scanner, ViviCodeValue **value)
+{
+ ViviCodeValue *tmp;
+
+ *value = NULL;
+
+ if (check_token (scanner, '!')) {
+ parse_value (scanner, SYMBOL_UNARY_EXPRESSION, value);
+ tmp = VIVI_CODE_VALUE (*value);
+ *value = vivi_code_unary_new (tmp, '!');
+ g_object_unref (tmp);
+ return STATUS_OK;
+ } else {
+ return parse_value (scanner, SYMBOL_POSTFIX_EXPRESSION, value);
+ }
+}
+
+static ParseStatus
+parse_operator_expression (GScanner *scanner, ViviCodeValue **value)
+{
+ ParseStatus status;
+ ViviCodeValue *left;
+ ViviCodeValue *right;
+
+ *value = NULL;
+
+ status = parse_value (scanner, SYMBOL_UNARY_EXPRESSION, value);
+ if (status != STATUS_OK)
+ return status;
+
+ do {
+ if (!check_token (scanner, '+'))
+ return STATUS_OK;
+
+ if (parse_value (scanner, SYMBOL_UNARY_EXPRESSION, &right) != STATUS_OK) {
+ g_object_unref (*value);
+ *value = NULL;
+ return STATUS_FAIL;
+ }
+
+ left = VIVI_CODE_VALUE (*value);
+ *value = vivi_code_binary_new_name (left, VIVI_CODE_VALUE (right), "+");
+ g_object_unref (left);
+ g_object_unref (right);
+ } while (TRUE);
+
+ g_object_unref (*value);
+ *value = NULL;
+
+ return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
+{
+ ParseStatus status;
+ ViviCodeValue *value;
+ ViviCodeStatement *if_statement, *else_statement;
+
+ *statement = NULL;
+ if_statement = NULL;
+
+ status = parse_value (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
+ if (status != STATUS_OK)
+ return status;
+
+ if (!check_token (scanner, '?')) {
+ *statement = vivi_code_value_statement_new (VIVI_CODE_VALUE (value));
+ g_object_unref (value);
+ return STATUS_OK;
+ }
+
+ if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &if_statement) !=
+ STATUS_OK)
+ goto fail;
+
+ if (!check_token (scanner, ':'))
+ goto fail;
+
+ if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION,
+ &else_statement) != STATUS_OK)
+ goto fail;
+
+ *statement = vivi_code_if_new (value);
+ vivi_code_if_set_if (VIVI_CODE_IF (*statement), if_statement);
+ vivi_code_if_set_else (VIVI_CODE_IF (*statement), else_statement);
+
+ g_object_unref (value);
+ g_object_unref (if_statement);
+ g_object_unref (else_statement);
+
+ return STATUS_OK;
+
+fail:
+
+ g_object_unref (value);
+ if (if_statement != NULL)
+ g_object_unref (if_statement);
+
+ return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement)
+{
+ *statement = NULL;
+
+ // TODO
+
+ return parse_statement (scanner, SYMBOL_CONDITIONAL_EXPRESSION, statement);
+}
+
+static ParseStatus
+parse_expression (GScanner *scanner, ViviCodeStatement **statement)
+{
+ ViviCodeStatement **list;
+ ParseStatus status;
+
+ *statement = NULL;
+
+ status =
+ parse_statement_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
+ if (status != STATUS_OK)
+ return status;
+
+ *statement = create_block (list);
+ free_statement_list (list);
+
+ return STATUS_OK;
+}
+
// statement
static ParseStatus
@@ -418,12 +708,6 @@ parse_variable_statement (GScanner *scanner, ViviCodeStatement **statement)
return STATUS_OK;
}
-/*
- * if ((a = c) && (b = 1))
- *
- * a = c; if (a) { b = 1; if (b) }
- */
-
static ParseStatus
parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement)
{
@@ -558,296 +842,6 @@ parse_program (GScanner *scanner, ViviCodeStatement **statement)
return STATUS_OK;
}
-// expression
-
-static ParseStatus
-parse_expression (GScanner *scanner, ViviCodeStatement **statement)
-{
- ViviCodeStatement **list;
- ParseStatus status;
-
- *statement = NULL;
-
- status =
- parse_statement_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
- if (status != STATUS_OK)
- return status;
-
- *statement = create_block (list);
- free_statement_list (list);
-
- return STATUS_OK;
-}
-
-static ParseStatus
-parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement)
-{
- *statement = NULL;
-
- // TODO
-
- return parse_statement (scanner, SYMBOL_CONDITIONAL_EXPRESSION, statement);
-}
-
-static ParseStatus
-parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
-{
- ParseStatus status;
- ViviCodeValue *value;
- ViviCodeStatement *if_statement, *else_statement;
-
- *statement = NULL;
- if_statement = NULL;
-
- status = parse_value (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
- if (status != STATUS_OK)
- return status;
-
- if (!check_token (scanner, '?')) {
- *statement = vivi_code_value_statement_new (VIVI_CODE_VALUE (value));
- g_object_unref (value);
- return STATUS_OK;
- }
-
- if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &if_statement) !=
- STATUS_OK)
- goto fail;
-
- if (!check_token (scanner, ':'))
- goto fail;
-
- if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION,
- &else_statement) != STATUS_OK)
- goto fail;
-
- *statement = vivi_code_if_new (value);
- vivi_code_if_set_if (VIVI_CODE_IF (*statement), if_statement);
- vivi_code_if_set_else (VIVI_CODE_IF (*statement), else_statement);
-
- g_object_unref (value);
- g_object_unref (if_statement);
- g_object_unref (else_statement);
-
- return STATUS_OK;
-
-fail:
-
- g_object_unref (value);
- if (if_statement != NULL)
- g_object_unref (if_statement);
-
- return STATUS_FAIL;
-}
-
-static ParseStatus
-parse_operator_expression (GScanner *scanner, ViviCodeValue **value)
-{
- ParseStatus status;
- ViviCodeValue *left;
- ViviCodeValue *right;
-
- *value = NULL;
-
- status = parse_value (scanner, SYMBOL_UNARY_EXPRESSION, value);
- if (status != STATUS_OK)
- return status;
-
- do {
- if (!check_token (scanner, '+'))
- return STATUS_OK;
-
- if (parse_value (scanner, SYMBOL_UNARY_EXPRESSION, &right) != STATUS_OK) {
- g_object_unref (*value);
- *value = NULL;
- return STATUS_FAIL;
- }
-
- left = VIVI_CODE_VALUE (*value);
- *value = vivi_code_binary_new_name (left, VIVI_CODE_VALUE (right), "+");
- g_object_unref (left);
- g_object_unref (right);
- } while (TRUE);
-
- g_object_unref (*value);
- *value = NULL;
-
- return STATUS_FAIL;
-}
-
-static ParseStatus
-parse_unary_expression (GScanner *scanner, ViviCodeValue **value)
-{
- ViviCodeValue *tmp;
-
- *value = NULL;
-
- if (check_token (scanner, '!')) {
- parse_value (scanner, SYMBOL_UNARY_EXPRESSION, value);
- tmp = VIVI_CODE_VALUE (*value);
- *value = vivi_code_unary_new (tmp, '!');
- g_object_unref (tmp);
- return STATUS_OK;
- } else {
- return parse_value (scanner, SYMBOL_POSTFIX_EXPRESSION, value);
- }
-}
-
-static ParseStatus
-parse_postfix_expression (GScanner *scanner, ViviCodeValue **value)
-{
- ParseStatus status;
-
- status = parse_value (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION, value);
- if (status != STATUS_OK)
- return status;
-
- // FIXME: Don't allow new line here
-
- /*if (check_token (scanner, TOKEN_PLUSPLUS)) {
- ViviCodeValue *tmp = *value;
- *value = vivi_code_postfix_new (tmp, "++");
- g_object_unref (tmp);
- } else {*/
- return STATUS_OK;
- //}
-}
-
-static ParseStatus
-parse_left_hand_side_expression (GScanner *scanner, ViviCodeValue **value)
-{
- ParseStatus status;
-
- *value = NULL;
-
- status = parse_value (scanner, SYMBOL_NEW_EXPRESSION, value);
- if (status == STATUS_CANCEL)
- status = parse_value (scanner, SYMBOL_CALL_EXPRESSION, value);
-
- return status;
-}
-
-static ParseStatus
-parse_new_expression (GScanner *scanner, ViviCodeValue **value)
-{
- *value = NULL;
-
- if (check_token (scanner, TOKEN_NEW)) {
- if (parse_value (scanner, SYMBOL_NEW_EXPRESSION, value) != STATUS_OK)
- return STATUS_FAIL;
- if (!VIVI_IS_CODE_FUNCTION_CALL (*value)) {
- ViviCodeValue *tmp = VIVI_CODE_VALUE (*value);
- *value = vivi_code_function_call_new (NULL, tmp);
- g_object_unref (tmp);
- }
- vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*value),
- TRUE);
- return STATUS_OK;
- } else {
- return parse_value (scanner, SYMBOL_MEMBER_EXPRESSION, value);
- }
-}
-
-static ParseStatus
-parse_member_expression (GScanner *scanner, ViviCodeValue **value)
-{
- ParseStatus status;
- ViviCodeValue *member;
-
- // TODO: new MemberExpression Arguments
-
- status = parse_value (scanner, SYMBOL_PRIMARY_EXPRESSION, value);
- if (status == STATUS_CANCEL)
- status = parse_value (scanner, SYMBOL_FUNCTION_EXPRESSION, value);
-
- if (status != 0)
- return status;
-
- do {
- ViviCodeValue *tmp;
-
- if (check_token (scanner, '[')) {
- if (parse_value (scanner, SYMBOL_EXPRESSION, &member) != STATUS_OK)
- return STATUS_FAIL;
- if (!check_token (scanner, ']'))
- return STATUS_FAIL;
- } else if (check_token (scanner, '.')) {
- if (parse_value (scanner, SYMBOL_IDENTIFIER, &member) != STATUS_OK)
- return STATUS_FAIL;
- } else {
- return STATUS_OK;
- }
-
- tmp = *value;
- *value = vivi_code_get_new (tmp, VIVI_CODE_VALUE (member));
- g_object_unref (tmp);
- g_object_unref (member);
- } while (TRUE);
-
- g_assert_not_reached ();
- return STATUS_FAIL;
-}
-
-static ParseStatus
-parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
-{
- int i;
- ParseStatus status;
- ParseSymbol options[] = {
- SYMBOL_IDENTIFIER,
- SYMBOL_LITERAL,
- SYMBOL_ARRAY_LITERAL,
- SYMBOL_OBJECT_LITERAL,
- SYMBOL_NONE
- };
-
- *value = NULL;
-
- if (check_token (scanner, TOKEN_THIS)) {
- *value = vivi_code_get_new_name ("this");
- return STATUS_OK;
- }
-
- /*if (check_token (scanner, '(')) {
- return STATUS_OK;
- }*/
-
- for (i = 0; options[i] != SYMBOL_NONE; i++) {
- status = parse_value (scanner, options[i], value);
- if (status != STATUS_CANCEL)
- return status;
- }
-
- return STATUS_CANCEL;
-}
-
-// misc
-
-static ParseStatus
-parse_variable_declaration (GScanner *scanner, ViviCodeStatement **statement)
-{
- ParseStatus status;
- ViviCodeValue *identifier;
- ViviCodeValue *value;
-
- *statement = NULL;
-
- status = parse_value (scanner, SYMBOL_IDENTIFIER, &identifier);
- if (status != STATUS_OK)
- return status;
-
- if (check_token (scanner, '=')) {
- // TODO
- return STATUS_FAIL;
- } else {
- value = vivi_code_constant_new_undefined ();
- }
-
- *statement = vivi_code_assignment_new (NULL, identifier, value);
- vivi_code_assignment_set_local (VIVI_CODE_ASSIGNMENT (*statement), TRUE);
-
- return STATUS_OK;
-}
-
// parsing
typedef struct {
commit a02163032fc771d8ddf666bb7cb95b77e8c3a4f5
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Sat Mar 29 02:09:21 2008 +0200
Handle variable statements, except for assignments
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 5d20e07..12db713 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -205,6 +205,7 @@ typedef enum {
SYMBOL_ARRAY_LITERAL,
SYMBOL_OBJECT_LITERAL,
// misc
+ SYMBOL_VARIABLE_DECLARATION,
SYMBOL_ASSIGNMENT_OPERATOR,
SYMBOL_ARGUMENTS,
} ParseSymbol;
@@ -389,6 +390,34 @@ parse_block (GScanner *scanner, ViviCodeStatement **statement)
return STATUS_OK;
}
+static ParseStatus
+parse_variable_statement (GScanner *scanner, ViviCodeStatement **statement)
+{
+ ViviCodeStatement **list;
+ ParseStatus status;
+
+ *statement = NULL;
+
+ if (!check_token (scanner, TOKEN_VAR)) {
+ return STATUS_CANCEL;
+ }
+
+ status =
+ parse_statement_list (scanner, SYMBOL_VARIABLE_DECLARATION, &list, ',');
+ if (status != STATUS_OK)
+ return status;
+
+ if (!check_token (scanner, ';')) {
+ free_statement_list (list);
+ return STATUS_FAIL;
+ }
+
+ *statement = create_block (list);
+ free_statement_list (list);
+
+ return STATUS_OK;
+}
+
/*
* if ((a = c) && (b = 1))
*
@@ -761,7 +790,8 @@ parse_member_expression (GScanner *scanner, ViviCodeValue **value)
static ParseStatus
parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
{
- int i, status;
+ int i;
+ ParseStatus status;
ParseSymbol options[] = {
SYMBOL_IDENTIFIER,
SYMBOL_LITERAL,
@@ -790,6 +820,34 @@ parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
return STATUS_CANCEL;
}
+// misc
+
+static ParseStatus
+parse_variable_declaration (GScanner *scanner, ViviCodeStatement **statement)
+{
+ ParseStatus status;
+ ViviCodeValue *identifier;
+ ViviCodeValue *value;
+
+ *statement = NULL;
+
+ status = parse_value (scanner, SYMBOL_IDENTIFIER, &identifier);
+ if (status != STATUS_OK)
+ return status;
+
+ if (check_token (scanner, '=')) {
+ // TODO
+ return STATUS_FAIL;
+ } else {
+ value = vivi_code_constant_new_undefined ();
+ }
+
+ *statement = vivi_code_assignment_new (NULL, identifier, value);
+ vivi_code_assignment_set_local (VIVI_CODE_ASSIGNMENT (*statement), TRUE);
+
+ return STATUS_OK;
+}
+
// parsing
typedef struct {
@@ -808,7 +866,7 @@ static const SymbolStatementFunctionList statement_symbols[] = {
// statement
{ SYMBOL_STATEMENT, "Statement", parse_statement_symbol },
{ SYMBOL_BLOCK, "Block", parse_block },
- //{ SYMBOL_VARIABLE_STATEMENT, "VariableStatement", parse_variable_statement },
+ { SYMBOL_VARIABLE_STATEMENT, "VariableStatement", parse_variable_statement },
{ SYMBOL_EMPTY_STATEMENT, "EmptyStatement", parse_empty_statement },
{ SYMBOL_EXPRESSION_STATEMENT, "ExpressionStatement",
parse_expression_statement },
@@ -829,6 +887,9 @@ static const SymbolStatementFunctionList statement_symbols[] = {
parse_assignment_expression },
{ SYMBOL_CONDITIONAL_EXPRESSION, "ConditionalExpression",
parse_conditional_expression },
+ // misc
+ { SYMBOL_VARIABLE_DECLARATION, "VariableDeclaration",
+ parse_variable_declaration },
{ SYMBOL_NONE, NULL, NULL }
};
commit c7bc33c91f3e5e410615aee0cdfe91be54d1dd69
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Sat Mar 29 02:06:55 2008 +0200
ViviCodeAssignment: Handle varname for Get. Don't print out undefined if local
diff --git a/vivified/code/vivi_code_assignment.c b/vivified/code/vivi_code_assignment.c
index f8bbd36..af4c909 100644
--- a/vivified/code/vivi_code_assignment.c
+++ b/vivified/code/vivi_code_assignment.c
@@ -23,6 +23,7 @@
#include "vivi_code_assignment.h"
#include "vivi_code_constant.h"
+#include "vivi_code_get.h"
#include "vivi_code_printer.h"
G_DEFINE_TYPE (ViviCodeAssignment, vivi_code_assignment, VIVI_TYPE_CODE_STATEMENT)
@@ -46,10 +47,13 @@ vivi_code_assignment_print (ViviCodeToken *token, ViviCodePrinter*printer)
ViviCodeAssignment *assignment = VIVI_CODE_ASSIGNMENT (token);
char *varname;
- if (VIVI_IS_CODE_CONSTANT (assignment->name))
+ if (VIVI_IS_CODE_CONSTANT (assignment->name)) {
varname = vivi_code_constant_get_variable_name (VIVI_CODE_CONSTANT (assignment->name));
- else
+ } else if (VIVI_IS_CODE_GET (assignment->name)) {
+ varname = vivi_code_constant_get_variable_name (VIVI_CODE_CONSTANT (VIVI_CODE_GET (assignment->name)->name));
+ } else {
varname = NULL;
+ }
if (assignment->local)
vivi_code_printer_print (printer, "var ");
@@ -76,8 +80,12 @@ vivi_code_assignment_print (ViviCodeToken *token, ViviCodePrinter*printer)
goto finalize;
}
}
- vivi_code_printer_print (printer, " = ");
- vivi_code_printer_print_value (printer, assignment->value, VIVI_PRECEDENCE_ASSIGNMENT);
+ if (!assignment->local || !VIVI_IS_CODE_CONSTANT (assignment->value) ||
+ vivi_code_constant_get_value_type (
+ VIVI_CODE_CONSTANT (assignment->value)) != SWFDEC_AS_TYPE_UNDEFINED) {
+ vivi_code_printer_print (printer, " = ");
+ vivi_code_printer_print_value (printer, assignment->value, VIVI_PRECEDENCE_ASSIGNMENT);
+ }
g_free (varname);
finalize:
vivi_code_printer_print (printer, ";");
commit 0299f0eb67800da2b8f72cdff96beaedc7be55a0
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Sat Mar 29 01:16:18 2008 +0200
Reorder some functions in the compiler code
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index c9baced..5d20e07 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -276,39 +276,156 @@ create_block (ViviCodeStatement **list)
return VIVI_CODE_STATEMENT (block);
}
-// top
+// values
static ParseStatus
-parse_program (GScanner *scanner, ViviCodeStatement **statement)
+parse_literal (GScanner *scanner, ViviCodeValue **value)
+{
+ *value = NULL;
+
+ if (check_token (scanner, G_TOKEN_STRING)) {
+ *value = vivi_code_constant_new_string (scanner->value.v_string);
+ return STATUS_OK;
+ } else if (check_token (scanner, G_TOKEN_FLOAT)) {
+ *value = vivi_code_constant_new_number (scanner->value.v_float);
+ return STATUS_OK;
+ } else if (check_token (scanner, TOKEN_TRUE)) {
+ *value = vivi_code_constant_new_boolean (TRUE);
+ return STATUS_OK;
+ } else if (check_token (scanner, TOKEN_FALSE)) {
+ *value = vivi_code_constant_new_boolean (FALSE);
+ return STATUS_OK;
+ } else if (check_token (scanner, TOKEN_NULL)) {
+ *value = vivi_code_constant_new_null ();
+ return STATUS_OK;
+ } else {
+ return STATUS_CANCEL;
+ }
+
+ *value = vivi_code_get_new_name (scanner->value.v_identifier);
+
+ return STATUS_OK;
+}
+
+static ParseStatus
+parse_identifier (GScanner *scanner, ViviCodeValue **value)
+{
+ *value = NULL;
+
+ if (!check_token (scanner, G_TOKEN_IDENTIFIER))
+ return STATUS_CANCEL;
+
+ *value = vivi_code_get_new_name (scanner->value.v_identifier);
+
+ return STATUS_OK;
+}
+
+// statement
+
+static ParseStatus
+parse_expression_statement (GScanner *scanner, ViviCodeStatement **statement)
{
ParseStatus status;
- ViviCodeStatement **list;
*statement = NULL;
- status = parse_statement_list (scanner, SYMBOL_SOURCE_ELEMENT, &list,
- G_TOKEN_NONE);
+ g_scanner_peek_next_token (scanner);
+ if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
+ return STATUS_CANCEL;
+
+ status = parse_statement (scanner, SYMBOL_EXPRESSION, statement);
if (status != STATUS_OK)
return status;
- *statement = create_block (list);
+ if (!check_token (scanner, ';')) {
+ g_object_unref (*statement);
+ *statement = NULL;
+ return STATUS_FAIL;
+ }
return STATUS_OK;
}
static ParseStatus
-parse_source_element (GScanner *scanner, ViviCodeStatement **statement)
+parse_empty_statement (GScanner *scanner, ViviCodeStatement **statement)
{
- ParseStatus status;
+ *statement = NULL;
+
+ if (!check_token (scanner, ';'))
+ return STATUS_CANCEL;
+
+ *statement = vivi_compiler_empty_statement_new ();
+
+ return STATUS_OK;
+}
+
+static ParseStatus
+parse_block (GScanner *scanner, ViviCodeStatement **statement)
+{
+ ViviCodeStatement **list;
*statement = NULL;
- status = parse_statement (scanner, SYMBOL_FUNCTION_DECLARATION, statement);
+ if (!check_token (scanner, '{'))
+ return STATUS_CANCEL;
- if (status == STATUS_CANCEL)
- status = parse_statement (scanner, SYMBOL_STATEMENT, statement);
+ g_scanner_peek_next_token (scanner);
+ if (scanner->next_token != '}') {
+ if (parse_statement_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
+ != STATUS_OK)
+ return STATUS_FAIL;
+ } else {
+ list = g_new0 (ViviCodeStatement *, 1);
+ }
- return status;
+ if (!check_token (scanner, '}')) {
+ free_statement_list (list);
+ return STATUS_FAIL;
+ }
+
+ *statement = create_block (list);
+ free_statement_list (list);
+
+ return STATUS_OK;
+}
+
+/*
+ * if ((a = c) && (b = 1))
+ *
+ * a = c; if (a) { b = 1; if (b) }
+ */
+
+static ParseStatus
+parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement)
+{
+ int i, status;
+ ParseSymbol options[] = {
+ SYMBOL_BLOCK,
+ SYMBOL_VARIABLE_STATEMENT,
+ SYMBOL_EMPTY_STATEMENT,
+ SYMBOL_EXPRESSION_STATEMENT,
+ SYMBOL_IF_STATEMENT,
+ SYMBOL_ITERATION_STATEMENT,
+ SYMBOL_CONTINUE_STATEMENT,
+ SYMBOL_BREAK_STATEMENT,
+ SYMBOL_RETURN_STATEMENT,
+ SYMBOL_WITH_STATEMENT,
+ SYMBOL_LABELLED_STATEMENT,
+ SYMBOL_SWITCH_STATEMENT,
+ SYMBOL_THROW_STATEMENT,
+ SYMBOL_TRY_STATEMENT,
+ SYMBOL_NONE
+ };
+
+ *statement = NULL;
+
+ for (i = 0; options[i] != SYMBOL_NONE; i++) {
+ status = parse_statement (scanner, options[i], statement);
+ if (status != STATUS_CANCEL)
+ return status;
+ }
+
+ return STATUS_CANCEL;
}
// function
@@ -377,104 +494,37 @@ fail:
return STATUS_FAIL;
}
-// statement
-
-static ParseStatus
-parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement)
-{
- int i, status;
- ParseSymbol options[] = {
- SYMBOL_BLOCK,
- SYMBOL_VARIABLE_STATEMENT,
- SYMBOL_EMPTY_STATEMENT,
- SYMBOL_EXPRESSION_STATEMENT,
- SYMBOL_IF_STATEMENT,
- SYMBOL_ITERATION_STATEMENT,
- SYMBOL_CONTINUE_STATEMENT,
- SYMBOL_BREAK_STATEMENT,
- SYMBOL_RETURN_STATEMENT,
- SYMBOL_WITH_STATEMENT,
- SYMBOL_LABELLED_STATEMENT,
- SYMBOL_SWITCH_STATEMENT,
- SYMBOL_THROW_STATEMENT,
- SYMBOL_TRY_STATEMENT,
- SYMBOL_NONE
- };
-
- *statement = NULL;
-
- for (i = 0; options[i] != SYMBOL_NONE; i++) {
- status = parse_statement (scanner, options[i], statement);
- if (status != STATUS_CANCEL)
- return status;
- }
-
- return STATUS_CANCEL;
-}
+// top
static ParseStatus
-parse_block (GScanner *scanner, ViviCodeStatement **statement)
+parse_source_element (GScanner *scanner, ViviCodeStatement **statement)
{
- ViviCodeStatement **list;
-
- *statement = NULL;
-
- if (!check_token (scanner, '{'))
- return STATUS_CANCEL;
-
- g_scanner_peek_next_token (scanner);
- if (scanner->next_token != '}') {
- if (parse_statement_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
- != STATUS_OK)
- return STATUS_FAIL;
- } else {
- list = g_new0 (ViviCodeStatement *, 1);
- }
-
- if (!check_token (scanner, '}')) {
- free_statement_list (list);
- return STATUS_FAIL;
- }
-
- *statement = create_block (list);
- free_statement_list (list);
-
- return STATUS_OK;
-}
+ ParseStatus status;
-static ParseStatus
-parse_empty_statement (GScanner *scanner, ViviCodeStatement **statement)
-{
*statement = NULL;
- if (!check_token (scanner, ';'))
- return STATUS_CANCEL;
+ status = parse_statement (scanner, SYMBOL_FUNCTION_DECLARATION, statement);
- *statement = vivi_compiler_empty_statement_new ();
+ if (status == STATUS_CANCEL)
+ status = parse_statement (scanner, SYMBOL_STATEMENT, statement);
- return STATUS_OK;
+ return status;
}
static ParseStatus
-parse_expression_statement (GScanner *scanner, ViviCodeStatement **statement)
+parse_program (GScanner *scanner, ViviCodeStatement **statement)
{
ParseStatus status;
+ ViviCodeStatement **list;
*statement = NULL;
- g_scanner_peek_next_token (scanner);
- if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
- return STATUS_CANCEL;
-
- status = parse_statement (scanner, SYMBOL_EXPRESSION, statement);
+ status = parse_statement_list (scanner, SYMBOL_SOURCE_ELEMENT, &list,
+ G_TOKEN_NONE);
if (status != STATUS_OK)
return status;
- if (!check_token (scanner, ';')) {
- g_object_unref (*statement);
- *statement = NULL;
- return STATUS_FAIL;
- }
+ *statement = create_block (list);
return STATUS_OK;
}
@@ -740,50 +790,6 @@ parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
return STATUS_CANCEL;
}
-// values
-
-static ParseStatus
-parse_identifier (GScanner *scanner, ViviCodeValue **value)
-{
- *value = NULL;
-
- if (!check_token (scanner, G_TOKEN_IDENTIFIER))
- return STATUS_CANCEL;
-
- *value = vivi_code_get_new_name (scanner->value.v_identifier);
-
- return STATUS_OK;
-}
-
-static ParseStatus
-parse_literal (GScanner *scanner, ViviCodeValue **value)
-{
- *value = NULL;
-
- if (check_token (scanner, G_TOKEN_STRING)) {
- *value = vivi_code_constant_new_string (scanner->value.v_string);
- return STATUS_OK;
- } else if (check_token (scanner, G_TOKEN_FLOAT)) {
- *value = vivi_code_constant_new_number (scanner->value.v_float);
- return STATUS_OK;
- } else if (check_token (scanner, TOKEN_TRUE)) {
- *value = vivi_code_constant_new_boolean (TRUE);
- return STATUS_OK;
- } else if (check_token (scanner, TOKEN_FALSE)) {
- *value = vivi_code_constant_new_boolean (FALSE);
- return STATUS_OK;
- } else if (check_token (scanner, TOKEN_NULL)) {
- *value = vivi_code_constant_new_null ();
- return STATUS_OK;
- } else {
- return STATUS_CANCEL;
- }
-
- *value = vivi_code_get_new_name (scanner->value.v_identifier);
-
- return STATUS_OK;
-}
-
// parsing
typedef struct {
@@ -802,9 +808,21 @@ static const SymbolStatementFunctionList statement_symbols[] = {
// statement
{ SYMBOL_STATEMENT, "Statement", parse_statement_symbol },
{ SYMBOL_BLOCK, "Block", parse_block },
+ //{ SYMBOL_VARIABLE_STATEMENT, "VariableStatement", parse_variable_statement },
{ SYMBOL_EMPTY_STATEMENT, "EmptyStatement", parse_empty_statement },
{ SYMBOL_EXPRESSION_STATEMENT, "ExpressionStatement",
parse_expression_statement },
+ /*{ SYMBOL_IF_STATEMENT, "IfStatement", parse_if_statement },
+ { SYMBOL_ITERATION_STATEMENT, "IterationStatement",
+ parse_iteration_statement },
+ { SYMBOL_CONTINUE_STATEMENT, "ContinueStatement", parse_continue_statement },
+ { SYMBOL_BREAK_STATEMENT, "BreakStatement", parse_break_statement },
+ { SYMBOL_RETURN_STATEMENT, "ReturnStatement", parse_return_statement },
+ { SYMBOL_WITH_STATEMENT, "WithStatement", parse_with_statement },
+ { SYMBOL_LABELLED_STATEMENT, "LabelledStatement", parse_labelled_statement },
+ { SYMBOL_SWITCH_STATEMENT, "SwitchStatement", parse_switch_statement },
+ { SYMBOL_THROW_STATEMENT, "ThrowStatement", parse_throw_statement },
+ { SYMBOL_TRY_STATEMENT, "TryStatement", parse_try_statement },*/
// expression
{ SYMBOL_EXPRESSION, "Expression", parse_expression },
{ SYMBOL_ASSIGNMENT_EXPRESSION, "AssigmentExpression",
commit dccab3b02d3b2835862c0044e8b27edf9018bad1
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Sat Mar 29 00:40:04 2008 +0200
Add Ecma-262 keywords and reserved keywords
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 7e9e745..c9baced 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -54,14 +54,113 @@ typedef enum {
} ParseStatus;
enum {
- TOKEN_FUNCTION = G_TOKEN_LAST + 1,
- TOKEN_PLUSPLUS = G_TOKEN_LAST + 2,
- TOKEN_MINUSMINUS = G_TOKEN_LAST + 3,
- TOKEN_NEW = G_TOKEN_LAST + 4,
- TOKEN_TRUE = G_TOKEN_LAST + 5,
- TOKEN_FALSE = G_TOKEN_LAST + 6,
- TOKEN_NULL = G_TOKEN_LAST + 7,
- TOKEN_THIS = G_TOKEN_LAST + 8
+ // keywords
+ TOKEN_BREAK = G_TOKEN_LAST + 1,
+ TOKEN_CASE,
+ TOKEN_CATCH,
+ TOKEN_CONTINUE,
+ TOKEN_DEFAULT,
+ TOKEN_DELETE,
+ TOKEN_DO,
+ TOKEN_ELSE,
+ TOKEN_FINALLY,
+ TOKEN_FOR,
+ TOKEN_FUNCTION,
+ TOKEN_IF,
+ TOKEN_IN,
+ TOKEN_INSTANCEOF,
+ TOKEN_NEW,
+ TOKEN_RETURN,
+ TOKEN_SWITCH,
+ TOKEN_THIS,
+ TOKEN_THROW,
+ TOKEN_TRY,
+ TOKEN_TYPEOF,
+ TOKEN_VAR,
+ TOKEN_VOID,
+ TOKEN_WITH,
+ // reserved keywords
+ TOKEN_FUTURE,
+ // values
+ TOKEN_TRUE,
+ TOKEN_FALSE,
+ TOKEN_NULL,
+ // misc
+ TOKEN_PLUSPLUS,
+ TOKEN_MINUSMINUS
+};
+
+typedef struct {
+ guint token;
+ const char * symbol;
+} TokenDescription;
+
+static const TokenDescription custom_tokens[] = {
+ // keywords
+ { TOKEN_BREAK, "break" },
+ { TOKEN_CASE, "case" },
+ { TOKEN_CATCH, "catch" },
+ { TOKEN_CONTINUE, "continue" },
+ { TOKEN_DEFAULT, "default" },
+ { TOKEN_DELETE, "delete" },
+ { TOKEN_DO, "do" },
+ { TOKEN_ELSE, "else" },
+ { TOKEN_FINALLY, "finally" },
+ { TOKEN_FOR, "for" },
+ { TOKEN_FUNCTION, "function" },
+ { TOKEN_IF, "if" },
+ { TOKEN_IN, "in" },
+ { TOKEN_INSTANCEOF, "instanceof" },
+ { TOKEN_NEW, "new" },
+ { TOKEN_RETURN, "return" },
+ { TOKEN_SWITCH, "switch" },
+ { TOKEN_THIS, "this" },
+ { TOKEN_THROW, "throw" },
+ { TOKEN_TRY, "try" },
+ { TOKEN_TYPEOF, "typeof" },
+ { TOKEN_VAR, "var" },
+ { TOKEN_VOID, "while" },
+ { TOKEN_WITH, "with" },
+ // reserved keywords
+ { TOKEN_FUTURE, "abstract" },
+ { TOKEN_FUTURE, "boolean" },
+ { TOKEN_FUTURE, "byte" },
+ { TOKEN_FUTURE, "char" },
+ { TOKEN_FUTURE, "class" },
+ { TOKEN_FUTURE, "const" },
+ { TOKEN_FUTURE, "debugger" },
+ { TOKEN_FUTURE, "double" },
+ { TOKEN_FUTURE, "enum" },
+ { TOKEN_FUTURE, "export" },
+ { TOKEN_FUTURE, "extends" },
+ { TOKEN_FUTURE, "final" },
+ { TOKEN_FUTURE, "float" },
+ { TOKEN_FUTURE, "goto" },
+ { TOKEN_FUTURE, "implements" },
+ { TOKEN_FUTURE, "import" },
+ { TOKEN_FUTURE, "int" },
+ { TOKEN_FUTURE, "interface" },
+ { TOKEN_FUTURE, "long" },
+ { TOKEN_FUTURE, "native" },
+ { TOKEN_FUTURE, "package" },
+ { TOKEN_FUTURE, "private" },
+ { TOKEN_FUTURE, "protected" },
+ { TOKEN_FUTURE, "public" },
+ { TOKEN_FUTURE, "short" },
+ { TOKEN_FUTURE, "static" },
+ { TOKEN_FUTURE, "super" },
+ { TOKEN_FUTURE, "synchronized" },
+ { TOKEN_FUTURE, "throws" },
+ { TOKEN_FUTURE, "transient" },
+ { TOKEN_FUTURE, "volatile" },
+ // values
+ { TOKEN_TRUE, "true" },
+ { TOKEN_FALSE, "false" },
+ { TOKEN_NULL, "null" },
+ // misc
+ { TOKEN_PLUSPLUS, "++" },
+ { TOKEN_MINUSMINUS, "--" },
+ { G_TOKEN_NONE, NULL }
};
typedef enum {
@@ -861,6 +960,7 @@ vivi_compile_text (const char *text, gsize len, const char *input_name)
GScanner *scanner;
ViviCodeStatement *statement;
ParseStatus status;
+ int i;
g_return_val_if_fail (text != NULL, NULL);
@@ -877,13 +977,10 @@ vivi_compile_text (const char *text, gsize len, const char *input_name)
scanner->config->scan_identifier_1char = TRUE;
g_scanner_set_scope (scanner, 0);
- g_scanner_scope_add_symbol (scanner, 0, "function",
- GINT_TO_POINTER (TOKEN_FUNCTION));
- g_scanner_scope_add_symbol (scanner, 0, "++",
- GINT_TO_POINTER (TOKEN_PLUSPLUS));
- g_scanner_scope_add_symbol (scanner, 0, "--",
- GINT_TO_POINTER (TOKEN_MINUSMINUS));
- g_scanner_scope_add_symbol (scanner, 0, "new", GINT_TO_POINTER (TOKEN_NEW));
+ for (i = 0; custom_tokens[i].token != G_TOKEN_NONE; i++) {
+ g_scanner_scope_add_symbol (scanner, 0, custom_tokens[i].symbol,
+ GINT_TO_POINTER (custom_tokens[i].token));
+ }
scanner->input_name = input_name;
g_scanner_input_text (scanner, text, len);
commit 07687ebc5f3266e1e1a8928d4696db8ac0ddda2c
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Sat Mar 29 00:13:12 2008 +0200
No more secrets!
diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index 2d40e3c..a0d2807 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -90,16 +90,3 @@ vivi_compile_SOURCES = \
vivi_compile_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS)
vivi_compile_LDFLAGS = $(SWFDEC_LIBS)
vivi_compile_LDADD = libvivified-compiler.la
-
-if SECRET_TEST_CODE
-noinst_PROGRAMS += vivi-decompile-gtk
-
-vivi_decompile_gtk_SOURCES = \
- vivi_code_gtk_printer.c \
- vivi_code_gtk_printer.h \
- gtk_decompiler.c
-
-vivi_decompile_gtk_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(GTK_CFLAGS)
-vivi_decompile_gtk_LDFLAGS = $(SWFDEC_LIBS) $(GTK_LIBS)
-vivi_decompile_gtk_LDADD = libvivified-compiler.la
-endif
commit e54d550771c400bafa53a84d08aa1b6eb0d037b7
Merge: 9af10b3... 31434d2...
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Sat Mar 29 00:04:01 2008 +0200
Merge branch 'master' of ssh://medar@git.freedesktop.org/git/swfdec/swfdec
Conflicts:
vivified/code/Makefile.am
diff --cc vivified/code/Makefile.am
index a0d2807,57a7b4c..2d40e3c
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@@ -84,9 -80,15 +84,22 @@@ vivi_decompile_CFLAGS = $(GLOBAL_CFLAG
vivi_decompile_LDFLAGS = $(SWFDEC_LIBS)
vivi_decompile_LDADD = libvivified-compiler.la
+vivi_compile_SOURCES = \
+ compiler.c
+
+vivi_compile_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS)
+vivi_compile_LDFLAGS = $(SWFDEC_LIBS)
+vivi_compile_LDADD = libvivified-compiler.la
++
+ if SECRET_TEST_CODE
+ noinst_PROGRAMS += vivi-decompile-gtk
+
+ vivi_decompile_gtk_SOURCES = \
+ vivi_code_gtk_printer.c \
+ vivi_code_gtk_printer.h \
+ gtk_decompiler.c
+
+ vivi_decompile_gtk_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS) $(GTK_CFLAGS)
+ vivi_decompile_gtk_LDFLAGS = $(SWFDEC_LIBS) $(GTK_LIBS)
+ vivi_decompile_gtk_LDADD = libvivified-compiler.la
+ endif
commit 9af10b3fcd7589d54eba2b1960793c9a50c5580d
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Sat Mar 29 00:00:45 2008 +0200
Parse simple literals and conditional expressions. Allow 1char identifiers
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index e8ef2fa..7e9e745 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -57,7 +57,11 @@ enum {
TOKEN_FUNCTION = G_TOKEN_LAST + 1,
TOKEN_PLUSPLUS = G_TOKEN_LAST + 2,
TOKEN_MINUSMINUS = G_TOKEN_LAST + 3,
- TOKEN_NEW = G_TOKEN_LAST + 4
+ TOKEN_NEW = G_TOKEN_LAST + 4,
+ TOKEN_TRUE = G_TOKEN_LAST + 5,
+ TOKEN_FALSE = G_TOKEN_LAST + 6,
+ TOKEN_NULL = G_TOKEN_LAST + 7,
+ TOKEN_THIS = G_TOKEN_LAST + 8
};
typedef enum {
@@ -96,8 +100,12 @@ typedef enum {
SYMBOL_MEMBER_EXPRESSION,
SYMBOL_FUNCTION_EXPRESSION,
SYMBOL_PRIMARY_EXPRESSION,
- // misc
+ // values
SYMBOL_IDENTIFIER,
+ SYMBOL_LITERAL,
+ SYMBOL_ARRAY_LITERAL,
+ SYMBOL_OBJECT_LITERAL,
+ // misc
SYMBOL_ASSIGNMENT_OPERATOR,
SYMBOL_ARGUMENTS,
} ParseSymbol;
@@ -408,10 +416,10 @@ parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
{
ParseStatus status;
ViviCodeValue *value;
- ViviCodeStatement *first, *second;
+ ViviCodeStatement *if_statement, *else_statement;
*statement = NULL;
- first = NULL;
+ if_statement = NULL;
status = parse_value (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
if (status != STATUS_OK)
@@ -423,31 +431,32 @@ parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
return STATUS_OK;
}
- if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &first) !=
+ if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &if_statement) !=
STATUS_OK)
goto fail;
if (!check_token (scanner, ':'))
goto fail;
- if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &second) !=
- STATUS_OK)
+ if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION,
+ &else_statement) != STATUS_OK)
goto fail;
- //*statement = vivi_code_condional_new (VIVI_CODE_VALUE (value),
- // VIVI_CODE_STATEMENT (first), VIVI_CODE_STATEMENT (second));
+ *statement = vivi_code_if_new (value);
+ vivi_code_if_set_if (VIVI_CODE_IF (*statement), if_statement);
+ vivi_code_if_set_else (VIVI_CODE_IF (*statement), else_statement);
g_object_unref (value);
- g_object_unref (first);
- g_object_unref (second);
+ g_object_unref (if_statement);
+ g_object_unref (else_statement);
return STATUS_OK;
fail:
g_object_unref (value);
- if (first != NULL)
- g_object_unref (first);
+ if (if_statement != NULL)
+ g_object_unref (if_statement);
return STATUS_FAIL;
}
@@ -603,11 +612,36 @@ parse_member_expression (GScanner *scanner, ViviCodeValue **value)
static ParseStatus
parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
{
- // TODO
- return parse_value (scanner, SYMBOL_IDENTIFIER, value);
+ int i, status;
+ ParseSymbol options[] = {
+ SYMBOL_IDENTIFIER,
+ SYMBOL_LITERAL,
+ SYMBOL_ARRAY_LITERAL,
+ SYMBOL_OBJECT_LITERAL,
+ SYMBOL_NONE
+ };
+
+ *value = NULL;
+
+ if (check_token (scanner, TOKEN_THIS)) {
+ *value = vivi_code_get_new_name ("this");
+ return STATUS_OK;
+ }
+
+ /*if (check_token (scanner, '(')) {
+ return STATUS_OK;
+ }*/
+
+ for (i = 0; options[i] != SYMBOL_NONE; i++) {
+ status = parse_value (scanner, options[i], value);
+ if (status != STATUS_CANCEL)
+ return status;
+ }
+
+ return STATUS_CANCEL;
}
-// misc.
+// values
static ParseStatus
parse_identifier (GScanner *scanner, ViviCodeValue **value)
@@ -622,6 +656,35 @@ parse_identifier (GScanner *scanner, ViviCodeValue **value)
return STATUS_OK;
}
+static ParseStatus
+parse_literal (GScanner *scanner, ViviCodeValue **value)
+{
+ *value = NULL;
+
+ if (check_token (scanner, G_TOKEN_STRING)) {
+ *value = vivi_code_constant_new_string (scanner->value.v_string);
+ return STATUS_OK;
+ } else if (check_token (scanner, G_TOKEN_FLOAT)) {
+ *value = vivi_code_constant_new_number (scanner->value.v_float);
+ return STATUS_OK;
+ } else if (check_token (scanner, TOKEN_TRUE)) {
+ *value = vivi_code_constant_new_boolean (TRUE);
+ return STATUS_OK;
+ } else if (check_token (scanner, TOKEN_FALSE)) {
+ *value = vivi_code_constant_new_boolean (FALSE);
+ return STATUS_OK;
+ } else if (check_token (scanner, TOKEN_NULL)) {
+ *value = vivi_code_constant_new_null ();
+ return STATUS_OK;
+ } else {
+ return STATUS_CANCEL;
+ }
+
+ *value = vivi_code_get_new_name (scanner->value.v_identifier);
+
+ return STATUS_OK;
+}
+
// parsing
typedef struct {
@@ -669,8 +732,9 @@ static const SymbolValueFunctionList value_symbols[] = {
{ SYMBOL_NEW_EXPRESSION, "NewExpression", parse_new_expression },
{ SYMBOL_MEMBER_EXPRESSION, "MemberExpression", parse_member_expression },
{ SYMBOL_PRIMARY_EXPRESSION, "PrimaryExpression", parse_primary_expression },
- // misc
+ // value
{ SYMBOL_IDENTIFIER, "Identifier", parse_identifier },
+ { SYMBOL_LITERAL, "Literal", parse_literal },
{ SYMBOL_NONE, NULL, NULL }
};
@@ -805,6 +869,12 @@ vivi_compile_text (const char *text, gsize len, const char *input_name)
scanner->config->numbers_2_int = TRUE;
scanner->config->int_2_float = TRUE;
scanner->config->symbol_2_token = TRUE;
+ // FIXME: Should allow other Unicode characters
+ scanner->config->cset_identifier_first =
+ g_strdup (G_CSET_A_2_Z G_CSET_a_2_z G_CSET_LATINS G_CSET_LATINC "_$");
+ scanner->config->cset_identifier_nth = g_strdup (G_CSET_A_2_Z G_CSET_a_2_z
+ G_CSET_LATINS G_CSET_LATINC "_$" G_CSET_DIGITS);
+ scanner->config->scan_identifier_1char = TRUE;
g_scanner_set_scope (scanner, 0);
g_scanner_scope_add_symbol (scanner, 0, "function",
commit 0b76dda301be3f1acda0d70d203e1ab8be58c8fc
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Fri Mar 28 19:59:48 2008 +0200
Optimize empty statement and remove the useless need_braces function
diff --git a/vivified/code/vivi_compiler_empty_statement.c b/vivified/code/vivi_compiler_empty_statement.c
index 1cabdfd..568da2d 100644
--- a/vivified/code/vivi_compiler_empty_statement.c
+++ b/vivified/code/vivi_compiler_empty_statement.c
@@ -30,14 +30,7 @@ G_DEFINE_TYPE (ViviCompilerEmptyStatement, vivi_compiler_empty_statement, VIVI_T
static ViviCodeStatement *
vivi_compiler_empty_statement_optimize (ViviCodeStatement *statement)
{
- // FIXME
- return statement;
-}
-
-static gboolean
-vivi_compiler_empty_statement_needs_braces (ViviCodeStatement *stmt)
-{
- return FALSE;
+ return NULL;
}
static void
@@ -58,7 +51,6 @@ vivi_compiler_empty_statement_class_init (
token_class->print = vivi_compiler_empty_statement_print;
statement_class->optimize = vivi_compiler_empty_statement_optimize;
- statement_class->needs_braces = vivi_compiler_empty_statement_needs_braces;
}
static void
commit 60171ab83143fc6849bdefee240219cfd7bd7db7
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Fri Mar 28 19:59:06 2008 +0200
Rename CodeEmpty to CompilerEmptyStatement
diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index fc3cfd7..a0d2807 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -13,7 +13,6 @@ libvivified_compiler_la_SOURCES = \
vivi_code_comment.c \
vivi_code_constant.c \
vivi_code_continue.c \
- vivi_code_empty.c \
vivi_code_function.c \
vivi_code_function_call.c \
vivi_code_get.c \
@@ -33,6 +32,7 @@ libvivified_compiler_la_SOURCES = \
vivi_code_value.c \
vivi_code_value_statement.c \
vivi_compiler.c \
+ vivi_compiler_empty_statement.c \
vivi_decompiler_block.c \
vivi_decompiler_duplicate.c \
vivi_decompiler_state.c \
@@ -47,7 +47,6 @@ noinst_HEADERS = \
vivi_code_comment.h \
vivi_code_constant.h \
vivi_code_continue.h \
- vivi_code_empty.h \
vivi_code_function.h \
vivi_code_function_call.h \
vivi_code_get.h \
@@ -67,6 +66,7 @@ noinst_HEADERS = \
vivi_code_value.h \
vivi_code_value_statement.h \
vivi_compiler.h \
+ vivi_compiler_empty_statement.h \
vivi_decompiler.h \
vivi_decompiler_block.h \
vivi_decompiler_duplicate.h \
diff --git a/vivified/code/vivi_code_empty.c b/vivified/code/vivi_code_empty.c
deleted file mode 100644
index cf56456..0000000
--- a/vivified/code/vivi_code_empty.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/* Vivified
- * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
- * 2008 Pekka Lampila <pekka.lampila at iki.fi>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "vivi_code_empty.h"
-#include "vivi_code_printer.h"
-
-G_DEFINE_TYPE (ViviCodeEmpty, vivi_code_empty, VIVI_TYPE_CODE_STATEMENT)
-
-static ViviCodeStatement *
-vivi_code_empty_optimize (ViviCodeStatement *statement)
-{
- // FIXME
- return statement;
-}
-
-static gboolean
-vivi_code_empty_needs_braces (ViviCodeStatement *stmt)
-{
- return FALSE;
-}
-
-static void
-vivi_code_empty_print (ViviCodeToken *token, ViviCodePrinter *printer)
-{
- vivi_code_printer_print (printer, ";");
- vivi_code_printer_new_line (printer, FALSE);
-}
-
-static void
-vivi_code_empty_class_init (ViviCodeEmptyClass *klass)
-{
- ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
- ViviCodeStatementClass *statement_class = VIVI_CODE_STATEMENT_CLASS (klass);
-
- token_class->print = vivi_code_empty_print;
-
- statement_class->optimize = vivi_code_empty_optimize;
- statement_class->needs_braces = vivi_code_empty_needs_braces;
-}
-
-static void
-vivi_code_empty_init (ViviCodeEmpty *token)
-{
-}
-
-ViviCodeStatement *
-vivi_code_empty_new (void)
-{
- ViviCodeEmpty *stmt;
-
- stmt = g_object_new (VIVI_TYPE_CODE_EMPTY, NULL);
-
- return VIVI_CODE_STATEMENT (stmt);
-}
diff --git a/vivified/code/vivi_code_empty.h b/vivified/code/vivi_code_empty.h
deleted file mode 100644
index 48dc126..0000000
--- a/vivified/code/vivi_code_empty.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* Vivified
- * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
- * 2008 Pekka Lampila <pekka.lampila at iki.fi>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301 USA
- */
-
-#ifndef _VIVI_CODE_EMPTY_H_
-#define _VIVI_CODE_EMPTY_H_
-
-#include <vivified/code/vivi_code_statement.h>
-#include <vivified/code/vivi_code_value.h>
-
-G_BEGIN_DECLS
-
-
-typedef struct _ViviCodeEmpty ViviCodeEmpty;
-typedef struct _ViviCodeEmptyClass ViviCodeEmptyClass;
-
-#define VIVI_TYPE_CODE_EMPTY (vivi_code_empty_get_type())
-#define VIVI_IS_CODE_EMPTY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_EMPTY))
-#define VIVI_IS_CODE_EMPTY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_EMPTY))
-#define VIVI_CODE_EMPTY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_EMPTY, ViviCodeEmpty))
-#define VIVI_CODE_EMPTY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_EMPTY, ViviCodeEmptyClass))
-#define VIVI_CODE_EMPTY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_EMPTY, ViviCodeEmptyClass))
-
-struct _ViviCodeEmpty
-{
- ViviCodeStatement statement;
-};
-
-struct _ViviCodeEmptyClass
-{
- ViviCodeStatementClass statement_class;
-};
-
-GType vivi_code_empty_get_type (void);
-
-ViviCodeStatement * vivi_code_empty_new (void);
-
-
-G_END_DECLS
-#endif
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index dae6046..e8ef2fa 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -31,7 +31,6 @@
#include "vivi_code_break.h"
#include "vivi_code_constant.h"
#include "vivi_code_continue.h"
-#include "vivi_code_empty.h"
#include "vivi_code_function.h"
#include "vivi_code_function_call.h"
#include "vivi_code_get.h"
@@ -44,6 +43,7 @@
#include "vivi_code_trace.h"
#include "vivi_code_unary.h"
#include "vivi_code_value_statement.h"
+#include "vivi_compiler_empty_statement.h"
#include "vivi_code_text_printer.h"
@@ -249,7 +249,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
/*function = vivi_code_function_new (arguments, body);
*statement = vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
VIVI_CODE_VALUE (function));*/
- *statement = vivi_code_empty_new ();
+ *statement = vivi_compiler_empty_statement_new ();
g_object_unref (identifier);
if (arguments != NULL)
@@ -343,7 +343,7 @@ parse_empty_statement (GScanner *scanner, ViviCodeStatement **statement)
if (!check_token (scanner, ';'))
return STATUS_CANCEL;
- *statement = vivi_code_empty_new ();
+ *statement = vivi_compiler_empty_statement_new ();
return STATUS_OK;
}
@@ -603,6 +603,7 @@ parse_member_expression (GScanner *scanner, ViviCodeValue **value)
static ParseStatus
parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
{
+ // TODO
return parse_value (scanner, SYMBOL_IDENTIFIER, value);
}
diff --git a/vivified/code/vivi_compiler_empty_statement.c b/vivified/code/vivi_compiler_empty_statement.c
new file mode 100644
index 0000000..1cabdfd
--- /dev/null
+++ b/vivified/code/vivi_compiler_empty_statement.c
@@ -0,0 +1,77 @@
+/* Vivified
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ * 2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "vivi_compiler_empty_statement.h"
+#include "vivi_code_printer.h"
+
+G_DEFINE_TYPE (ViviCompilerEmptyStatement, vivi_compiler_empty_statement, VIVI_TYPE_CODE_STATEMENT)
+
+static ViviCodeStatement *
+vivi_compiler_empty_statement_optimize (ViviCodeStatement *statement)
+{
+ // FIXME
+ return statement;
+}
+
+static gboolean
+vivi_compiler_empty_statement_needs_braces (ViviCodeStatement *stmt)
+{
+ return FALSE;
+}
+
+static void
+vivi_compiler_empty_statement_print (ViviCodeToken *token,
+ ViviCodePrinter *printer)
+{
+ vivi_code_printer_print (printer, ";");
+ vivi_code_printer_new_line (printer, FALSE);
+}
+
+static void
+vivi_compiler_empty_statement_class_init (
+ ViviCompilerEmptyStatementClass *klass)
+{
+ ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+ ViviCodeStatementClass *statement_class = VIVI_CODE_STATEMENT_CLASS (klass);
+
+ token_class->print = vivi_compiler_empty_statement_print;
+
+ statement_class->optimize = vivi_compiler_empty_statement_optimize;
+ statement_class->needs_braces = vivi_compiler_empty_statement_needs_braces;
+}
+
+static void
+vivi_compiler_empty_statement_init (ViviCompilerEmptyStatement *token)
+{
+}
+
+ViviCodeStatement *
+vivi_compiler_empty_statement_new (void)
+{
+ ViviCompilerEmptyStatement *stmt;
+
+ stmt = g_object_new (VIVI_TYPE_COMPILER_EMPTY, NULL);
+
+ return VIVI_CODE_STATEMENT (stmt);
+}
diff --git a/vivified/code/vivi_compiler_empty_statement.h b/vivified/code/vivi_compiler_empty_statement.h
new file mode 100644
index 0000000..ede1fa5
--- /dev/null
+++ b/vivified/code/vivi_compiler_empty_statement.h
@@ -0,0 +1,56 @@
+/* Vivified
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ * 2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef _VIVI_COMPILER_EMPTY_H_
+#define _VIVI_COMPILER_EMPTY_H_
+
+#include <vivified/code/vivi_code_statement.h>
+#include <vivified/code/vivi_code_value.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCompilerEmptyStatement ViviCompilerEmptyStatement;
+typedef struct _ViviCompilerEmptyStatementClass ViviCompilerEmptyStatementClass;
+
+#define VIVI_TYPE_COMPILER_EMPTY (vivi_compiler_empty_statement_get_type())
+#define VIVI_IS_COMPILER_EMPTY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_COMPILER_EMPTY))
+#define VIVI_IS_COMPILER_EMPTY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_COMPILER_EMPTY))
+#define VIVI_COMPILER_EMPTY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_COMPILER_EMPTY, ViviCompilerEmptyStatement))
+#define VIVI_COMPILER_EMPTY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_COMPILER_EMPTY, ViviCompilerEmptyStatementClass))
+#define VIVI_COMPILER_EMPTY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_COMPILER_EMPTY, ViviCompilerEmptyStatementClass))
+
+struct _ViviCompilerEmptyStatement
+{
+ ViviCodeStatement statement;
+};
+
+struct _ViviCompilerEmptyStatementClass
+{
+ ViviCodeStatementClass statement_class;
+};
+
+GType vivi_compiler_empty_statement_get_type (void);
+
+ViviCodeStatement * vivi_compiler_empty_statement_new (void);
+
+
+G_END_DECLS
+#endif
commit f183b6a6523b0102671ae057d3ab7e51a5bb694a
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Fri Mar 28 18:56:01 2008 +0200
Few cleanups to the compiler code
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 17fcd2b..dae6046 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -179,7 +179,8 @@ parse_program (GScanner *scanner, ViviCodeStatement **statement)
*statement = NULL;
- status = parse_statement_list (scanner, SYMBOL_SOURCE_ELEMENT, &list, G_TOKEN_NONE);
+ status = parse_statement_list (scanner, SYMBOL_SOURCE_ELEMENT, &list,
+ G_TOKEN_NONE);
if (status != STATUS_OK)
return status;
@@ -228,7 +229,8 @@ parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
if (!check_token (scanner, '('))
goto fail;
- if (parse_value_list (scanner, SYMBOL_IDENTIFIER, &arguments, ',') == STATUS_FAIL)
+ if (parse_value_list (scanner, SYMBOL_IDENTIFIER, &arguments, ',') ==
+ STATUS_FAIL)
goto fail;
if (!check_token (scanner, ')'))
@@ -313,18 +315,17 @@ parse_block (GScanner *scanner, ViviCodeStatement **statement)
if (!check_token (scanner, '{'))
return STATUS_CANCEL;
- list = NULL;
-
g_scanner_peek_next_token (scanner);
if (scanner->next_token != '}') {
if (parse_statement_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
!= STATUS_OK)
return STATUS_FAIL;
+ } else {
+ list = g_new0 (ViviCodeStatement *, 1);
}
if (!check_token (scanner, '}')) {
- if (list != NULL)
- free_statement_list (list);
+ free_statement_list (list);
return STATUS_FAIL;
}
@@ -386,12 +387,7 @@ parse_expression (GScanner *scanner, ViviCodeStatement **statement)
if (status != STATUS_OK)
return status;
- if (list[1] == NULL) {
- *statement = g_object_ref (list[0]);
- } else {
- *statement = create_block (list);
- }
-
+ *statement = create_block (list);
free_statement_list (list);
return STATUS_OK;
commit 59cd72f052fa595bd816907c5fa8953a589278b8
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Fri Mar 28 18:43:28 2008 +0200
Split compiler's parsing functions to Statement and Value categories
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
index 53d873c..17fcd2b 100644
--- a/vivified/code/vivi_compiler.c
+++ b/vivified/code/vivi_compiler.c
@@ -102,14 +102,23 @@ typedef enum {
SYMBOL_ARGUMENTS,
} ParseSymbol;
-typedef ParseStatus (*ParseFunction) (GScanner *scanner, ViviCodeToken **token);
+typedef ParseStatus (*ParseStatementFunction) (GScanner *scanner, ViviCodeStatement **statement);
+typedef ParseStatus (*ParseValueFunction) (GScanner *scanner, ViviCodeValue **value);
static ParseStatus
-parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token);
+parse_statement (GScanner *scanner, ParseSymbol symbol,
+ ViviCodeStatement **statement);
static ParseStatus
-parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
- guint separator);
+parse_value (GScanner *scanner, ParseSymbol symbol, ViviCodeValue **value);
+
+static ParseStatus
+parse_statement_list (GScanner *scanner, ParseSymbol symbol,
+ ViviCodeStatement ***list, guint separator);
+
+static ParseStatus
+parse_value_list (GScanner *scanner, ParseSymbol symbol,
+ ViviCodeValue ***list, guint separator);
// helpers
@@ -124,7 +133,7 @@ check_token (GScanner *scanner, guint token)
}
static void
-free_list (ViviCodeToken **list)
+free_statement_list (ViviCodeStatement **list)
{
int i;
@@ -134,8 +143,19 @@ free_list (ViviCodeToken **list)
g_free (list);
}
-static ViviCodeBlock *
-create_block (ViviCodeToken **list)
+static void
+free_value_list (ViviCodeValue **list)
+{
+ int i;
+
+ for (i = 0; list[i] != NULL; i++) {
+ g_object_unref (list[i]);
+ }
+ g_free (list);
+}
+
+static ViviCodeStatement *
+create_block (ViviCodeStatement **list)
{
ViviCodeBlock *block;
int i;
@@ -143,42 +163,42 @@ create_block (ViviCodeToken **list)
block = VIVI_CODE_BLOCK (vivi_code_block_new ());
for (i = 0; list[i] != NULL; i++) {
- vivi_code_block_add_statement (block, VIVI_CODE_STATEMENT (list[i]));
+ vivi_code_block_add_statement (block, list[i]);
}
- return block;
+ return VIVI_CODE_STATEMENT (block);
}
// top
static ParseStatus
-parse_program (GScanner *scanner, ViviCodeToken **token)
+parse_program (GScanner *scanner, ViviCodeStatement **statement)
{
ParseStatus status;
- ViviCodeToken **list;
+ ViviCodeStatement **list;
- *token = NULL;
+ *statement = NULL;
- status = parse_list (scanner, SYMBOL_SOURCE_ELEMENT, &list, G_TOKEN_NONE);
+ status = parse_statement_list (scanner, SYMBOL_SOURCE_ELEMENT, &list, G_TOKEN_NONE);
if (status != STATUS_OK)
return status;
- *token = VIVI_CODE_TOKEN (create_block (list));
+ *statement = create_block (list);
return STATUS_OK;
}
static ParseStatus
-parse_source_element (GScanner *scanner, ViviCodeToken **token)
+parse_source_element (GScanner *scanner, ViviCodeStatement **statement)
{
ParseStatus status;
- *token = NULL;
+ *statement = NULL;
- status = parse (scanner, SYMBOL_FUNCTION_DECLARATION, token);
+ status = parse_statement (scanner, SYMBOL_FUNCTION_DECLARATION, statement);
if (status == STATUS_CANCEL)
- status = parse (scanner, SYMBOL_STATEMENT, token);
+ status = parse_statement (scanner, SYMBOL_STATEMENT, statement);
return status;
}
@@ -186,13 +206,14 @@ parse_source_element (GScanner *scanner, ViviCodeToken **token)
// function
static ParseStatus
-parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
+parse_function_declaration (GScanner *scanner, ViviCodeStatement **statement)
{
- //ViviCodeToken *function;
- ViviCodeToken *identifier;
- ViviCodeToken **arguments, **body;
+ //ViviCodeStatement *function;
+ ViviCodeValue *identifier;
+ ViviCodeValue **arguments;
+ ViviCodeStatement **body;
- *token = NULL;
+ *statement = NULL;
identifier = NULL;
arguments = NULL;
@@ -201,13 +222,13 @@ parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
if (!check_token (scanner, TOKEN_FUNCTION))
return STATUS_CANCEL;
- if (parse (scanner, SYMBOL_IDENTIFIER, &identifier) != STATUS_OK)
+ if (parse_value (scanner, SYMBOL_IDENTIFIER, &identifier) != STATUS_OK)
return STATUS_FAIL;
if (!check_token (scanner, '('))
goto fail;
- if (parse_list (scanner, SYMBOL_IDENTIFIER, &arguments, ',') == STATUS_FAIL)
+ if (parse_value_list (scanner, SYMBOL_IDENTIFIER, &arguments, ',') == STATUS_FAIL)
goto fail;
if (!check_token (scanner, ')'))
@@ -216,7 +237,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
if (!check_token (scanner, '{'))
goto fail;
- if (parse_list (scanner, SYMBOL_SOURCE_ELEMENT, &body, G_TOKEN_NONE)
+ if (parse_statement_list (scanner, SYMBOL_SOURCE_ELEMENT, &body, G_TOKEN_NONE)
== STATUS_FAIL)
goto fail;
@@ -224,16 +245,15 @@ parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
goto fail;
/*function = vivi_code_function_new (arguments, body);
- *token = VIVI_CODE_TOKEN (
- vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
- VIVI_CODE_VALUE (function)));*/
- *token = VIVI_CODE_TOKEN (vivi_code_empty_new ());
+ *statement = vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
+ VIVI_CODE_VALUE (function));*/
+ *statement = vivi_code_empty_new ();
g_object_unref (identifier);
if (arguments != NULL)
- free_list (arguments);
+ free_value_list (arguments);
if (body != NULL)
- free_list (body);
+ free_statement_list (body);
return STATUS_OK;
@@ -241,9 +261,9 @@ fail:
if (identifier != NULL)
g_object_unref (identifier);
if (arguments != NULL)
- free_list (arguments);
+ free_value_list (arguments);
if (body != NULL)
- free_list (body);
+ free_statement_list (body);
return STATUS_FAIL;
}
@@ -251,7 +271,7 @@ fail:
// statement
static ParseStatus
-parse_statement (GScanner *scanner, ViviCodeToken **token)
+parse_statement_symbol (GScanner *scanner, ViviCodeStatement **statement)
{
int i, status;
ParseSymbol options[] = {
@@ -272,10 +292,10 @@ parse_statement (GScanner *scanner, ViviCodeToken **token)
SYMBOL_NONE
};
- *token = NULL;
+ *statement = NULL;
for (i = 0; options[i] != SYMBOL_NONE; i++) {
- status = parse (scanner, options[i], token);
+ status = parse_statement (scanner, options[i], statement);
if (status != STATUS_CANCEL)
return status;
}
@@ -284,11 +304,11 @@ parse_statement (GScanner *scanner, ViviCodeToken **token)
}
static ParseStatus
-parse_block (GScanner *scanner, ViviCodeToken **token)
+parse_block (GScanner *scanner, ViviCodeStatement **statement)
{
- ViviCodeToken **list;
+ ViviCodeStatement **list;
- *token = NULL;
+ *statement = NULL;
if (!check_token (scanner, '{'))
return STATUS_CANCEL;
@@ -297,54 +317,54 @@ parse_block (GScanner *scanner, ViviCodeToken **token)
g_scanner_peek_next_token (scanner);
if (scanner->next_token != '}') {
- if (parse_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
+ if (parse_statement_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
!= STATUS_OK)
return STATUS_FAIL;
}
if (!check_token (scanner, '}')) {
if (list != NULL)
- free_list (list);
+ free_statement_list (list);
return STATUS_FAIL;
}
- *token = VIVI_CODE_TOKEN (create_block (list));
- free_list (list);
+ *statement = create_block (list);
+ free_statement_list (list);
return STATUS_OK;
}
static ParseStatus
-parse_empty_statement (GScanner *scanner, ViviCodeToken **token)
+parse_empty_statement (GScanner *scanner, ViviCodeStatement **statement)
{
- *token = NULL;
+ *statement = NULL;
if (!check_token (scanner, ';'))
return STATUS_CANCEL;
- *token = VIVI_CODE_TOKEN (vivi_code_empty_new ());
+ *statement = vivi_code_empty_new ();
return STATUS_OK;
}
static ParseStatus
-parse_expression_statement (GScanner *scanner, ViviCodeToken **token)
+parse_expression_statement (GScanner *scanner, ViviCodeStatement **statement)
{
ParseStatus status;
- *token = NULL;
+ *statement = NULL;
g_scanner_peek_next_token (scanner);
if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
return STATUS_CANCEL;
- status = parse (scanner, SYMBOL_EXPRESSION, token);
+ status = parse_statement (scanner, SYMBOL_EXPRESSION, statement);
if (status != STATUS_OK)
return status;
if (!check_token (scanner, ';')) {
- g_object_unref (*token);
- *token = NULL;
+ g_object_unref (*statement);
+ *statement = NULL;
return STATUS_FAIL;
}
@@ -354,69 +374,71 @@ parse_expression_statement (GScanner *scanner, ViviCodeToken **token)
// expression
static ParseStatus
-parse_expression (GScanner *scanner, ViviCodeToken **token)
+parse_expression (GScanner *scanner, ViviCodeStatement **statement)
{
- ViviCodeToken **list;
+ ViviCodeStatement **list;
ParseStatus status;
- *token = NULL;
+ *statement = NULL;
- status = parse_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
+ status =
+ parse_statement_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
if (status != STATUS_OK)
return status;
if (list[1] == NULL) {
- *token = g_object_ref (list[0]);
+ *statement = g_object_ref (list[0]);
} else {
- *token = VIVI_CODE_TOKEN (create_block (list));
+ *statement = create_block (list);
}
- free_list (list);
+ free_statement_list (list);
return STATUS_OK;
}
static ParseStatus
-parse_assignment_expression (GScanner *scanner, ViviCodeToken **token)
+parse_assignment_expression (GScanner *scanner, ViviCodeStatement **statement)
{
- *token = NULL;
+ *statement = NULL;
// TODO
- return parse (scanner, SYMBOL_CONDITIONAL_EXPRESSION, token);
+ return parse_statement (scanner, SYMBOL_CONDITIONAL_EXPRESSION, statement);
}
static ParseStatus
-parse_conditional_expression (GScanner *scanner, ViviCodeToken **token)
+parse_conditional_expression (GScanner *scanner, ViviCodeStatement **statement)
{
ParseStatus status;
- ViviCodeToken *value;
- ViviCodeToken *first, *second;
+ ViviCodeValue *value;
+ ViviCodeStatement *first, *second;
- *token = NULL;
+ *statement = NULL;
first = NULL;
- status = parse (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
+ status = parse_value (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
if (status != STATUS_OK)
return status;
if (!check_token (scanner, '?')) {
- *token = VIVI_CODE_TOKEN (
- vivi_code_value_statement_new (VIVI_CODE_VALUE (value)));
+ *statement = vivi_code_value_statement_new (VIVI_CODE_VALUE (value));
g_object_unref (value);
return STATUS_OK;
}
- if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &first) != STATUS_OK)
+ if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &first) !=
+ STATUS_OK)
goto fail;
if (!check_token (scanner, ':'))
goto fail;
- if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &second) != STATUS_OK)
+ if (parse_statement (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &second) !=
+ STATUS_OK)
goto fail;
- //*token = vivi_code_condional_new (VIVI_CODE_VALUE (value),
+ //*statement = vivi_code_condional_new (VIVI_CODE_VALUE (value),
// VIVI_CODE_STATEMENT (first), VIVI_CODE_STATEMENT (second));
g_object_unref (value);
@@ -435,15 +457,15 @@ fail:
}
static ParseStatus
-parse_operator_expression (GScanner *scanner, ViviCodeToken **token)
+parse_operator_expression (GScanner *scanner, ViviCodeValue **value)
{
ParseStatus status;
ViviCodeValue *left;
- ViviCodeToken *right;
+ ViviCodeValue *right;
- *token = NULL;
+ *value = NULL;
- status = parse (scanner, SYMBOL_UNARY_EXPRESSION, token);
+ status = parse_value (scanner, SYMBOL_UNARY_EXPRESSION, value);
if (status != STATUS_OK)
return status;
@@ -451,132 +473,130 @@ parse_operator_expression (GScanner *scanner, ViviCodeToken **token)
if (!check_token (scanner, '+'))
return STATUS_OK;
- if (parse (scanner, SYMBOL_UNARY_EXPRESSION, &right) != STATUS_OK) {
- g_object_unref (*token);
- *token = NULL;
+ if (parse_value (scanner, SYMBOL_UNARY_EXPRESSION, &right) != STATUS_OK) {
+ g_object_unref (*value);
+ *value = NULL;
return STATUS_FAIL;
}
- left = VIVI_CODE_VALUE (*token);
- *token = VIVI_CODE_TOKEN (vivi_code_binary_new_name (left,
- VIVI_CODE_VALUE (right), "+"));
+ left = VIVI_CODE_VALUE (*value);
+ *value = vivi_code_binary_new_name (left, VIVI_CODE_VALUE (right), "+");
g_object_unref (left);
g_object_unref (right);
} while (TRUE);
- g_object_unref (*token);
- *token = NULL;
+ g_object_unref (*value);
+ *value = NULL;
return STATUS_FAIL;
}
static ParseStatus
-parse_unary_expression (GScanner *scanner, ViviCodeToken **token)
+parse_unary_expression (GScanner *scanner, ViviCodeValue **value)
{
- ViviCodeValue *value;
+ ViviCodeValue *tmp;
- *token = NULL;
+ *value = NULL;
if (check_token (scanner, '!')) {
- parse (scanner, SYMBOL_UNARY_EXPRESSION, token);
- value = VIVI_CODE_VALUE (*token);
- *token = VIVI_CODE_TOKEN (vivi_code_unary_new (value, '!'));
- g_object_unref (value);
+ parse_value (scanner, SYMBOL_UNARY_EXPRESSION, value);
+ tmp = VIVI_CODE_VALUE (*value);
+ *value = vivi_code_unary_new (tmp, '!');
+ g_object_unref (tmp);
return STATUS_OK;
} else {
- return parse (scanner, SYMBOL_POSTFIX_EXPRESSION, token);
+ return parse_value (scanner, SYMBOL_POSTFIX_EXPRESSION, value);
}
}
static ParseStatus
-parse_postfix_expression (GScanner *scanner, ViviCodeToken **token)
+parse_postfix_expression (GScanner *scanner, ViviCodeValue **value)
{
- //ViviCodeValue *value;
ParseStatus status;
- status = parse (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION, token);
+ status = parse_value (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION, value);
if (status != STATUS_OK)
return status;
// FIXME: Don't allow new line here
/*if (check_token (scanner, TOKEN_PLUSPLUS)) {
- value = VIVI_CODE_VALUE (*token);
- *token = VIVI_CODE_TOKEN (vivi_code_postfix_new (value, "++"));
- g_object_unref (value);
+ ViviCodeValue *tmp = *value;
+ *value = vivi_code_postfix_new (tmp, "++");
+ g_object_unref (tmp);
} else {*/
return STATUS_OK;
//}
}
static ParseStatus
-parse_left_hand_side_expression (GScanner *scanner, ViviCodeToken **token)
+parse_left_hand_side_expression (GScanner *scanner, ViviCodeValue **value)
{
ParseStatus status;
- *token = NULL;
+ *value = NULL;
- status = parse (scanner, SYMBOL_NEW_EXPRESSION, token);
+ status = parse_value (scanner, SYMBOL_NEW_EXPRESSION, value);
if (status == STATUS_CANCEL)
- status = parse (scanner, SYMBOL_CALL_EXPRESSION, token);
+ status = parse_value (scanner, SYMBOL_CALL_EXPRESSION, value);
return status;
}
static ParseStatus
-parse_new_expression (GScanner *scanner, ViviCodeToken **token)
+parse_new_expression (GScanner *scanner, ViviCodeValue **value)
{
- *token = NULL;
+ *value = NULL;
if (check_token (scanner, TOKEN_NEW)) {
- if (parse (scanner, SYMBOL_NEW_EXPRESSION, token) != STATUS_OK)
+ if (parse_value (scanner, SYMBOL_NEW_EXPRESSION, value) != STATUS_OK)
return STATUS_FAIL;
- if (!VIVI_IS_CODE_FUNCTION_CALL (*token)) {
- ViviCodeValue *value = VIVI_CODE_VALUE (*token);
- *token = VIVI_CODE_TOKEN (vivi_code_function_call_new (NULL, value));
- g_object_unref (value);
+ if (!VIVI_IS_CODE_FUNCTION_CALL (*value)) {
+ ViviCodeValue *tmp = VIVI_CODE_VALUE (*value);
+ *value = vivi_code_function_call_new (NULL, tmp);
+ g_object_unref (tmp);
}
- vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*token),
+ vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*value),
TRUE);
return STATUS_OK;
} else {
- return parse (scanner, SYMBOL_MEMBER_EXPRESSION, token);
+ return parse_value (scanner, SYMBOL_MEMBER_EXPRESSION, value);
}
}
static ParseStatus
-parse_member_expression (GScanner *scanner, ViviCodeToken **token)
+parse_member_expression (GScanner *scanner, ViviCodeValue **value)
{
ParseStatus status;
- ViviCodeValue *value;
- ViviCodeToken *member;
+ ViviCodeValue *member;
// TODO: new MemberExpression Arguments
- status = parse (scanner, SYMBOL_PRIMARY_EXPRESSION, token);
+ status = parse_value (scanner, SYMBOL_PRIMARY_EXPRESSION, value);
if (status == STATUS_CANCEL)
- status = parse (scanner, SYMBOL_FUNCTION_EXPRESSION, token);
+ status = parse_value (scanner, SYMBOL_FUNCTION_EXPRESSION, value);
if (status != 0)
return status;
do {
+ ViviCodeValue *tmp;
+
if (check_token (scanner, '[')) {
- if (parse (scanner, SYMBOL_EXPRESSION, &member) != STATUS_OK)
+ if (parse_value (scanner, SYMBOL_EXPRESSION, &member) != STATUS_OK)
return STATUS_FAIL;
if (!check_token (scanner, ']'))
return STATUS_FAIL;
} else if (check_token (scanner, '.')) {
- if (parse (scanner, SYMBOL_IDENTIFIER, &member) != STATUS_OK)
+ if (parse_value (scanner, SYMBOL_IDENTIFIER, &member) != STATUS_OK)
return STATUS_FAIL;
} else {
return STATUS_OK;
}
- value = VIVI_CODE_VALUE (token);
- *token = VIVI_CODE_TOKEN (
- vivi_code_get_new (value, VIVI_CODE_VALUE (member)));
- g_object_unref (value);
+ tmp = *value;
+ *value = vivi_code_get_new (tmp, VIVI_CODE_VALUE (member));
+ g_object_unref (tmp);
g_object_unref (member);
} while (TRUE);
@@ -585,34 +605,35 @@ parse_member_expression (GScanner *scanner, ViviCodeToken **token)
}
static ParseStatus
-parse_primary_expression (GScanner *scanner, ViviCodeToken **token)
+parse_primary_expression (GScanner *scanner, ViviCodeValue **value)
{
- return parse (scanner, SYMBOL_IDENTIFIER, token);
+ return parse_value (scanner, SYMBOL_IDENTIFIER, value);
}
// misc.
static ParseStatus
-parse_identifier (GScanner *scanner, ViviCodeToken **token)
+parse_identifier (GScanner *scanner, ViviCodeValue **value)
{
- *token = NULL;
+ *value = NULL;
if (!check_token (scanner, G_TOKEN_IDENTIFIER))
return STATUS_CANCEL;
- *token =
- VIVI_CODE_TOKEN (vivi_code_get_new_name (scanner->value.v_identifier));
+ *value = vivi_code_get_new_name (scanner->value.v_identifier);
return STATUS_OK;
}
// parsing
-static const struct {
- ParseSymbol id;
- const char * name;
- ParseFunction parse;
-} symbols[] = {
+typedef struct {
+ ParseSymbol id;
+ const char * name;
+ ParseStatementFunction parse;
+} SymbolStatementFunctionList;
+
+static const SymbolStatementFunctionList statement_symbols[] = {
// top
{ SYMBOL_PROGRAM, "Program", parse_program },
{ SYMBOL_SOURCE_ELEMENT, "SourceElement", parse_source_element },
@@ -620,7 +641,7 @@ static const struct {
{ SYMBOL_FUNCTION_DECLARATION, "FunctionDeclaration",
parse_function_declaration },
// statement
- { SYMBOL_STATEMENT, "Statement", parse_statement },
+ { SYMBOL_STATEMENT, "Statement", parse_statement_symbol },
{ SYMBOL_BLOCK, "Block", parse_block },
{ SYMBOL_EMPTY_STATEMENT, "EmptyStatement", parse_empty_statement },
{ SYMBOL_EXPRESSION_STATEMENT, "ExpressionStatement",
@@ -631,6 +652,17 @@ static const struct {
parse_assignment_expression },
{ SYMBOL_CONDITIONAL_EXPRESSION, "ConditionalExpression",
parse_conditional_expression },
+ { SYMBOL_NONE, NULL, NULL }
+};
+
+typedef struct {
+ ParseSymbol id;
+ const char * name;
+ ParseValueFunction parse;
+} SymbolValueFunctionList;
+
+static const SymbolValueFunctionList value_symbols[] = {
+ // expression
{ SYMBOL_OPERATOR_EXPRESSION, "OperatorExpression",
parse_operator_expression },
{ SYMBOL_UNARY_EXPRESSION, "UnaryExpression", parse_unary_expression },
@@ -646,19 +678,42 @@ static const struct {
};
static ParseStatus
-parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token)
+parse_statement (GScanner *scanner, ParseSymbol symbol,
+ ViviCodeStatement **statement)
+{
+ int i;
+
+ g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
+ g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
+ g_return_val_if_fail (statement != NULL, STATUS_FAIL);
+
+ for (i = 0; statement_symbols[i].id != SYMBOL_NONE; i++) {
+ if (statement_symbols[i].id == symbol) {
+ ParseStatus status = statement_symbols[i].parse (scanner, statement);
+ g_assert ((status == STATUS_OK && VIVI_IS_CODE_TOKEN (*statement)) ||
+ (status != STATUS_OK && *statement == NULL));
+ return status;
+ }
+ }
+
+ //g_assert_not_reached ();
+ return STATUS_CANCEL;
+}
+
+static ParseStatus
+parse_value (GScanner *scanner, ParseSymbol symbol, ViviCodeValue **value)
{
int i;
g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
- g_return_val_if_fail (token != NULL, STATUS_FAIL);
+ g_return_val_if_fail (value != NULL, STATUS_FAIL);
- for (i = 0; symbols[i].id != SYMBOL_NONE; i++) {
- if (symbols[i].id == symbol) {
- ParseStatus status = symbols[i].parse (scanner, token);
- g_assert ((status == STATUS_OK && VIVI_IS_CODE_TOKEN (*token)) ||
- (status != STATUS_OK && *token == NULL));
+ for (i = 0; value_symbols[i].id != SYMBOL_NONE; i++) {
+ if (value_symbols[i].id == symbol) {
+ ParseStatus status = value_symbols[i].parse (scanner, value);
+ g_assert ((status == STATUS_OK && VIVI_IS_CODE_TOKEN (*value)) ||
+ (status != STATUS_OK && *value == NULL));
return status;
}
}
@@ -668,36 +723,71 @@ parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token)
}
static ParseStatus
-parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
+parse_statement_list (GScanner *scanner, ParseSymbol symbol,
+ ViviCodeStatement ***list, guint separator)
+{
+ GPtrArray *array;
+ ViviCodeStatement *statement;
+ ParseStatus status;
+
+ g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
+ g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
+ g_return_val_if_fail (list != NULL, STATUS_FAIL);
+
+ status = parse_statement (scanner, symbol, &statement);
+ if (status != STATUS_OK)
+ return status;
+
+ array = g_ptr_array_new ();
+
+ do {
+ g_ptr_array_add (array, statement);
+
+ if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
+ break;
+
+ status = parse_statement (scanner, symbol, &statement);
+ if (status == STATUS_FAIL)
+ return STATUS_FAIL;
+ } while (status == STATUS_OK);
+ g_ptr_array_add (array, NULL);
+
+ *list = (ViviCodeStatement **)g_ptr_array_free (array, FALSE);
+
+ return STATUS_OK;
+}
+
+static ParseStatus
+parse_value_list (GScanner *scanner, ParseSymbol symbol, ViviCodeValue ***list,
guint separator)
{
GPtrArray *array;
- ViviCodeToken *token;
- ParseStatus ret;
+ ViviCodeValue *value;
+ ParseStatus status;
g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
g_return_val_if_fail (list != NULL, STATUS_FAIL);
- ret = parse (scanner, symbol, &token);
- if (ret != STATUS_OK)
- return ret;
+ status = parse_value (scanner, symbol, &value);
+ if (status != STATUS_OK)
+ return status;
array = g_ptr_array_new ();
do {
- g_ptr_array_add (array, token);
+ g_ptr_array_add (array, value);
if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
break;
- ret = parse (scanner, symbol, &token);
- if (ret == STATUS_FAIL)
+ status = parse_value (scanner, symbol, &value);
+ if (status == STATUS_FAIL)
return STATUS_FAIL;
- } while (ret == STATUS_OK);
+ } while (status == STATUS_OK);
g_ptr_array_add (array, NULL);
- *list = (ViviCodeToken **)g_ptr_array_free (array, FALSE);
+ *list = (ViviCodeValue **)g_ptr_array_free (array, FALSE);
return STATUS_OK;
}
@@ -708,7 +798,7 @@ ViviCodeStatement *
vivi_compile_text (const char *text, gsize len, const char *input_name)
{
GScanner *scanner;
- ViviCodeToken *token;
+ ViviCodeStatement *statement;
ParseStatus status;
g_return_val_if_fail (text != NULL, NULL);
@@ -721,23 +811,21 @@ vivi_compile_text (const char *text, gsize len, const char *input_name)
g_scanner_set_scope (scanner, 0);
g_scanner_scope_add_symbol (scanner, 0, "function",
- GINT_TO_POINTER(TOKEN_FUNCTION));
+ GINT_TO_POINTER (TOKEN_FUNCTION));
g_scanner_scope_add_symbol (scanner, 0, "++",
- GINT_TO_POINTER(TOKEN_PLUSPLUS));
+ GINT_TO_POINTER (TOKEN_PLUSPLUS));
g_scanner_scope_add_symbol (scanner, 0, "--",
- GINT_TO_POINTER(TOKEN_MINUSMINUS));
- g_scanner_scope_add_symbol (scanner, 0, "new", GINT_TO_POINTER(TOKEN_NEW));
+ GINT_TO_POINTER (TOKEN_MINUSMINUS));
+ g_scanner_scope_add_symbol (scanner, 0, "new", GINT_TO_POINTER (TOKEN_NEW));
scanner->input_name = input_name;
g_scanner_input_text (scanner, text, len);
- status = parse (scanner, SYMBOL_PROGRAM, &token);
+ status = parse_statement (scanner, SYMBOL_PROGRAM, &statement);
+ g_assert ((status == STATUS_OK && VIVI_IS_CODE_STATEMENT (statement)) ||
+ (status != STATUS_OK && statement == NULL));
g_scanner_destroy (scanner);
- if (status == STATUS_OK) {
- return VIVI_CODE_STATEMENT (token);
- } else {
- return NULL;
- }
+ return statement;
}
commit 2eb1fb3580b4abd7c80b64d62c51aed4d31268fb
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Fri Mar 28 18:10:06 2008 +0200
Add vivi-compiler to .gitignore
diff --git a/vivified/code/.gitignore b/vivified/code/.gitignore
index 8761c5f..b85daef 100644
--- a/vivified/code/.gitignore
+++ b/vivified/code/.gitignore
@@ -12,3 +12,4 @@ Makefile.in
*.loT
vivi-decompile
+vivi-compile
commit ce82ff6d58d7d8afd7b8bbc9057b1745a1f26c9c
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Fri Mar 28 18:09:42 2008 +0200
Re-organize and clean up the compiler code
diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index a731138..fc3cfd7 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -32,6 +32,7 @@ libvivified_compiler_la_SOURCES = \
vivi_code_unary.c \
vivi_code_value.c \
vivi_code_value_statement.c \
+ vivi_compiler.c \
vivi_decompiler_block.c \
vivi_decompiler_duplicate.c \
vivi_decompiler_state.c \
@@ -65,6 +66,7 @@ noinst_HEADERS = \
vivi_code_unary.h \
vivi_code_value.h \
vivi_code_value_statement.h \
+ vivi_compiler.h \
vivi_decompiler.h \
vivi_decompiler_block.h \
vivi_decompiler_duplicate.h \
diff --git a/vivified/code/compiler.c b/vivified/code/compiler.c
index f550b1e..1e5cd3a 100644
--- a/vivified/code/compiler.c
+++ b/vivified/code/compiler.c
@@ -21,749 +21,39 @@
#include "config.h"
#endif
-#include <string.h>
#include <swfdec/swfdec.h>
-#include "vivi_code_assignment.h"
-#include "vivi_code_binary.h"
-#include "vivi_code_block.h"
-#include "vivi_code_break.h"
-#include "vivi_code_constant.h"
-#include "vivi_code_continue.h"
-#include "vivi_code_empty.h"
-#include "vivi_code_function.h"
-#include "vivi_code_function_call.h"
-#include "vivi_code_get.h"
-#include "vivi_code_get_url.h"
-#include "vivi_code_goto.h"
-#include "vivi_code_if.h"
-#include "vivi_code_init_object.h"
-#include "vivi_code_loop.h"
-#include "vivi_code_return.h"
-#include "vivi_code_trace.h"
-#include "vivi_code_unary.h"
-#include "vivi_code_value_statement.h"
-
-typedef enum {
- STATUS_FAIL = -1,
- STATUS_OK = 0,
- STATUS_CANCEL = 1
-} ParseStatus;
-
-enum {
- TOKEN_FUNCTION = G_TOKEN_LAST + 1,
- TOKEN_PLUSPLUS = G_TOKEN_LAST + 2,
- TOKEN_MINUSMINUS = G_TOKEN_LAST + 3,
- TOKEN_NEW = G_TOKEN_LAST + 4
-};
-
-typedef enum {
- SYMBOL_NONE,
- // top
- SYMBOL_SOURCE_ELEMENT,
- // function
- SYMBOL_FUNCTION_DECLARATION,
- // statement
- SYMBOL_STATEMENT,
- SYMBOL_BLOCK,
- SYMBOL_VARIABLE_STATEMENT,
- SYMBOL_EMPTY_STATEMENT,
- SYMBOL_EXPRESSION_STATEMENT,
- SYMBOL_IF_STATEMENT,
- SYMBOL_ITERATION_STATEMENT,
- SYMBOL_CONTINUE_STATEMENT,
- SYMBOL_BREAK_STATEMENT,
- SYMBOL_RETURN_STATEMENT,
- SYMBOL_WITH_STATEMENT,
- SYMBOL_LABELLED_STATEMENT,
- SYMBOL_SWITCH_STATEMENT,
- SYMBOL_THROW_STATEMENT,
- SYMBOL_TRY_STATEMENT,
- // expression
- SYMBOL_EXPRESSION,
- SYMBOL_ASSIGNMENT_EXPRESSION,
- SYMBOL_CONDITIONAL_EXPRESSION,
- SYMBOL_LEFT_HAND_SIDE_EXPRESSION,
- SYMBOL_OPERATOR_EXPRESSION,
- SYMBOL_UNARY_EXPRESSION,
- SYMBOL_POSTFIX_EXPRESSION,
- SYMBOL_NEW_EXPRESSION,
- SYMBOL_CALL_EXPRESSION,
- SYMBOL_MEMBER_EXPRESSION,
- SYMBOL_FUNCTION_EXPRESSION,
- SYMBOL_PRIMARY_EXPRESSION,
- // misc
- SYMBOL_IDENTIFIER,
- SYMBOL_ASSIGNMENT_OPERATOR,
- SYMBOL_ARGUMENTS,
-} ParseSymbol;
-
-typedef ParseStatus (*ParseFunction) (GScanner *scanner, ViviCodeToken **token);
-
-static ParseStatus
-parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token);
-
-static ParseStatus
-parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
- guint separator);
-
-// helpers
-
-static gboolean
-check_token (GScanner *scanner, guint token)
-{
- g_scanner_peek_next_token (scanner);
- if (scanner->next_token != token)
- return FALSE;
- g_scanner_get_next_token (scanner);
- return TRUE;
-}
-
-static void
-free_list (ViviCodeToken **list)
-{
- int i;
-
- for (i = 0; list[i] != NULL; i++) {
- g_object_unref (list[i]);
- }
- g_free (list);
-}
-
-static ViviCodeBlock *
-create_block (ViviCodeToken **list)
-{
- ViviCodeBlock *block;
- int i;
-
- block = VIVI_CODE_BLOCK (vivi_code_block_new ());
-
- for (i = 0; list[i] != NULL; i++) {
- vivi_code_block_add_statement (block, VIVI_CODE_STATEMENT (list[i]));
- }
-
- return block;
-}
-
-// top
-
-static ParseStatus
-parse_source_element (GScanner *scanner, ViviCodeToken **token)
-{
- ParseStatus status;
-
- *token = NULL;
-
- status = parse (scanner, SYMBOL_FUNCTION_DECLARATION, token);
-
- if (status == STATUS_CANCEL)
- status = parse (scanner, SYMBOL_STATEMENT, token);
-
- return status;
-}
-
-// function
-
-static ParseStatus
-parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
-{
- //ViviCodeToken *function;
- ViviCodeToken *identifier;
- ViviCodeToken **arguments, **body;
-
- *token = NULL;
-
- identifier = NULL;
- arguments = NULL;
- body = NULL;
-
- if (!check_token (scanner, TOKEN_FUNCTION))
- return STATUS_CANCEL;
-
- if (parse (scanner, SYMBOL_IDENTIFIER, &identifier) != STATUS_OK)
- return STATUS_FAIL;
-
- if (!check_token (scanner, '('))
- goto fail;
-
- if (parse_list (scanner, SYMBOL_IDENTIFIER, &arguments, ',') == STATUS_FAIL)
- goto fail;
-
- if (!check_token (scanner, ')'))
- goto fail;
-
- if (!check_token (scanner, '{'))
- goto fail;
-
- if (parse_list (scanner, SYMBOL_SOURCE_ELEMENT, &body, G_TOKEN_NONE)
- == STATUS_FAIL)
- goto fail;
-
- if (!check_token (scanner, '}'))
- goto fail;
-
- /*function = vivi_code_function_new (arguments, body);
- *token = VIVI_CODE_TOKEN (
- vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
- VIVI_CODE_VALUE (function)));*/
- *token = VIVI_CODE_TOKEN (vivi_code_empty_new ());
-
- g_object_unref (identifier);
- if (arguments != NULL)
- free_list (arguments);
- if (body != NULL)
- free_list (body);
-
- return STATUS_OK;
-
-fail:
- if (identifier != NULL)
- g_object_unref (identifier);
- if (arguments != NULL)
- free_list (arguments);
- if (body != NULL)
- free_list (body);
-
- return STATUS_FAIL;
-}
-
-// statement
-
-static ParseStatus
-parse_statement (GScanner *scanner, ViviCodeToken **token)
-{
- int i, status;
- ParseSymbol options[] = {
- SYMBOL_BLOCK,
- SYMBOL_VARIABLE_STATEMENT,
- SYMBOL_EMPTY_STATEMENT,
- SYMBOL_EXPRESSION_STATEMENT,
- SYMBOL_IF_STATEMENT,
- SYMBOL_ITERATION_STATEMENT,
- SYMBOL_CONTINUE_STATEMENT,
- SYMBOL_BREAK_STATEMENT,
- SYMBOL_RETURN_STATEMENT,
- SYMBOL_WITH_STATEMENT,
- SYMBOL_LABELLED_STATEMENT,
- SYMBOL_SWITCH_STATEMENT,
- SYMBOL_THROW_STATEMENT,
- SYMBOL_TRY_STATEMENT,
- SYMBOL_NONE
- };
-
- *token = NULL;
-
- for (i = 0; options[i] != SYMBOL_NONE; i++) {
- status = parse (scanner, options[i], token);
- if (status != STATUS_CANCEL)
- return status;
- }
-
- return STATUS_CANCEL;
-}
-
-static ParseStatus
-parse_block (GScanner *scanner, ViviCodeToken **token)
-{
- ViviCodeToken **list;
-
- *token = NULL;
-
- if (!check_token (scanner, '{'))
- return STATUS_CANCEL;
-
- list = NULL;
-
- g_scanner_peek_next_token (scanner);
- if (scanner->next_token != '}') {
- if (parse_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
- != STATUS_OK)
- return STATUS_FAIL;
- }
-
- if (!check_token (scanner, '}')) {
- if (list != NULL)
- free_list (list);
- return STATUS_FAIL;
- }
-
- *token = VIVI_CODE_TOKEN (create_block (list));
- free_list (list);
-
- return STATUS_OK;
-}
-
-static ParseStatus
-parse_empty_statement (GScanner *scanner, ViviCodeToken **token)
-{
- *token = NULL;
-
- if (!check_token (scanner, ';'))
- return STATUS_CANCEL;
-
- *token = VIVI_CODE_TOKEN (vivi_code_empty_new ());
-
- return STATUS_OK;
-}
-
-static ParseStatus
-parse_expression_statement (GScanner *scanner, ViviCodeToken **token)
-{
- ParseStatus status;
-
- *token = NULL;
-
- g_scanner_peek_next_token (scanner);
- if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
- return STATUS_CANCEL;
-
- status = parse (scanner, SYMBOL_EXPRESSION, token);
- if (status != STATUS_OK)
- return status;
-
- if (!check_token (scanner, ';')) {
- g_object_unref (*token);
- *token = NULL;
- return STATUS_FAIL;
- }
-
- return STATUS_OK;
-}
-
-// expression
-
-static ParseStatus
-parse_expression (GScanner *scanner, ViviCodeToken **token)
-{
- ViviCodeToken **list;
- ParseStatus status;
-
- *token = NULL;
-
- status = parse_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
- if (status != STATUS_OK)
- return status;
-
- if (list[1] == NULL) {
- *token = g_object_ref (list[0]);
- } else {
- *token = VIVI_CODE_TOKEN (create_block (list));
- }
-
- free_list (list);
-
- return STATUS_OK;
-}
-
-static ParseStatus
-parse_assignment_expression (GScanner *scanner, ViviCodeToken **token)
-{
- *token = NULL;
-
- // TODO
-
- return parse (scanner, SYMBOL_CONDITIONAL_EXPRESSION, token);
-}
-
-static ParseStatus
-parse_conditional_expression (GScanner *scanner, ViviCodeToken **token)
-{
- ParseStatus status;
- ViviCodeToken *value;
- ViviCodeToken *first, *second;
-
- *token = NULL;
- first = NULL;
-
- status = parse (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
- if (status != STATUS_OK)
- return status;
-
- if (!check_token (scanner, '?')) {
- *token = VIVI_CODE_TOKEN (
- vivi_code_value_statement_new (VIVI_CODE_VALUE (value)));
- g_object_unref (value);
- return STATUS_OK;
- }
-
- if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &first) != STATUS_OK)
- goto fail;
-
- if (!check_token (scanner, ':'))
- goto fail;
-
- if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &second) != STATUS_OK)
- goto fail;
-
- //*token = vivi_code_condional_new (VIVI_CODE_VALUE (value),
- // VIVI_CODE_STATEMENT (first), VIVI_CODE_STATEMENT (second));
-
- g_object_unref (value);
- g_object_unref (first);
- g_object_unref (second);
-
- return STATUS_OK;
-
-fail:
-
- g_object_unref (value);
- if (first != NULL)
- g_object_unref (first);
-
- return STATUS_FAIL;
-}
-
-static ParseStatus
-parse_operator_expression (GScanner *scanner, ViviCodeToken **token)
-{
- ParseStatus status;
- ViviCodeValue *left;
- ViviCodeToken *right;
-
- *token = NULL;
-
- status = parse (scanner, SYMBOL_UNARY_EXPRESSION, token);
- if (status != STATUS_OK)
- return status;
-
- do {
- if (!check_token (scanner, '+'))
- return STATUS_OK;
-
- if (parse (scanner, SYMBOL_UNARY_EXPRESSION, &right) != STATUS_OK) {
- g_object_unref (*token);
- *token = NULL;
- return STATUS_FAIL;
- }
-
- left = VIVI_CODE_VALUE (token);
- *token = VIVI_CODE_TOKEN (vivi_code_binary_new_name (left,
- VIVI_CODE_VALUE (right), "+"));
- g_object_unref (left);
- g_object_unref (right);
- } while (TRUE);
-
- g_object_unref (*token);
- *token = NULL;
-
- return STATUS_FAIL;
-}
-
-static ParseStatus
-parse_unary_expression (GScanner *scanner, ViviCodeToken **token)
-{
- ViviCodeValue *value;
-
- *token = NULL;
-
- if (check_token (scanner, '!')) {
- parse (scanner, SYMBOL_UNARY_EXPRESSION, token);
- value = VIVI_CODE_VALUE (*token);
- *token = VIVI_CODE_TOKEN (vivi_code_unary_new (value, '!'));
- g_object_unref (value);
- return STATUS_OK;
- } else {
- return parse (scanner, SYMBOL_POSTFIX_EXPRESSION, token);
- }
-}
-
-static ParseStatus
-parse_postfix_expression (GScanner *scanner, ViviCodeToken **token)
-{
- //ViviCodeValue *value;
- ParseStatus status;
-
- status = parse (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION, token);
- if (status != STATUS_OK)
- return status;
-
- // FIXME: Don't allow new line here
-
- /*if (check_token (scanner, TOKEN_PLUSPLUS)) {
- value = VIVI_CODE_VALUE (*token);
- *token = VIVI_CODE_TOKEN (vivi_code_postfix_new (value, "++"));
- g_object_unref (value);
- } else {*/
- return STATUS_OK;
- //}
-}
-
-static ParseStatus
-parse_left_hand_side_expression (GScanner *scanner, ViviCodeToken **token)
-{
- ParseStatus status;
-
- *token = NULL;
-
- status = parse (scanner, SYMBOL_NEW_EXPRESSION, token);
- if (status == STATUS_CANCEL)
- status = parse (scanner, SYMBOL_CALL_EXPRESSION, token);
-
- return status;
-}
-
-static ParseStatus
-parse_new_expression (GScanner *scanner, ViviCodeToken **token)
-{
- *token = NULL;
-
- if (check_token (scanner, TOKEN_NEW)) {
- if (parse (scanner, SYMBOL_NEW_EXPRESSION, token) != STATUS_OK)
- return STATUS_FAIL;
- if (!VIVI_IS_CODE_FUNCTION_CALL (*token)) {
- ViviCodeValue *value = VIVI_CODE_VALUE (*token);
- *token = VIVI_CODE_TOKEN (vivi_code_function_call_new (NULL, value));
- g_object_unref (value);
- }
- vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*token),
- TRUE);
- return STATUS_OK;
- } else {
- return parse (scanner, SYMBOL_MEMBER_EXPRESSION, token);
- }
-}
-
-static ParseStatus
-parse_member_expression (GScanner *scanner, ViviCodeToken **token)
-{
- ParseStatus status;
- ViviCodeValue *value;
- ViviCodeToken *member;
-
- // TODO: new MemberExpression Arguments
-
- status = parse (scanner, SYMBOL_PRIMARY_EXPRESSION, token);
- if (status == STATUS_CANCEL)
- status = parse (scanner, SYMBOL_FUNCTION_EXPRESSION, token);
-
- if (status != 0)
- return status;
-
- do {
- if (check_token (scanner, '[')) {
- if (parse (scanner, SYMBOL_EXPRESSION, &member) != STATUS_OK)
- return STATUS_FAIL;
- if (!check_token (scanner, ']'))
- return STATUS_FAIL;
- } else if (check_token (scanner, '.')) {
- if (parse (scanner, SYMBOL_IDENTIFIER, &member) != STATUS_OK)
- return STATUS_FAIL;
- } else {
- return STATUS_OK;
- }
-
- value = VIVI_CODE_VALUE (token);
- *token = VIVI_CODE_TOKEN (
- vivi_code_get_new (value, VIVI_CODE_VALUE (member)));
- g_object_unref (value);
- g_object_unref (member);
- } while (TRUE);
-
- g_assert_not_reached ();
- return STATUS_FAIL;
-}
-
-static ParseStatus
-parse_primary_expression (GScanner *scanner, ViviCodeToken **token)
-{
- return parse (scanner, SYMBOL_IDENTIFIER, token);
-}
-
-// misc.
-
-static ParseStatus
-parse_identifier (GScanner *scanner, ViviCodeToken **token)
-{
- *token = NULL;
-
- if (!check_token (scanner, G_TOKEN_IDENTIFIER))
- return STATUS_CANCEL;
-
- *token =
- VIVI_CODE_TOKEN (vivi_code_get_new_name (scanner->value.v_identifier));
-
- return STATUS_OK;
-}
-
-// parsing
-
-static const struct {
- ParseSymbol id;
- const char * name;
- ParseFunction parse;
-} symbols[] = {
- // top
- { SYMBOL_SOURCE_ELEMENT, "SourceElement", parse_source_element },
- // function
- { SYMBOL_FUNCTION_DECLARATION, "FunctionDeclaration",
- parse_function_declaration },
- // statement
- { SYMBOL_STATEMENT, "Statement", parse_statement },
- { SYMBOL_BLOCK, "Block", parse_block },
- { SYMBOL_EMPTY_STATEMENT, "EmptyStatement", parse_empty_statement },
- { SYMBOL_EXPRESSION_STATEMENT, "ExpressionStatement",
- parse_expression_statement },
- // expression
- { SYMBOL_EXPRESSION, "Expression", parse_expression },
- { SYMBOL_ASSIGNMENT_EXPRESSION, "AssigmentExpression",
- parse_assignment_expression },
- { SYMBOL_CONDITIONAL_EXPRESSION, "ConditionalExpression",
- parse_conditional_expression },
- { SYMBOL_OPERATOR_EXPRESSION, "OperatorExpression",
- parse_operator_expression },
- { SYMBOL_UNARY_EXPRESSION, "UnaryExpression", parse_unary_expression },
- { SYMBOL_POSTFIX_EXPRESSION, "PostfixExpression", parse_postfix_expression },
- { SYMBOL_LEFT_HAND_SIDE_EXPRESSION, "LeftHandSideExpression",
- parse_left_hand_side_expression },
- { SYMBOL_NEW_EXPRESSION, "NewExpression", parse_new_expression },
- { SYMBOL_MEMBER_EXPRESSION, "MemberExpression", parse_member_expression },
- { SYMBOL_PRIMARY_EXPRESSION, "PrimaryExpression", parse_primary_expression },
- // misc
- { SYMBOL_IDENTIFIER, "Identifier", parse_identifier },
- { SYMBOL_NONE, NULL, NULL }
-};
-
-static ParseStatus
-parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token)
-{
- int i;
-
- g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
- g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
- g_return_val_if_fail (token != NULL, STATUS_FAIL);
-
- for (i = 0; symbols[i].id != SYMBOL_NONE; i++) {
- if (symbols[i].id == symbol) {
- ParseStatus status = symbols[i].parse (scanner, token);
- g_assert ((status == STATUS_OK && VIVI_IS_CODE_TOKEN (*token)) ||
- (status != STATUS_OK && *token == NULL));
- if (status != STATUS_CANCEL)
- g_print (":%i: %s\n", status, symbols[i].name);
- return status;
- }
- }
-
- //g_assert_not_reached ();
- return STATUS_CANCEL;
-}
-
-static ParseStatus
-parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
- guint separator)
-{
- GPtrArray *array;
- ViviCodeToken *token;
- ParseStatus ret;
-
- g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
- g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
- g_return_val_if_fail (list != NULL, STATUS_FAIL);
-
- ret = parse (scanner, symbol, &token);
- if (ret != STATUS_OK)
- return ret;
-
- array = g_ptr_array_new ();
-
- do {
- g_ptr_array_add (array, token);
-
- if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
- break;
-
- ret = parse (scanner, symbol, &token);
- if (ret == STATUS_FAIL)
- return STATUS_FAIL;
- } while (ret == STATUS_OK);
- g_ptr_array_add (array, NULL);
-
- *list = (ViviCodeToken **)g_ptr_array_free (array, FALSE);
-
- return STATUS_OK;
-}
-
-// main
+#include "vivi_compiler.h"
+#include "vivi_code_text_printer.h"
int
main (int argc, char *argv[])
{
- GScanner *scanner;
- char *test_text;
- gsize test_text_len;
- int ret;
- ViviCodeToken **list;
SwfdecPlayer *player;
+ char *text;
+ gsize text_len;
+ ViviCodeStatement *statement;
player = swfdec_player_new (NULL);
- if (argc < 2) {
- g_print ("Usage!\n");
+ if (argc != 2) {
+ g_printerr ("Usage: %s <filename>\n", argv[0]);
return 1;
}
- if (!g_file_get_contents (argv[1], &test_text, &test_text_len, NULL)) {
+ if (!g_file_get_contents (argv[1], &text, &text_len, NULL)) {
g_printerr ("Couldn't open file %s", argv[1]);
return -1;
}
- scanner = g_scanner_new (NULL);
-
- scanner->config->numbers_2_int = TRUE;
- scanner->config->int_2_float = TRUE;
- scanner->config->symbol_2_token = TRUE;
-
- g_scanner_set_scope (scanner, 0);
- g_scanner_scope_add_symbol (scanner, 0, "function",
- GINT_TO_POINTER(TOKEN_FUNCTION));
- g_scanner_scope_add_symbol (scanner, 0, "++",
- GINT_TO_POINTER(TOKEN_PLUSPLUS));
- g_scanner_scope_add_symbol (scanner, 0, "--",
- GINT_TO_POINTER(TOKEN_MINUSMINUS));
- g_scanner_scope_add_symbol (scanner, 0, "new", GINT_TO_POINTER(TOKEN_NEW));
-
- scanner->input_name = argv[1];
- g_scanner_input_text (scanner, test_text, test_text_len);
-
-
- ret = parse_list (scanner, SYMBOL_SOURCE_ELEMENT, &list, G_TOKEN_NONE);
- g_print ("%i: %i, %i\n", ret,
- g_scanner_cur_line (scanner), g_scanner_cur_position (scanner));
-
- g_scanner_peek_next_token (scanner);
- while (scanner->next_token != G_TOKEN_EOF &&
- scanner->next_token != G_TOKEN_ERROR)
- {
- g_scanner_get_next_token (scanner);
- g_print (":: %i, %i :: ", g_scanner_cur_line (scanner),
- g_scanner_cur_position (scanner));
- switch ((int)scanner->token) {
- case G_TOKEN_SYMBOL:
- g_print ("SYMBOL\n");
- break;
- case G_TOKEN_FLOAT:
- g_print ("Primitive: %f\n", scanner->value.v_float);
- break;
- case G_TOKEN_STRING:
- g_print ("Primitive: \"%s\"\n", scanner->value.v_string);
- break;
- case G_TOKEN_NONE:
- g_print ("NONE\n");
- break;
- case G_TOKEN_IDENTIFIER:
- g_print ("Identifier: %s\n", scanner->value.v_identifier);
- break;
- default:
- if (scanner->token > 0 && scanner->token < 256) {
- g_print ("%c\n", scanner->token);
- } else {
- g_print ("TOKEN %i\n", scanner->token);
- }
- break;
- }
- g_scanner_peek_next_token (scanner);
+ statement = vivi_compile_text (text, text_len, argv[1]);
+ if (statement == NULL) {
+ g_printerr ("Compilation failed\n");
+ return -1;
+ } else {
+ ViviCodePrinter *printer = vivi_code_text_printer_new ();
+ vivi_code_printer_print_token (printer, VIVI_CODE_TOKEN (statement));
+ g_object_unref (printer);
+ return 0;
}
-
- g_scanner_destroy (scanner);
-
- return 0;
}
diff --git a/vivified/code/vivi_compiler.c b/vivified/code/vivi_compiler.c
new file mode 100644
index 0000000..53d873c
--- /dev/null
+++ b/vivified/code/vivi_compiler.c
@@ -0,0 +1,743 @@
+/* Vivified
+ * Copyright (C) 2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "vivi_compiler.h"
+
+#include "vivi_code_assignment.h"
+#include "vivi_code_binary.h"
+#include "vivi_code_block.h"
+#include "vivi_code_break.h"
+#include "vivi_code_constant.h"
+#include "vivi_code_continue.h"
+#include "vivi_code_empty.h"
+#include "vivi_code_function.h"
+#include "vivi_code_function_call.h"
+#include "vivi_code_get.h"
+#include "vivi_code_get_url.h"
+#include "vivi_code_goto.h"
+#include "vivi_code_if.h"
+#include "vivi_code_init_object.h"
+#include "vivi_code_loop.h"
+#include "vivi_code_return.h"
+#include "vivi_code_trace.h"
+#include "vivi_code_unary.h"
+#include "vivi_code_value_statement.h"
+
+#include "vivi_code_text_printer.h"
+
+typedef enum {
+ STATUS_FAIL = -1,
+ STATUS_OK = 0,
+ STATUS_CANCEL = 1
+} ParseStatus;
+
+enum {
+ TOKEN_FUNCTION = G_TOKEN_LAST + 1,
+ TOKEN_PLUSPLUS = G_TOKEN_LAST + 2,
+ TOKEN_MINUSMINUS = G_TOKEN_LAST + 3,
+ TOKEN_NEW = G_TOKEN_LAST + 4
+};
+
+typedef enum {
+ SYMBOL_NONE,
+ // top
+ SYMBOL_PROGRAM,
+ SYMBOL_SOURCE_ELEMENT,
+ // function
+ SYMBOL_FUNCTION_DECLARATION,
+ // statement
+ SYMBOL_STATEMENT,
+ SYMBOL_BLOCK,
+ SYMBOL_VARIABLE_STATEMENT,
+ SYMBOL_EMPTY_STATEMENT,
+ SYMBOL_EXPRESSION_STATEMENT,
+ SYMBOL_IF_STATEMENT,
+ SYMBOL_ITERATION_STATEMENT,
+ SYMBOL_CONTINUE_STATEMENT,
+ SYMBOL_BREAK_STATEMENT,
+ SYMBOL_RETURN_STATEMENT,
+ SYMBOL_WITH_STATEMENT,
+ SYMBOL_LABELLED_STATEMENT,
+ SYMBOL_SWITCH_STATEMENT,
+ SYMBOL_THROW_STATEMENT,
+ SYMBOL_TRY_STATEMENT,
+ // expression
+ SYMBOL_EXPRESSION,
+ SYMBOL_ASSIGNMENT_EXPRESSION,
+ SYMBOL_CONDITIONAL_EXPRESSION,
+ SYMBOL_LEFT_HAND_SIDE_EXPRESSION,
+ SYMBOL_OPERATOR_EXPRESSION,
+ SYMBOL_UNARY_EXPRESSION,
+ SYMBOL_POSTFIX_EXPRESSION,
+ SYMBOL_NEW_EXPRESSION,
+ SYMBOL_CALL_EXPRESSION,
+ SYMBOL_MEMBER_EXPRESSION,
+ SYMBOL_FUNCTION_EXPRESSION,
+ SYMBOL_PRIMARY_EXPRESSION,
+ // misc
+ SYMBOL_IDENTIFIER,
+ SYMBOL_ASSIGNMENT_OPERATOR,
+ SYMBOL_ARGUMENTS,
+} ParseSymbol;
+
+typedef ParseStatus (*ParseFunction) (GScanner *scanner, ViviCodeToken **token);
+
+static ParseStatus
+parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token);
+
+static ParseStatus
+parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
+ guint separator);
+
+// helpers
+
+static gboolean
+check_token (GScanner *scanner, guint token)
+{
+ g_scanner_peek_next_token (scanner);
+ if (scanner->next_token != token)
+ return FALSE;
+ g_scanner_get_next_token (scanner);
+ return TRUE;
+}
+
+static void
+free_list (ViviCodeToken **list)
+{
+ int i;
+
+ for (i = 0; list[i] != NULL; i++) {
+ g_object_unref (list[i]);
+ }
+ g_free (list);
+}
+
+static ViviCodeBlock *
+create_block (ViviCodeToken **list)
+{
+ ViviCodeBlock *block;
+ int i;
+
+ block = VIVI_CODE_BLOCK (vivi_code_block_new ());
+
+ for (i = 0; list[i] != NULL; i++) {
+ vivi_code_block_add_statement (block, VIVI_CODE_STATEMENT (list[i]));
+ }
+
+ return block;
+}
+
+// top
+
+static ParseStatus
+parse_program (GScanner *scanner, ViviCodeToken **token)
+{
+ ParseStatus status;
+ ViviCodeToken **list;
+
+ *token = NULL;
+
+ status = parse_list (scanner, SYMBOL_SOURCE_ELEMENT, &list, G_TOKEN_NONE);
+ if (status != STATUS_OK)
+ return status;
+
+ *token = VIVI_CODE_TOKEN (create_block (list));
+
+ return STATUS_OK;
+}
+
+static ParseStatus
+parse_source_element (GScanner *scanner, ViviCodeToken **token)
+{
+ ParseStatus status;
+
+ *token = NULL;
+
+ status = parse (scanner, SYMBOL_FUNCTION_DECLARATION, token);
+
+ if (status == STATUS_CANCEL)
+ status = parse (scanner, SYMBOL_STATEMENT, token);
+
+ return status;
+}
+
+// function
+
+static ParseStatus
+parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
+{
+ //ViviCodeToken *function;
+ ViviCodeToken *identifier;
+ ViviCodeToken **arguments, **body;
+
+ *token = NULL;
+
+ identifier = NULL;
+ arguments = NULL;
+ body = NULL;
+
+ if (!check_token (scanner, TOKEN_FUNCTION))
+ return STATUS_CANCEL;
+
+ if (parse (scanner, SYMBOL_IDENTIFIER, &identifier) != STATUS_OK)
+ return STATUS_FAIL;
+
+ if (!check_token (scanner, '('))
+ goto fail;
+
+ if (parse_list (scanner, SYMBOL_IDENTIFIER, &arguments, ',') == STATUS_FAIL)
+ goto fail;
+
+ if (!check_token (scanner, ')'))
+ goto fail;
+
+ if (!check_token (scanner, '{'))
+ goto fail;
+
+ if (parse_list (scanner, SYMBOL_SOURCE_ELEMENT, &body, G_TOKEN_NONE)
+ == STATUS_FAIL)
+ goto fail;
+
+ if (!check_token (scanner, '}'))
+ goto fail;
+
+ /*function = vivi_code_function_new (arguments, body);
+ *token = VIVI_CODE_TOKEN (
+ vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
+ VIVI_CODE_VALUE (function)));*/
+ *token = VIVI_CODE_TOKEN (vivi_code_empty_new ());
+
+ g_object_unref (identifier);
+ if (arguments != NULL)
+ free_list (arguments);
+ if (body != NULL)
+ free_list (body);
+
+ return STATUS_OK;
+
+fail:
+ if (identifier != NULL)
+ g_object_unref (identifier);
+ if (arguments != NULL)
+ free_list (arguments);
+ if (body != NULL)
+ free_list (body);
+
+ return STATUS_FAIL;
+}
+
+// statement
+
+static ParseStatus
+parse_statement (GScanner *scanner, ViviCodeToken **token)
+{
+ int i, status;
+ ParseSymbol options[] = {
+ SYMBOL_BLOCK,
+ SYMBOL_VARIABLE_STATEMENT,
+ SYMBOL_EMPTY_STATEMENT,
+ SYMBOL_EXPRESSION_STATEMENT,
+ SYMBOL_IF_STATEMENT,
+ SYMBOL_ITERATION_STATEMENT,
+ SYMBOL_CONTINUE_STATEMENT,
+ SYMBOL_BREAK_STATEMENT,
+ SYMBOL_RETURN_STATEMENT,
+ SYMBOL_WITH_STATEMENT,
+ SYMBOL_LABELLED_STATEMENT,
+ SYMBOL_SWITCH_STATEMENT,
+ SYMBOL_THROW_STATEMENT,
+ SYMBOL_TRY_STATEMENT,
+ SYMBOL_NONE
+ };
+
+ *token = NULL;
+
+ for (i = 0; options[i] != SYMBOL_NONE; i++) {
+ status = parse (scanner, options[i], token);
+ if (status != STATUS_CANCEL)
+ return status;
+ }
+
+ return STATUS_CANCEL;
+}
+
+static ParseStatus
+parse_block (GScanner *scanner, ViviCodeToken **token)
+{
+ ViviCodeToken **list;
+
+ *token = NULL;
+
+ if (!check_token (scanner, '{'))
+ return STATUS_CANCEL;
+
+ list = NULL;
+
+ g_scanner_peek_next_token (scanner);
+ if (scanner->next_token != '}') {
+ if (parse_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
+ != STATUS_OK)
+ return STATUS_FAIL;
+ }
+
+ if (!check_token (scanner, '}')) {
+ if (list != NULL)
+ free_list (list);
+ return STATUS_FAIL;
+ }
+
+ *token = VIVI_CODE_TOKEN (create_block (list));
+ free_list (list);
+
+ return STATUS_OK;
+}
+
+static ParseStatus
+parse_empty_statement (GScanner *scanner, ViviCodeToken **token)
+{
+ *token = NULL;
+
+ if (!check_token (scanner, ';'))
+ return STATUS_CANCEL;
+
+ *token = VIVI_CODE_TOKEN (vivi_code_empty_new ());
+
+ return STATUS_OK;
+}
+
+static ParseStatus
+parse_expression_statement (GScanner *scanner, ViviCodeToken **token)
+{
+ ParseStatus status;
+
+ *token = NULL;
+
+ g_scanner_peek_next_token (scanner);
+ if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
+ return STATUS_CANCEL;
+
+ status = parse (scanner, SYMBOL_EXPRESSION, token);
+ if (status != STATUS_OK)
+ return status;
+
+ if (!check_token (scanner, ';')) {
+ g_object_unref (*token);
+ *token = NULL;
+ return STATUS_FAIL;
+ }
+
+ return STATUS_OK;
+}
+
+// expression
+
+static ParseStatus
+parse_expression (GScanner *scanner, ViviCodeToken **token)
+{
+ ViviCodeToken **list;
+ ParseStatus status;
+
+ *token = NULL;
+
+ status = parse_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
+ if (status != STATUS_OK)
+ return status;
+
+ if (list[1] == NULL) {
+ *token = g_object_ref (list[0]);
+ } else {
+ *token = VIVI_CODE_TOKEN (create_block (list));
+ }
+
+ free_list (list);
+
+ return STATUS_OK;
+}
+
+static ParseStatus
+parse_assignment_expression (GScanner *scanner, ViviCodeToken **token)
+{
+ *token = NULL;
+
+ // TODO
+
+ return parse (scanner, SYMBOL_CONDITIONAL_EXPRESSION, token);
+}
+
+static ParseStatus
+parse_conditional_expression (GScanner *scanner, ViviCodeToken **token)
+{
+ ParseStatus status;
+ ViviCodeToken *value;
+ ViviCodeToken *first, *second;
+
+ *token = NULL;
+ first = NULL;
+
+ status = parse (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
+ if (status != STATUS_OK)
+ return status;
+
+ if (!check_token (scanner, '?')) {
+ *token = VIVI_CODE_TOKEN (
+ vivi_code_value_statement_new (VIVI_CODE_VALUE (value)));
+ g_object_unref (value);
+ return STATUS_OK;
+ }
+
+ if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &first) != STATUS_OK)
+ goto fail;
+
+ if (!check_token (scanner, ':'))
+ goto fail;
+
+ if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &second) != STATUS_OK)
+ goto fail;
+
+ //*token = vivi_code_condional_new (VIVI_CODE_VALUE (value),
+ // VIVI_CODE_STATEMENT (first), VIVI_CODE_STATEMENT (second));
+
+ g_object_unref (value);
+ g_object_unref (first);
+ g_object_unref (second);
+
+ return STATUS_OK;
+
+fail:
+
+ g_object_unref (value);
+ if (first != NULL)
+ g_object_unref (first);
+
+ return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_operator_expression (GScanner *scanner, ViviCodeToken **token)
+{
+ ParseStatus status;
+ ViviCodeValue *left;
+ ViviCodeToken *right;
+
+ *token = NULL;
+
+ status = parse (scanner, SYMBOL_UNARY_EXPRESSION, token);
+ if (status != STATUS_OK)
+ return status;
+
+ do {
+ if (!check_token (scanner, '+'))
+ return STATUS_OK;
+
+ if (parse (scanner, SYMBOL_UNARY_EXPRESSION, &right) != STATUS_OK) {
+ g_object_unref (*token);
+ *token = NULL;
+ return STATUS_FAIL;
+ }
+
+ left = VIVI_CODE_VALUE (*token);
+ *token = VIVI_CODE_TOKEN (vivi_code_binary_new_name (left,
+ VIVI_CODE_VALUE (right), "+"));
+ g_object_unref (left);
+ g_object_unref (right);
+ } while (TRUE);
+
+ g_object_unref (*token);
+ *token = NULL;
+
+ return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_unary_expression (GScanner *scanner, ViviCodeToken **token)
+{
+ ViviCodeValue *value;
+
+ *token = NULL;
+
+ if (check_token (scanner, '!')) {
+ parse (scanner, SYMBOL_UNARY_EXPRESSION, token);
+ value = VIVI_CODE_VALUE (*token);
+ *token = VIVI_CODE_TOKEN (vivi_code_unary_new (value, '!'));
+ g_object_unref (value);
+ return STATUS_OK;
+ } else {
+ return parse (scanner, SYMBOL_POSTFIX_EXPRESSION, token);
+ }
+}
+
+static ParseStatus
+parse_postfix_expression (GScanner *scanner, ViviCodeToken **token)
+{
+ //ViviCodeValue *value;
+ ParseStatus status;
+
+ status = parse (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION, token);
+ if (status != STATUS_OK)
+ return status;
+
+ // FIXME: Don't allow new line here
+
+ /*if (check_token (scanner, TOKEN_PLUSPLUS)) {
+ value = VIVI_CODE_VALUE (*token);
+ *token = VIVI_CODE_TOKEN (vivi_code_postfix_new (value, "++"));
+ g_object_unref (value);
+ } else {*/
+ return STATUS_OK;
+ //}
+}
+
+static ParseStatus
+parse_left_hand_side_expression (GScanner *scanner, ViviCodeToken **token)
+{
+ ParseStatus status;
+
+ *token = NULL;
+
+ status = parse (scanner, SYMBOL_NEW_EXPRESSION, token);
+ if (status == STATUS_CANCEL)
+ status = parse (scanner, SYMBOL_CALL_EXPRESSION, token);
+
+ return status;
+}
+
+static ParseStatus
+parse_new_expression (GScanner *scanner, ViviCodeToken **token)
+{
+ *token = NULL;
+
+ if (check_token (scanner, TOKEN_NEW)) {
+ if (parse (scanner, SYMBOL_NEW_EXPRESSION, token) != STATUS_OK)
+ return STATUS_FAIL;
+ if (!VIVI_IS_CODE_FUNCTION_CALL (*token)) {
+ ViviCodeValue *value = VIVI_CODE_VALUE (*token);
+ *token = VIVI_CODE_TOKEN (vivi_code_function_call_new (NULL, value));
+ g_object_unref (value);
+ }
+ vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*token),
+ TRUE);
+ return STATUS_OK;
+ } else {
+ return parse (scanner, SYMBOL_MEMBER_EXPRESSION, token);
+ }
+}
+
+static ParseStatus
+parse_member_expression (GScanner *scanner, ViviCodeToken **token)
+{
+ ParseStatus status;
+ ViviCodeValue *value;
+ ViviCodeToken *member;
+
+ // TODO: new MemberExpression Arguments
+
+ status = parse (scanner, SYMBOL_PRIMARY_EXPRESSION, token);
+ if (status == STATUS_CANCEL)
+ status = parse (scanner, SYMBOL_FUNCTION_EXPRESSION, token);
+
+ if (status != 0)
+ return status;
+
+ do {
+ if (check_token (scanner, '[')) {
+ if (parse (scanner, SYMBOL_EXPRESSION, &member) != STATUS_OK)
+ return STATUS_FAIL;
+ if (!check_token (scanner, ']'))
+ return STATUS_FAIL;
+ } else if (check_token (scanner, '.')) {
+ if (parse (scanner, SYMBOL_IDENTIFIER, &member) != STATUS_OK)
+ return STATUS_FAIL;
+ } else {
+ return STATUS_OK;
+ }
+
+ value = VIVI_CODE_VALUE (token);
+ *token = VIVI_CODE_TOKEN (
+ vivi_code_get_new (value, VIVI_CODE_VALUE (member)));
+ g_object_unref (value);
+ g_object_unref (member);
+ } while (TRUE);
+
+ g_assert_not_reached ();
+ return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_primary_expression (GScanner *scanner, ViviCodeToken **token)
+{
+ return parse (scanner, SYMBOL_IDENTIFIER, token);
+}
+
+// misc.
+
+static ParseStatus
+parse_identifier (GScanner *scanner, ViviCodeToken **token)
+{
+ *token = NULL;
+
+ if (!check_token (scanner, G_TOKEN_IDENTIFIER))
+ return STATUS_CANCEL;
+
+ *token =
+ VIVI_CODE_TOKEN (vivi_code_get_new_name (scanner->value.v_identifier));
+
+ return STATUS_OK;
+}
+
+// parsing
+
+static const struct {
+ ParseSymbol id;
+ const char * name;
+ ParseFunction parse;
+} symbols[] = {
+ // top
+ { SYMBOL_PROGRAM, "Program", parse_program },
+ { SYMBOL_SOURCE_ELEMENT, "SourceElement", parse_source_element },
+ // function
+ { SYMBOL_FUNCTION_DECLARATION, "FunctionDeclaration",
+ parse_function_declaration },
+ // statement
+ { SYMBOL_STATEMENT, "Statement", parse_statement },
+ { SYMBOL_BLOCK, "Block", parse_block },
+ { SYMBOL_EMPTY_STATEMENT, "EmptyStatement", parse_empty_statement },
+ { SYMBOL_EXPRESSION_STATEMENT, "ExpressionStatement",
+ parse_expression_statement },
+ // expression
+ { SYMBOL_EXPRESSION, "Expression", parse_expression },
+ { SYMBOL_ASSIGNMENT_EXPRESSION, "AssigmentExpression",
+ parse_assignment_expression },
+ { SYMBOL_CONDITIONAL_EXPRESSION, "ConditionalExpression",
+ parse_conditional_expression },
+ { SYMBOL_OPERATOR_EXPRESSION, "OperatorExpression",
+ parse_operator_expression },
+ { SYMBOL_UNARY_EXPRESSION, "UnaryExpression", parse_unary_expression },
+ { SYMBOL_POSTFIX_EXPRESSION, "PostfixExpression", parse_postfix_expression },
+ { SYMBOL_LEFT_HAND_SIDE_EXPRESSION, "LeftHandSideExpression",
+ parse_left_hand_side_expression },
+ { SYMBOL_NEW_EXPRESSION, "NewExpression", parse_new_expression },
+ { SYMBOL_MEMBER_EXPRESSION, "MemberExpression", parse_member_expression },
+ { SYMBOL_PRIMARY_EXPRESSION, "PrimaryExpression", parse_primary_expression },
+ // misc
+ { SYMBOL_IDENTIFIER, "Identifier", parse_identifier },
+ { SYMBOL_NONE, NULL, NULL }
+};
+
+static ParseStatus
+parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token)
+{
+ int i;
+
+ g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
+ g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
+ g_return_val_if_fail (token != NULL, STATUS_FAIL);
+
+ for (i = 0; symbols[i].id != SYMBOL_NONE; i++) {
+ if (symbols[i].id == symbol) {
+ ParseStatus status = symbols[i].parse (scanner, token);
+ g_assert ((status == STATUS_OK && VIVI_IS_CODE_TOKEN (*token)) ||
+ (status != STATUS_OK && *token == NULL));
+ return status;
+ }
+ }
+
+ //g_assert_not_reached ();
+ return STATUS_CANCEL;
+}
+
+static ParseStatus
+parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
+ guint separator)
+{
+ GPtrArray *array;
+ ViviCodeToken *token;
+ ParseStatus ret;
+
+ g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
+ g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
+ g_return_val_if_fail (list != NULL, STATUS_FAIL);
+
+ ret = parse (scanner, symbol, &token);
+ if (ret != STATUS_OK)
+ return ret;
+
+ array = g_ptr_array_new ();
+
+ do {
+ g_ptr_array_add (array, token);
+
+ if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
+ break;
+
+ ret = parse (scanner, symbol, &token);
+ if (ret == STATUS_FAIL)
+ return STATUS_FAIL;
+ } while (ret == STATUS_OK);
+ g_ptr_array_add (array, NULL);
+
+ *list = (ViviCodeToken **)g_ptr_array_free (array, FALSE);
+
+ return STATUS_OK;
+}
+
+// public
+
+ViviCodeStatement *
+vivi_compile_text (const char *text, gsize len, const char *input_name)
+{
+ GScanner *scanner;
+ ViviCodeToken *token;
+ ParseStatus status;
+
+ g_return_val_if_fail (text != NULL, NULL);
+
+ scanner = g_scanner_new (NULL);
+
+ scanner->config->numbers_2_int = TRUE;
+ scanner->config->int_2_float = TRUE;
+ scanner->config->symbol_2_token = TRUE;
+
+ g_scanner_set_scope (scanner, 0);
+ g_scanner_scope_add_symbol (scanner, 0, "function",
+ GINT_TO_POINTER(TOKEN_FUNCTION));
+ g_scanner_scope_add_symbol (scanner, 0, "++",
+ GINT_TO_POINTER(TOKEN_PLUSPLUS));
+ g_scanner_scope_add_symbol (scanner, 0, "--",
+ GINT_TO_POINTER(TOKEN_MINUSMINUS));
+ g_scanner_scope_add_symbol (scanner, 0, "new", GINT_TO_POINTER(TOKEN_NEW));
+
+ scanner->input_name = input_name;
+ g_scanner_input_text (scanner, text, len);
+
+ status = parse (scanner, SYMBOL_PROGRAM, &token);
+
+ g_scanner_destroy (scanner);
+
+ if (status == STATUS_OK) {
+ return VIVI_CODE_STATEMENT (token);
+ } else {
+ return NULL;
+ }
+}
diff --git a/vivified/code/vivi_compiler.h b/vivified/code/vivi_compiler.h
new file mode 100644
index 0000000..f15108a
--- /dev/null
+++ b/vivified/code/vivi_compiler.h
@@ -0,0 +1,35 @@
+/* Vivified
+ * Copyright (C) 2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef _VIVI_DECOMPILER_H_
+#define _VIVI_DECOMPILER_H_
+
+#include <swfdec/swfdec.h>
+#include <vivified/code/vivi_code_statement.h>
+
+G_BEGIN_DECLS
+
+
+ViviCodeStatement * vivi_compile_text (const char * text,
+ gsize len,
+ const char * input_name);
+
+
+G_END_DECLS
+#endif
commit 547fc557d07560337cdeabd5ed63bb7e943a792c
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Fri Mar 28 17:40:29 2008 +0200
Fix few bugs in the compiler code
diff --git a/vivified/code/compiler.c b/vivified/code/compiler.c
index 12d8495..f550b1e 100644
--- a/vivified/code/compiler.c
+++ b/vivified/code/compiler.c
@@ -167,7 +167,8 @@ parse_source_element (GScanner *scanner, ViviCodeToken **token)
static ParseStatus
parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
{
- ViviCodeToken *function, *identifier;
+ //ViviCodeToken *function;
+ ViviCodeToken *identifier;
ViviCodeToken **arguments, **body;
*token = NULL;
@@ -201,16 +202,17 @@ parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
if (!check_token (scanner, '}'))
goto fail;
- //function = vivi_code_function_new (arguments, body);
- function = NULL;
+ /*function = vivi_code_function_new (arguments, body);
*token = VIVI_CODE_TOKEN (
vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
- VIVI_CODE_VALUE (function)));
+ VIVI_CODE_VALUE (function)));*/
+ *token = VIVI_CODE_TOKEN (vivi_code_empty_new ());
g_object_unref (identifier);
if (arguments != NULL)
free_list (arguments);
- free_list (body);
+ if (body != NULL)
+ free_list (body);
return STATUS_OK;
@@ -336,12 +338,14 @@ parse_expression (GScanner *scanner, ViviCodeToken **token)
ViviCodeToken **list;
ParseStatus status;
+ *token = NULL;
+
status = parse_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
if (status != STATUS_OK)
return status;
if (list[1] == NULL) {
- *token = list[0];
+ *token = g_object_ref (list[0]);
} else {
*token = VIVI_CODE_TOKEN (create_block (list));
}
@@ -624,12 +628,18 @@ parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token)
{
int i;
+ g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
+ g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
+ g_return_val_if_fail (token != NULL, STATUS_FAIL);
+
for (i = 0; symbols[i].id != SYMBOL_NONE; i++) {
if (symbols[i].id == symbol) {
- ParseStatus ret = symbols[i].parse (scanner, token);
- if (ret != STATUS_CANCEL)
- g_print (":%i: %s\n", ret, symbols[i].name);
- return ret;
+ ParseStatus status = symbols[i].parse (scanner, token);
+ g_assert ((status == STATUS_OK && VIVI_IS_CODE_TOKEN (*token)) ||
+ (status != STATUS_OK && *token == NULL));
+ if (status != STATUS_CANCEL)
+ g_print (":%i: %s\n", status, symbols[i].name);
+ return status;
}
}
@@ -645,6 +655,10 @@ parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
ViviCodeToken *token;
ParseStatus ret;
+ g_return_val_if_fail (scanner != NULL, STATUS_FAIL);
+ g_return_val_if_fail (symbol != SYMBOL_NONE, STATUS_FAIL);
+ g_return_val_if_fail (list != NULL, STATUS_FAIL);
+
ret = parse (scanner, symbol, &token);
if (ret != STATUS_OK)
return ret;
@@ -678,6 +692,9 @@ main (int argc, char *argv[])
gsize test_text_len;
int ret;
ViviCodeToken **list;
+ SwfdecPlayer *player;
+
+ player = swfdec_player_new (NULL);
if (argc < 2) {
g_print ("Usage!\n");
commit a320e121301b8d41b6f33e0076f54f0b1c5bde09
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Fri Mar 28 17:24:09 2008 +0200
More work on the compiler
diff --git a/vivified/code/compiler.c b/vivified/code/compiler.c
index 2df22bf..12d8495 100644
--- a/vivified/code/compiler.c
+++ b/vivified/code/compiler.c
@@ -80,6 +80,7 @@ typedef enum {
SYMBOL_THROW_STATEMENT,
SYMBOL_TRY_STATEMENT,
// expression
+ SYMBOL_EXPRESSION,
SYMBOL_ASSIGNMENT_EXPRESSION,
SYMBOL_CONDITIONAL_EXPRESSION,
SYMBOL_LEFT_HAND_SIDE_EXPRESSION,
@@ -201,6 +202,7 @@ parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
goto fail;
//function = vivi_code_function_new (arguments, body);
+ function = NULL;
*token = VIVI_CODE_TOKEN (
vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
VIVI_CODE_VALUE (function)));
@@ -305,7 +307,6 @@ parse_empty_statement (GScanner *scanner, ViviCodeToken **token)
static ParseStatus
parse_expression_statement (GScanner *scanner, ViviCodeToken **token)
{
- ViviCodeToken **list;
ParseStatus status;
*token = NULL;
@@ -314,22 +315,43 @@ parse_expression_statement (GScanner *scanner, ViviCodeToken **token)
if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
return STATUS_CANCEL;
- status = parse_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
+ status = parse (scanner, SYMBOL_EXPRESSION, token);
+ if (status != STATUS_OK)
+ return status;
- if (status == STATUS_OK) {
- if (list[1] == NULL) {
- *token = list[0];
- } else {
- *token = VIVI_CODE_TOKEN (create_block (list));
- }
+ if (!check_token (scanner, ';')) {
+ g_object_unref (*token);
+ *token = NULL;
+ return STATUS_FAIL;
}
- return status;
+ return STATUS_OK;
}
// expression
static ParseStatus
+parse_expression (GScanner *scanner, ViviCodeToken **token)
+{
+ ViviCodeToken **list;
+ ParseStatus status;
+
+ status = parse_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
+ if (status != STATUS_OK)
+ return status;
+
+ if (list[1] == NULL) {
+ *token = list[0];
+ } else {
+ *token = VIVI_CODE_TOKEN (create_block (list));
+ }
+
+ free_list (list);
+
+ return STATUS_OK;
+}
+
+static ParseStatus
parse_assignment_expression (GScanner *scanner, ViviCodeToken **token)
{
*token = NULL;
@@ -526,7 +548,7 @@ parse_member_expression (GScanner *scanner, ViviCodeToken **token)
return STATUS_OK;
}
- value = VIVI_CODE_VALUE (token)
+ value = VIVI_CODE_VALUE (token);
*token = VIVI_CODE_TOKEN (
vivi_code_get_new (value, VIVI_CODE_VALUE (member)));
g_object_unref (value);
@@ -553,16 +575,8 @@ parse_identifier (GScanner *scanner, ViviCodeToken **token)
if (!check_token (scanner, G_TOKEN_IDENTIFIER))
return STATUS_CANCEL;
- *token = VIVI_CODE_TOKEN (vivi_code_get_new_name (scanner->value));
-
- return STATUS_OK;
-}
-
-static ParseStatus
-parse_assignment_operator (GScanner *scanner)
-{
- if (!check_token (scanner, '='))
- return STATUS_CANCEL;
+ *token =
+ VIVI_CODE_TOKEN (vivi_code_get_new_name (scanner->value.v_identifier));
return STATUS_OK;
}
@@ -602,19 +616,17 @@ static const struct {
{ SYMBOL_PRIMARY_EXPRESSION, "PrimaryExpression", parse_primary_expression },
// misc
{ SYMBOL_IDENTIFIER, "Identifier", parse_identifier },
- { SYMBOL_ASSIGNMENT_OPERATOR, "AssignmentOperator",
- parse_assignment_operator },
{ SYMBOL_NONE, NULL, NULL }
};
-static ParseSymbol
-parse (GScanner *scanner, ParseSymbol symbol)
+static ParseStatus
+parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token)
{
int i;
for (i = 0; symbols[i].id != SYMBOL_NONE; i++) {
if (symbols[i].id == symbol) {
- ParseSymbol ret = symbols[i].parse (scanner);
+ ParseStatus ret = symbols[i].parse (scanner, token);
if (ret != STATUS_CANCEL)
g_print (":%i: %s\n", ret, symbols[i].name);
return ret;
@@ -625,13 +637,13 @@ parse (GScanner *scanner, ParseSymbol symbol)
return STATUS_CANCEL;
}
-static ParseSymbol
+static ParseStatus
parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
guint separator)
{
GPtrArray *array;
ViviCodeToken *token;
- ParseSymbol ret;
+ ParseStatus ret;
ret = parse (scanner, symbol, &token);
if (ret != STATUS_OK)
@@ -651,7 +663,7 @@ parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
} while (ret == STATUS_OK);
g_ptr_array_add (array, NULL);
- *list = g_ptr_array_free (array, FALSE);
+ *list = (ViviCodeToken **)g_ptr_array_free (array, FALSE);
return STATUS_OK;
}
@@ -665,6 +677,7 @@ main (int argc, char *argv[])
char *test_text;
gsize test_text_len;
int ret;
+ ViviCodeToken **list;
if (argc < 2) {
g_print ("Usage!\n");
@@ -695,7 +708,7 @@ main (int argc, char *argv[])
g_scanner_input_text (scanner, test_text, test_text_len);
- ret = parse_list (scanner, SYMBOL_SOURCE_ELEMENT);
+ ret = parse_list (scanner, SYMBOL_SOURCE_ELEMENT, &list, G_TOKEN_NONE);
g_print ("%i: %i, %i\n", ret,
g_scanner_cur_line (scanner), g_scanner_cur_position (scanner));
commit 3e62fcd8d682d5764135acba972b10baa3622b8a
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Fri Mar 28 16:38:35 2008 +0200
Start creating ViviCode elements in complier code
diff --git a/vivified/code/compiler.c b/vivified/code/compiler.c
index 45e1af0..2df22bf 100644
--- a/vivified/code/compiler.c
+++ b/vivified/code/compiler.c
@@ -24,6 +24,26 @@
#include <string.h>
#include <swfdec/swfdec.h>
+#include "vivi_code_assignment.h"
+#include "vivi_code_binary.h"
+#include "vivi_code_block.h"
+#include "vivi_code_break.h"
+#include "vivi_code_constant.h"
+#include "vivi_code_continue.h"
+#include "vivi_code_empty.h"
+#include "vivi_code_function.h"
+#include "vivi_code_function_call.h"
+#include "vivi_code_get.h"
+#include "vivi_code_get_url.h"
+#include "vivi_code_goto.h"
+#include "vivi_code_if.h"
+#include "vivi_code_init_object.h"
+#include "vivi_code_loop.h"
+#include "vivi_code_return.h"
+#include "vivi_code_trace.h"
+#include "vivi_code_unary.h"
+#include "vivi_code_value_statement.h"
+
typedef enum {
STATUS_FAIL = -1,
STATUS_OK = 0,
@@ -60,7 +80,6 @@ typedef enum {
SYMBOL_THROW_STATEMENT,
SYMBOL_TRY_STATEMENT,
// expression
- SYMBOL_EXPRESSION,
SYMBOL_ASSIGNMENT_EXPRESSION,
SYMBOL_CONDITIONAL_EXPRESSION,
SYMBOL_LEFT_HAND_SIDE_EXPRESSION,
@@ -78,10 +97,14 @@ typedef enum {
SYMBOL_ARGUMENTS,
} ParseSymbol;
-typedef ParseStatus (*ParseFunction) (GScanner *scanner);
+typedef ParseStatus (*ParseFunction) (GScanner *scanner, ViviCodeToken **token);
-static ParseStatus parse (GScanner *scanner, ParseSymbol symbol);
-static ParseStatus parse_list (GScanner *scanner, ParseSymbol symbol);
+static ParseStatus
+parse (GScanner *scanner, ParseSymbol symbol, ViviCodeToken **token);
+
+static ParseStatus
+parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
+ guint separator);
// helpers
@@ -95,17 +118,45 @@ check_token (GScanner *scanner, guint token)
return TRUE;
}
+static void
+free_list (ViviCodeToken **list)
+{
+ int i;
+
+ for (i = 0; list[i] != NULL; i++) {
+ g_object_unref (list[i]);
+ }
+ g_free (list);
+}
+
+static ViviCodeBlock *
+create_block (ViviCodeToken **list)
+{
+ ViviCodeBlock *block;
+ int i;
+
+ block = VIVI_CODE_BLOCK (vivi_code_block_new ());
+
+ for (i = 0; list[i] != NULL; i++) {
+ vivi_code_block_add_statement (block, VIVI_CODE_STATEMENT (list[i]));
+ }
+
+ return block;
+}
+
// top
static ParseStatus
-parse_source_element (GScanner *scanner)
+parse_source_element (GScanner *scanner, ViviCodeToken **token)
{
ParseStatus status;
- status = parse (scanner, SYMBOL_FUNCTION_DECLARATION);
+ *token = NULL;
+
+ status = parse (scanner, SYMBOL_FUNCTION_DECLARATION, token);
if (status == STATUS_CANCEL)
- status = parse (scanner, SYMBOL_STATEMENT);
+ status = parse (scanner, SYMBOL_STATEMENT, token);
return status;
}
@@ -113,39 +164,69 @@ parse_source_element (GScanner *scanner)
// function
static ParseStatus
-parse_function_declaration (GScanner *scanner)
+parse_function_declaration (GScanner *scanner, ViviCodeToken **token)
{
+ ViviCodeToken *function, *identifier;
+ ViviCodeToken **arguments, **body;
+
+ *token = NULL;
+
+ identifier = NULL;
+ arguments = NULL;
+ body = NULL;
+
if (!check_token (scanner, TOKEN_FUNCTION))
return STATUS_CANCEL;
- if (parse (scanner, SYMBOL_IDENTIFIER) != STATUS_OK)
+ if (parse (scanner, SYMBOL_IDENTIFIER, &identifier) != STATUS_OK)
return STATUS_FAIL;
if (!check_token (scanner, '('))
- return STATUS_FAIL;
+ goto fail;
- if (parse_list (scanner, SYMBOL_IDENTIFIER) == STATUS_FAIL)
- return STATUS_FAIL;
+ if (parse_list (scanner, SYMBOL_IDENTIFIER, &arguments, ',') == STATUS_FAIL)
+ goto fail;
if (!check_token (scanner, ')'))
- return STATUS_FAIL;
+ goto fail;
if (!check_token (scanner, '{'))
- return STATUS_FAIL;
+ goto fail;
- if (parse_list (scanner, SYMBOL_SOURCE_ELEMENT) == STATUS_FAIL)
- return STATUS_FAIL;
+ if (parse_list (scanner, SYMBOL_SOURCE_ELEMENT, &body, G_TOKEN_NONE)
+ == STATUS_FAIL)
+ goto fail;
if (!check_token (scanner, '}'))
- return STATUS_FAIL;
+ goto fail;
+
+ //function = vivi_code_function_new (arguments, body);
+ *token = VIVI_CODE_TOKEN (
+ vivi_code_assignment_new (NULL, VIVI_CODE_VALUE (identifier),
+ VIVI_CODE_VALUE (function)));
+
+ g_object_unref (identifier);
+ if (arguments != NULL)
+ free_list (arguments);
+ free_list (body);
return STATUS_OK;
+
+fail:
+ if (identifier != NULL)
+ g_object_unref (identifier);
+ if (arguments != NULL)
+ free_list (arguments);
+ if (body != NULL)
+ free_list (body);
+
+ return STATUS_FAIL;
}
// statement
static ParseStatus
-parse_statement (GScanner *scanner)
+parse_statement (GScanner *scanner, ViviCodeToken **token)
{
int i, status;
ParseSymbol options[] = {
@@ -166,8 +247,10 @@ parse_statement (GScanner *scanner)
SYMBOL_NONE
};
+ *token = NULL;
+
for (i = 0; options[i] != SYMBOL_NONE; i++) {
- status = parse (scanner, options[i]);
+ status = parse (scanner, options[i], token);
if (status != STATUS_CANCEL)
return status;
}
@@ -176,225 +259,278 @@ parse_statement (GScanner *scanner)
}
static ParseStatus
-parse_block (GScanner *scanner)
+parse_block (GScanner *scanner, ViviCodeToken **token)
{
+ ViviCodeToken **list;
+
+ *token = NULL;
+
if (!check_token (scanner, '{'))
return STATUS_CANCEL;
+ list = NULL;
+
g_scanner_peek_next_token (scanner);
if (scanner->next_token != '}') {
- if (parse_list (scanner, SYMBOL_STATEMENT) != STATUS_OK)
+ if (parse_list (scanner, SYMBOL_STATEMENT, &list, G_TOKEN_NONE)
+ != STATUS_OK)
return STATUS_FAIL;
}
- if (!check_token (scanner, '}'))
+ if (!check_token (scanner, '}')) {
+ if (list != NULL)
+ free_list (list);
return STATUS_FAIL;
+ }
+
+ *token = VIVI_CODE_TOKEN (create_block (list));
+ free_list (list);
return STATUS_OK;
}
static ParseStatus
-parse_empty_statement (GScanner *scanner)
+parse_empty_statement (GScanner *scanner, ViviCodeToken **token)
{
+ *token = NULL;
+
if (!check_token (scanner, ';'))
return STATUS_CANCEL;
+ *token = VIVI_CODE_TOKEN (vivi_code_empty_new ());
+
return STATUS_OK;
}
static ParseStatus
-parse_expression_statement (GScanner *scanner)
+parse_expression_statement (GScanner *scanner, ViviCodeToken **token)
{
+ ViviCodeToken **list;
+ ParseStatus status;
+
+ *token = NULL;
+
g_scanner_peek_next_token (scanner);
if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
return STATUS_CANCEL;
- return parse (scanner, SYMBOL_EXPRESSION);
+ status = parse_list (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &list, ',');
+
+ if (status == STATUS_OK) {
+ if (list[1] == NULL) {
+ *token = list[0];
+ } else {
+ *token = VIVI_CODE_TOKEN (create_block (list));
+ }
+ }
+
+ return status;
}
// expression
static ParseStatus
-parse_expression (GScanner *scanner)
+parse_assignment_expression (GScanner *scanner, ViviCodeToken **token)
{
- ParseStatus status;
+ *token = NULL;
- status = parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION);
- if (status != STATUS_OK)
- return status;
-
- do {
- if (!check_token (scanner, ','))
- return STATUS_OK;
- } while (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION) == STATUS_OK);
+ // TODO
- return STATUS_FAIL;
+ return parse (scanner, SYMBOL_CONDITIONAL_EXPRESSION, token);
}
static ParseStatus
-parse_assignment_expression (GScanner *scanner)
+parse_conditional_expression (GScanner *scanner, ViviCodeToken **token)
{
ParseStatus status;
+ ViviCodeToken *value;
+ ViviCodeToken *first, *second;
- status = parse (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION);
- if (status == STATUS_OK) {
- status = parse (scanner, SYMBOL_ASSIGNMENT_OPERATOR);
- if (status == STATUS_CANCEL)
- return STATUS_OK;
- if (status == STATUS_FAIL)
- return STATUS_FAIL;
- if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION) != STATUS_OK)
- return STATUS_FAIL;
- return STATUS_OK;
- } else if (status == STATUS_CANCEL) {
- return parse (scanner, SYMBOL_CONDITIONAL_EXPRESSION);
- } else {
- return STATUS_FAIL;
- }
-}
-
-static ParseStatus
-parse_conditional_expression (GScanner *scanner)
-{
- ParseStatus status;
+ *token = NULL;
+ first = NULL;
- status = parse (scanner, SYMBOL_OPERATOR_EXPRESSION);
+ status = parse (scanner, SYMBOL_OPERATOR_EXPRESSION, &value);
if (status != STATUS_OK)
return status;
- if (!check_token (scanner, '?'))
+ if (!check_token (scanner, '?')) {
+ *token = VIVI_CODE_TOKEN (
+ vivi_code_value_statement_new (VIVI_CODE_VALUE (value)));
+ g_object_unref (value);
return STATUS_OK;
+ }
- if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION) != STATUS_OK)
- return STATUS_FAIL;
+ if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &first) != STATUS_OK)
+ goto fail;
if (!check_token (scanner, ':'))
- return STATUS_FAIL;
+ goto fail;
- if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION) != STATUS_OK)
- return STATUS_FAIL;
+ if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION, &second) != STATUS_OK)
+ goto fail;
+
+ //*token = vivi_code_condional_new (VIVI_CODE_VALUE (value),
+ // VIVI_CODE_STATEMENT (first), VIVI_CODE_STATEMENT (second));
+
+ g_object_unref (value);
+ g_object_unref (first);
+ g_object_unref (second);
return STATUS_OK;
+
+fail:
+
+ g_object_unref (value);
+ if (first != NULL)
+ g_object_unref (first);
+
+ return STATUS_FAIL;
}
static ParseStatus
-parse_operator_expression (GScanner *scanner)
+parse_operator_expression (GScanner *scanner, ViviCodeToken **token)
{
ParseStatus status;
+ ViviCodeValue *left;
+ ViviCodeToken *right;
+
+ *token = NULL;
- status = parse (scanner, SYMBOL_UNARY_EXPRESSION);
+ status = parse (scanner, SYMBOL_UNARY_EXPRESSION, token);
if (status != STATUS_OK)
return status;
do {
if (!check_token (scanner, '+'))
return STATUS_OK;
- } while (parse (scanner, SYMBOL_UNARY_EXPRESSION) == STATUS_OK);
+
+ if (parse (scanner, SYMBOL_UNARY_EXPRESSION, &right) != STATUS_OK) {
+ g_object_unref (*token);
+ *token = NULL;
+ return STATUS_FAIL;
+ }
+
+ left = VIVI_CODE_VALUE (token);
+ *token = VIVI_CODE_TOKEN (vivi_code_binary_new_name (left,
+ VIVI_CODE_VALUE (right), "+"));
+ g_object_unref (left);
+ g_object_unref (right);
+ } while (TRUE);
+
+ g_object_unref (*token);
+ *token = NULL;
return STATUS_FAIL;
}
static ParseStatus
-parse_unary_expression (GScanner *scanner)
+parse_unary_expression (GScanner *scanner, ViviCodeToken **token)
{
- ParseStatus status;
-
- status = parse (scanner, SYMBOL_POSTFIX_EXPRESSION);
- if (status != STATUS_OK)
- return status;
+ ViviCodeValue *value;
- do {
- if (!check_token (scanner, '!'))
- return STATUS_OK;
- } while (parse (scanner, SYMBOL_POSTFIX_EXPRESSION) == STATUS_OK);
+ *token = NULL;
- return STATUS_FAIL;
+ if (check_token (scanner, '!')) {
+ parse (scanner, SYMBOL_UNARY_EXPRESSION, token);
+ value = VIVI_CODE_VALUE (*token);
+ *token = VIVI_CODE_TOKEN (vivi_code_unary_new (value, '!'));
+ g_object_unref (value);
+ return STATUS_OK;
+ } else {
+ return parse (scanner, SYMBOL_POSTFIX_EXPRESSION, token);
+ }
}
static ParseStatus
-parse_postfix_expression (GScanner *scanner)
+parse_postfix_expression (GScanner *scanner, ViviCodeToken **token)
{
+ //ViviCodeValue *value;
ParseStatus status;
- status = parse (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION);
+ status = parse (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION, token);
if (status != STATUS_OK)
return status;
- // don't allow new line here
+ // FIXME: Don't allow new line here
- g_scanner_peek_next_token (scanner);
- if (scanner->next_token == TOKEN_PLUSPLUS ||
- scanner->next_token == TOKEN_MINUSMINUS) {
- g_scanner_get_next_token (scanner);
+ /*if (check_token (scanner, TOKEN_PLUSPLUS)) {
+ value = VIVI_CODE_VALUE (*token);
+ *token = VIVI_CODE_TOKEN (vivi_code_postfix_new (value, "++"));
+ g_object_unref (value);
+ } else {*/
return STATUS_OK;
- }
-
- return STATUS_OK;
+ //}
}
static ParseStatus
-parse_left_hand_side_expression (GScanner *scanner)
+parse_left_hand_side_expression (GScanner *scanner, ViviCodeToken **token)
{
ParseStatus status;
- status = parse (scanner, SYMBOL_NEW_EXPRESSION);
+ *token = NULL;
+
+ status = parse (scanner, SYMBOL_NEW_EXPRESSION, token);
if (status == STATUS_CANCEL)
- status = parse (scanner, SYMBOL_CALL_EXPRESSION);
+ status = parse (scanner, SYMBOL_CALL_EXPRESSION, token);
return status;
}
static ParseStatus
-parse_new_expression (GScanner *scanner)
+parse_new_expression (GScanner *scanner, ViviCodeToken **token)
{
- g_scanner_peek_next_token (scanner);
- if (scanner->next_token == TOKEN_NEW) {
- g_scanner_get_next_token (scanner);
- if (parse (scanner, SYMBOL_NEW_EXPRESSION) != STATUS_OK)
+ *token = NULL;
+
+ if (check_token (scanner, TOKEN_NEW)) {
+ if (parse (scanner, SYMBOL_NEW_EXPRESSION, token) != STATUS_OK)
return STATUS_FAIL;
+ if (!VIVI_IS_CODE_FUNCTION_CALL (*token)) {
+ ViviCodeValue *value = VIVI_CODE_VALUE (*token);
+ *token = VIVI_CODE_TOKEN (vivi_code_function_call_new (NULL, value));
+ g_object_unref (value);
+ }
+ vivi_code_function_call_set_construct (VIVI_CODE_FUNCTION_CALL (*token),
+ TRUE);
return STATUS_OK;
} else {
- return parse (scanner, SYMBOL_MEMBER_EXPRESSION);
+ return parse (scanner, SYMBOL_MEMBER_EXPRESSION, token);
}
}
static ParseStatus
-parse_member_expression (GScanner *scanner)
+parse_member_expression (GScanner *scanner, ViviCodeToken **token)
{
ParseStatus status;
+ ViviCodeValue *value;
+ ViviCodeToken *member;
- g_scanner_peek_next_token (scanner);
- if (scanner->next_token == TOKEN_NEW) {
- g_scanner_get_next_token (scanner);
- if (parse (scanner, SYMBOL_MEMBER_EXPRESSION) != STATUS_OK)
- return STATUS_FAIL;
- if (parse (scanner, SYMBOL_ARGUMENTS) != STATUS_OK)
- return STATUS_FAIL;
- return STATUS_OK;
- }
+ // TODO: new MemberExpression Arguments
- status = parse (scanner, SYMBOL_PRIMARY_EXPRESSION);
+ status = parse (scanner, SYMBOL_PRIMARY_EXPRESSION, token);
if (status == STATUS_CANCEL)
- status = parse (scanner, SYMBOL_FUNCTION_EXPRESSION);
+ status = parse (scanner, SYMBOL_FUNCTION_EXPRESSION, token);
if (status != 0)
return status;
do {
- g_scanner_peek_next_token (scanner);
- if (scanner->next_token == '[') {
- g_scanner_get_next_token (scanner);
- if (parse (scanner, SYMBOL_EXPRESSION) != STATUS_OK)
+ if (check_token (scanner, '[')) {
+ if (parse (scanner, SYMBOL_EXPRESSION, &member) != STATUS_OK)
return STATUS_FAIL;
if (!check_token (scanner, ']'))
return STATUS_FAIL;
- } else if (scanner->next_token == '.') {
- g_scanner_get_next_token (scanner);
- if (parse (scanner, SYMBOL_IDENTIFIER) != STATUS_OK)
+ } else if (check_token (scanner, '.')) {
+ if (parse (scanner, SYMBOL_IDENTIFIER, &member) != STATUS_OK)
return STATUS_FAIL;
} else {
return STATUS_OK;
}
+
+ value = VIVI_CODE_VALUE (token)
+ *token = VIVI_CODE_TOKEN (
+ vivi_code_get_new (value, VIVI_CODE_VALUE (member)));
+ g_object_unref (value);
+ g_object_unref (member);
} while (TRUE);
g_assert_not_reached ();
@@ -402,19 +538,23 @@ parse_member_expression (GScanner *scanner)
}
static ParseStatus
-parse_primary_expression (GScanner *scanner)
+parse_primary_expression (GScanner *scanner, ViviCodeToken **token)
{
- return parse (scanner, SYMBOL_IDENTIFIER);
+ return parse (scanner, SYMBOL_IDENTIFIER, token);
}
// misc.
static ParseStatus
-parse_identifier (GScanner *scanner)
+parse_identifier (GScanner *scanner, ViviCodeToken **token)
{
+ *token = NULL;
+
if (!check_token (scanner, G_TOKEN_IDENTIFIER))
return STATUS_CANCEL;
+ *token = VIVI_CODE_TOKEN (vivi_code_get_new_name (scanner->value));
+
return STATUS_OK;
}
@@ -467,40 +607,53 @@ static const struct {
{ SYMBOL_NONE, NULL, NULL }
};
-static int
+static ParseSymbol
parse (GScanner *scanner, ParseSymbol symbol)
{
int i;
for (i = 0; symbols[i].id != SYMBOL_NONE; i++) {
if (symbols[i].id == symbol) {
- int ret = symbols[i].parse (scanner);
- if (ret != 1)
+ ParseSymbol ret = symbols[i].parse (scanner);
+ if (ret != STATUS_CANCEL)
g_print (":%i: %s\n", ret, symbols[i].name);
return ret;
}
}
//g_assert_not_reached ();
- return 1;
+ return STATUS_CANCEL;
}
-static gboolean
-parse_list (GScanner *scanner, ParseSymbol symbol)
+static ParseSymbol
+parse_list (GScanner *scanner, ParseSymbol symbol, ViviCodeToken ***list,
+ guint separator)
{
- int ret;
+ GPtrArray *array;
+ ViviCodeToken *token;
+ ParseSymbol ret;
- ret = parse (scanner, symbol);
- if (ret != 0)
+ ret = parse (scanner, symbol, &token);
+ if (ret != STATUS_OK)
return ret;
+ array = g_ptr_array_new ();
+
do {
- ret = parse (scanner, symbol);
- if (ret == -1)
- return -1;
- } while (ret == 0);
+ g_ptr_array_add (array, token);
- return 0;
+ if (separator != G_TOKEN_NONE && !check_token (scanner, separator))
+ break;
+
+ ret = parse (scanner, symbol, &token);
+ if (ret == STATUS_FAIL)
+ return STATUS_FAIL;
+ } while (ret == STATUS_OK);
+ g_ptr_array_add (array, NULL);
+
+ *list = g_ptr_array_free (array, FALSE);
+
+ return STATUS_OK;
}
// main
commit 20a1e8a41aa9bac648433bdbeeff093c62d02811
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Fri Mar 28 14:23:10 2008 +0200
Add a ViviCodeEmpty class for empty statements
diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index 9185680..a731138 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -13,6 +13,7 @@ libvivified_compiler_la_SOURCES = \
vivi_code_comment.c \
vivi_code_constant.c \
vivi_code_continue.c \
+ vivi_code_empty.c \
vivi_code_function.c \
vivi_code_function_call.c \
vivi_code_get.c \
@@ -45,6 +46,7 @@ noinst_HEADERS = \
vivi_code_comment.h \
vivi_code_constant.h \
vivi_code_continue.h \
+ vivi_code_empty.h \
vivi_code_function.h \
vivi_code_function_call.h \
vivi_code_get.h \
diff --git a/vivified/code/vivi_code_empty.c b/vivified/code/vivi_code_empty.c
new file mode 100644
index 0000000..cf56456
--- /dev/null
+++ b/vivified/code/vivi_code_empty.c
@@ -0,0 +1,75 @@
+/* Vivified
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ * 2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "vivi_code_empty.h"
+#include "vivi_code_printer.h"
+
+G_DEFINE_TYPE (ViviCodeEmpty, vivi_code_empty, VIVI_TYPE_CODE_STATEMENT)
+
+static ViviCodeStatement *
+vivi_code_empty_optimize (ViviCodeStatement *statement)
+{
+ // FIXME
+ return statement;
+}
+
+static gboolean
+vivi_code_empty_needs_braces (ViviCodeStatement *stmt)
+{
+ return FALSE;
+}
+
+static void
+vivi_code_empty_print (ViviCodeToken *token, ViviCodePrinter *printer)
+{
+ vivi_code_printer_print (printer, ";");
+ vivi_code_printer_new_line (printer, FALSE);
+}
+
+static void
+vivi_code_empty_class_init (ViviCodeEmptyClass *klass)
+{
+ ViviCodeTokenClass *token_class = VIVI_CODE_TOKEN_CLASS (klass);
+ ViviCodeStatementClass *statement_class = VIVI_CODE_STATEMENT_CLASS (klass);
+
+ token_class->print = vivi_code_empty_print;
+
+ statement_class->optimize = vivi_code_empty_optimize;
+ statement_class->needs_braces = vivi_code_empty_needs_braces;
+}
+
+static void
+vivi_code_empty_init (ViviCodeEmpty *token)
+{
+}
+
+ViviCodeStatement *
+vivi_code_empty_new (void)
+{
+ ViviCodeEmpty *stmt;
+
+ stmt = g_object_new (VIVI_TYPE_CODE_EMPTY, NULL);
+
+ return VIVI_CODE_STATEMENT (stmt);
+}
diff --git a/vivified/code/vivi_code_empty.h b/vivified/code/vivi_code_empty.h
new file mode 100644
index 0000000..48dc126
--- /dev/null
+++ b/vivified/code/vivi_code_empty.h
@@ -0,0 +1,56 @@
+/* Vivified
+ * Copyright (C) 2008 Benjamin Otte <otte at gnome.org>
+ * 2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef _VIVI_CODE_EMPTY_H_
+#define _VIVI_CODE_EMPTY_H_
+
+#include <vivified/code/vivi_code_statement.h>
+#include <vivified/code/vivi_code_value.h>
+
+G_BEGIN_DECLS
+
+
+typedef struct _ViviCodeEmpty ViviCodeEmpty;
+typedef struct _ViviCodeEmptyClass ViviCodeEmptyClass;
+
+#define VIVI_TYPE_CODE_EMPTY (vivi_code_empty_get_type())
+#define VIVI_IS_CODE_EMPTY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), VIVI_TYPE_CODE_EMPTY))
+#define VIVI_IS_CODE_EMPTY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), VIVI_TYPE_CODE_EMPTY))
+#define VIVI_CODE_EMPTY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), VIVI_TYPE_CODE_EMPTY, ViviCodeEmpty))
+#define VIVI_CODE_EMPTY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), VIVI_TYPE_CODE_EMPTY, ViviCodeEmptyClass))
+#define VIVI_CODE_EMPTY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), VIVI_TYPE_CODE_EMPTY, ViviCodeEmptyClass))
+
+struct _ViviCodeEmpty
+{
+ ViviCodeStatement statement;
+};
+
+struct _ViviCodeEmptyClass
+{
+ ViviCodeStatementClass statement_class;
+};
+
+GType vivi_code_empty_get_type (void);
+
+ViviCodeStatement * vivi_code_empty_new (void);
+
+
+G_END_DECLS
+#endif
commit 552f3d6d72f093c3df56aa619e0745472b6097a2
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Fri Mar 28 11:13:24 2008 +0200
Make the compiler build and add a copyright header
diff --git a/vivified/code/Makefile.am b/vivified/code/Makefile.am
index 786c688..9185680 100644
--- a/vivified/code/Makefile.am
+++ b/vivified/code/Makefile.am
@@ -71,7 +71,7 @@ noinst_HEADERS = \
vivified-compiler.h
-noinst_PROGRAMS = vivi-decompile
+noinst_PROGRAMS = vivi-decompile vivi-compile
vivi_decompile_SOURCES = \
decompiler.c
@@ -79,3 +79,10 @@ vivi_decompile_SOURCES = \
vivi_decompile_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS)
vivi_decompile_LDFLAGS = $(SWFDEC_LIBS)
vivi_decompile_LDADD = libvivified-compiler.la
+
+vivi_compile_SOURCES = \
+ compiler.c
+
+vivi_compile_CFLAGS = $(GLOBAL_CFLAGS) $(SWFDEC_CFLAGS)
+vivi_compile_LDFLAGS = $(SWFDEC_LIBS)
+vivi_compile_LDADD = libvivified-compiler.la
diff --git a/vivified/code/compiler.c b/vivified/code/compiler.c
index 7e386ef..45e1af0 100644
--- a/vivified/code/compiler.c
+++ b/vivified/code/compiler.c
@@ -1,5 +1,28 @@
-#include <glib.h>
+/* Vivified
+ * Copyright (C) 2008 Pekka Lampila <pekka.lampila at iki.fi>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#include <string.h>
+#include <swfdec/swfdec.h>
typedef enum {
STATUS_FAIL = -1,
@@ -530,7 +553,7 @@ main (int argc, char *argv[])
g_scanner_get_next_token (scanner);
g_print (":: %i, %i :: ", g_scanner_cur_line (scanner),
g_scanner_cur_position (scanner));
- switch (scanner->token) {
+ switch ((int)scanner->token) {
case G_TOKEN_SYMBOL:
g_print ("SYMBOL\n");
break;
commit 57039838368dd04377ca4dd14dbee5229d26b7b2
Author: Pekka Lampila <pekka.lampila at iki.fi>
Date: Fri Mar 28 11:06:48 2008 +0200
Start work on a ActionScript compiler
diff --git a/vivified/code/compiler.c b/vivified/code/compiler.c
new file mode 100644
index 0000000..7e386ef
--- /dev/null
+++ b/vivified/code/compiler.c
@@ -0,0 +1,563 @@
+#include <glib.h>
+#include <string.h>
+
+typedef enum {
+ STATUS_FAIL = -1,
+ STATUS_OK = 0,
+ STATUS_CANCEL = 1
+} ParseStatus;
+
+enum {
+ TOKEN_FUNCTION = G_TOKEN_LAST + 1,
+ TOKEN_PLUSPLUS = G_TOKEN_LAST + 2,
+ TOKEN_MINUSMINUS = G_TOKEN_LAST + 3,
+ TOKEN_NEW = G_TOKEN_LAST + 4
+};
+
+typedef enum {
+ SYMBOL_NONE,
+ // top
+ SYMBOL_SOURCE_ELEMENT,
+ // function
+ SYMBOL_FUNCTION_DECLARATION,
+ // statement
+ SYMBOL_STATEMENT,
+ SYMBOL_BLOCK,
+ SYMBOL_VARIABLE_STATEMENT,
+ SYMBOL_EMPTY_STATEMENT,
+ SYMBOL_EXPRESSION_STATEMENT,
+ SYMBOL_IF_STATEMENT,
+ SYMBOL_ITERATION_STATEMENT,
+ SYMBOL_CONTINUE_STATEMENT,
+ SYMBOL_BREAK_STATEMENT,
+ SYMBOL_RETURN_STATEMENT,
+ SYMBOL_WITH_STATEMENT,
+ SYMBOL_LABELLED_STATEMENT,
+ SYMBOL_SWITCH_STATEMENT,
+ SYMBOL_THROW_STATEMENT,
+ SYMBOL_TRY_STATEMENT,
+ // expression
+ SYMBOL_EXPRESSION,
+ SYMBOL_ASSIGNMENT_EXPRESSION,
+ SYMBOL_CONDITIONAL_EXPRESSION,
+ SYMBOL_LEFT_HAND_SIDE_EXPRESSION,
+ SYMBOL_OPERATOR_EXPRESSION,
+ SYMBOL_UNARY_EXPRESSION,
+ SYMBOL_POSTFIX_EXPRESSION,
+ SYMBOL_NEW_EXPRESSION,
+ SYMBOL_CALL_EXPRESSION,
+ SYMBOL_MEMBER_EXPRESSION,
+ SYMBOL_FUNCTION_EXPRESSION,
+ SYMBOL_PRIMARY_EXPRESSION,
+ // misc
+ SYMBOL_IDENTIFIER,
+ SYMBOL_ASSIGNMENT_OPERATOR,
+ SYMBOL_ARGUMENTS,
+} ParseSymbol;
+
+typedef ParseStatus (*ParseFunction) (GScanner *scanner);
+
+static ParseStatus parse (GScanner *scanner, ParseSymbol symbol);
+static ParseStatus parse_list (GScanner *scanner, ParseSymbol symbol);
+
+// helpers
+
+static gboolean
+check_token (GScanner *scanner, guint token)
+{
+ g_scanner_peek_next_token (scanner);
+ if (scanner->next_token != token)
+ return FALSE;
+ g_scanner_get_next_token (scanner);
+ return TRUE;
+}
+
+// top
+
+static ParseStatus
+parse_source_element (GScanner *scanner)
+{
+ ParseStatus status;
+
+ status = parse (scanner, SYMBOL_FUNCTION_DECLARATION);
+
+ if (status == STATUS_CANCEL)
+ status = parse (scanner, SYMBOL_STATEMENT);
+
+ return status;
+}
+
+// function
+
+static ParseStatus
+parse_function_declaration (GScanner *scanner)
+{
+ if (!check_token (scanner, TOKEN_FUNCTION))
+ return STATUS_CANCEL;
+
+ if (parse (scanner, SYMBOL_IDENTIFIER) != STATUS_OK)
+ return STATUS_FAIL;
+
+ if (!check_token (scanner, '('))
+ return STATUS_FAIL;
+
+ if (parse_list (scanner, SYMBOL_IDENTIFIER) == STATUS_FAIL)
+ return STATUS_FAIL;
+
+ if (!check_token (scanner, ')'))
+ return STATUS_FAIL;
+
+ if (!check_token (scanner, '{'))
+ return STATUS_FAIL;
+
+ if (parse_list (scanner, SYMBOL_SOURCE_ELEMENT) == STATUS_FAIL)
+ return STATUS_FAIL;
+
+ if (!check_token (scanner, '}'))
+ return STATUS_FAIL;
+
+ return STATUS_OK;
+}
+
+// statement
+
+static ParseStatus
+parse_statement (GScanner *scanner)
+{
+ int i, status;
+ ParseSymbol options[] = {
+ SYMBOL_BLOCK,
+ SYMBOL_VARIABLE_STATEMENT,
+ SYMBOL_EMPTY_STATEMENT,
+ SYMBOL_EXPRESSION_STATEMENT,
+ SYMBOL_IF_STATEMENT,
+ SYMBOL_ITERATION_STATEMENT,
+ SYMBOL_CONTINUE_STATEMENT,
+ SYMBOL_BREAK_STATEMENT,
+ SYMBOL_RETURN_STATEMENT,
+ SYMBOL_WITH_STATEMENT,
+ SYMBOL_LABELLED_STATEMENT,
+ SYMBOL_SWITCH_STATEMENT,
+ SYMBOL_THROW_STATEMENT,
+ SYMBOL_TRY_STATEMENT,
+ SYMBOL_NONE
+ };
+
+ for (i = 0; options[i] != SYMBOL_NONE; i++) {
+ status = parse (scanner, options[i]);
+ if (status != STATUS_CANCEL)
+ return status;
+ }
+
+ return STATUS_CANCEL;
+}
+
+static ParseStatus
+parse_block (GScanner *scanner)
+{
+ if (!check_token (scanner, '{'))
+ return STATUS_CANCEL;
+
+ g_scanner_peek_next_token (scanner);
+ if (scanner->next_token != '}') {
+ if (parse_list (scanner, SYMBOL_STATEMENT) != STATUS_OK)
+ return STATUS_FAIL;
+ }
+
+ if (!check_token (scanner, '}'))
+ return STATUS_FAIL;
+
+ return STATUS_OK;
+}
+
+static ParseStatus
+parse_empty_statement (GScanner *scanner)
+{
+ if (!check_token (scanner, ';'))
+ return STATUS_CANCEL;
+
+ return STATUS_OK;
+}
+
+static ParseStatus
+parse_expression_statement (GScanner *scanner)
+{
+ g_scanner_peek_next_token (scanner);
+ if (scanner->next_token == '{' || scanner->next_token == TOKEN_FUNCTION)
+ return STATUS_CANCEL;
+
+ return parse (scanner, SYMBOL_EXPRESSION);
+}
+
+// expression
+
+static ParseStatus
+parse_expression (GScanner *scanner)
+{
+ ParseStatus status;
+
+ status = parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION);
+ if (status != STATUS_OK)
+ return status;
+
+ do {
+ if (!check_token (scanner, ','))
+ return STATUS_OK;
+ } while (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION) == STATUS_OK);
+
+ return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_assignment_expression (GScanner *scanner)
+{
+ ParseStatus status;
+
+ status = parse (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION);
+ if (status == STATUS_OK) {
+ status = parse (scanner, SYMBOL_ASSIGNMENT_OPERATOR);
+ if (status == STATUS_CANCEL)
+ return STATUS_OK;
+ if (status == STATUS_FAIL)
+ return STATUS_FAIL;
+ if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION) != STATUS_OK)
+ return STATUS_FAIL;
+ return STATUS_OK;
+ } else if (status == STATUS_CANCEL) {
+ return parse (scanner, SYMBOL_CONDITIONAL_EXPRESSION);
+ } else {
+ return STATUS_FAIL;
+ }
+}
+
+static ParseStatus
+parse_conditional_expression (GScanner *scanner)
+{
+ ParseStatus status;
+
+ status = parse (scanner, SYMBOL_OPERATOR_EXPRESSION);
+ if (status != STATUS_OK)
+ return status;
+
+ if (!check_token (scanner, '?'))
+ return STATUS_OK;
+
+ if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION) != STATUS_OK)
+ return STATUS_FAIL;
+
+ if (!check_token (scanner, ':'))
+ return STATUS_FAIL;
+
+ if (parse (scanner, SYMBOL_ASSIGNMENT_EXPRESSION) != STATUS_OK)
+ return STATUS_FAIL;
+
+ return STATUS_OK;
+}
+
+static ParseStatus
+parse_operator_expression (GScanner *scanner)
+{
+ ParseStatus status;
+
+ status = parse (scanner, SYMBOL_UNARY_EXPRESSION);
+ if (status != STATUS_OK)
+ return status;
+
+ do {
+ if (!check_token (scanner, '+'))
+ return STATUS_OK;
+ } while (parse (scanner, SYMBOL_UNARY_EXPRESSION) == STATUS_OK);
+
+ return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_unary_expression (GScanner *scanner)
+{
+ ParseStatus status;
+
+ status = parse (scanner, SYMBOL_POSTFIX_EXPRESSION);
+ if (status != STATUS_OK)
+ return status;
+
+ do {
+ if (!check_token (scanner, '!'))
+ return STATUS_OK;
+ } while (parse (scanner, SYMBOL_POSTFIX_EXPRESSION) == STATUS_OK);
+
+ return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_postfix_expression (GScanner *scanner)
+{
+ ParseStatus status;
+
+ status = parse (scanner, SYMBOL_LEFT_HAND_SIDE_EXPRESSION);
+ if (status != STATUS_OK)
+ return status;
+
+ // don't allow new line here
+
+ g_scanner_peek_next_token (scanner);
+ if (scanner->next_token == TOKEN_PLUSPLUS ||
+ scanner->next_token == TOKEN_MINUSMINUS) {
+ g_scanner_get_next_token (scanner);
+ return STATUS_OK;
+ }
+
+ return STATUS_OK;
+}
+
+static ParseStatus
+parse_left_hand_side_expression (GScanner *scanner)
+{
+ ParseStatus status;
+
+ status = parse (scanner, SYMBOL_NEW_EXPRESSION);
+ if (status == STATUS_CANCEL)
+ status = parse (scanner, SYMBOL_CALL_EXPRESSION);
+
+ return status;
+}
+
+static ParseStatus
+parse_new_expression (GScanner *scanner)
+{
+ g_scanner_peek_next_token (scanner);
+ if (scanner->next_token == TOKEN_NEW) {
+ g_scanner_get_next_token (scanner);
+ if (parse (scanner, SYMBOL_NEW_EXPRESSION) != STATUS_OK)
+ return STATUS_FAIL;
+ return STATUS_OK;
+ } else {
+ return parse (scanner, SYMBOL_MEMBER_EXPRESSION);
+ }
+}
+
+static ParseStatus
+parse_member_expression (GScanner *scanner)
+{
+ ParseStatus status;
+
+ g_scanner_peek_next_token (scanner);
+ if (scanner->next_token == TOKEN_NEW) {
+ g_scanner_get_next_token (scanner);
+ if (parse (scanner, SYMBOL_MEMBER_EXPRESSION) != STATUS_OK)
+ return STATUS_FAIL;
+ if (parse (scanner, SYMBOL_ARGUMENTS) != STATUS_OK)
+ return STATUS_FAIL;
+ return STATUS_OK;
+ }
+
+ status = parse (scanner, SYMBOL_PRIMARY_EXPRESSION);
+ if (status == STATUS_CANCEL)
+ status = parse (scanner, SYMBOL_FUNCTION_EXPRESSION);
+
+ if (status != 0)
+ return status;
+
+ do {
+ g_scanner_peek_next_token (scanner);
+ if (scanner->next_token == '[') {
+ g_scanner_get_next_token (scanner);
+ if (parse (scanner, SYMBOL_EXPRESSION) != STATUS_OK)
+ return STATUS_FAIL;
+ if (!check_token (scanner, ']'))
+ return STATUS_FAIL;
+ } else if (scanner->next_token == '.') {
+ g_scanner_get_next_token (scanner);
+ if (parse (scanner, SYMBOL_IDENTIFIER) != STATUS_OK)
+ return STATUS_FAIL;
+ } else {
+ return STATUS_OK;
+ }
+ } while (TRUE);
+
+ g_assert_not_reached ();
+ return STATUS_FAIL;
+}
+
+static ParseStatus
+parse_primary_expression (GScanner *scanner)
+{
+ return parse (scanner, SYMBOL_IDENTIFIER);
+}
+
+// misc.
+
+static ParseStatus
+parse_identifier (GScanner *scanner)
+{
+ if (!check_token (scanner, G_TOKEN_IDENTIFIER))
+ return STATUS_CANCEL;
+
+ return STATUS_OK;
+}
+
+static ParseStatus
+parse_assignment_operator (GScanner *scanner)
+{
+ if (!check_token (scanner, '='))
+ return STATUS_CANCEL;
+
+ return STATUS_OK;
+}
+
+// parsing
+
+static const struct {
+ ParseSymbol id;
+ const char * name;
+ ParseFunction parse;
+} symbols[] = {
+ // top
+ { SYMBOL_SOURCE_ELEMENT, "SourceElement", parse_source_element },
+ // function
+ { SYMBOL_FUNCTION_DECLARATION, "FunctionDeclaration",
+ parse_function_declaration },
+ // statement
+ { SYMBOL_STATEMENT, "Statement", parse_statement },
+ { SYMBOL_BLOCK, "Block", parse_block },
+ { SYMBOL_EMPTY_STATEMENT, "EmptyStatement", parse_empty_statement },
+ { SYMBOL_EXPRESSION_STATEMENT, "ExpressionStatement",
+ parse_expression_statement },
+ // expression
+ { SYMBOL_EXPRESSION, "Expression", parse_expression },
+ { SYMBOL_ASSIGNMENT_EXPRESSION, "AssigmentExpression",
+ parse_assignment_expression },
+ { SYMBOL_CONDITIONAL_EXPRESSION, "ConditionalExpression",
+ parse_conditional_expression },
+ { SYMBOL_OPERATOR_EXPRESSION, "OperatorExpression",
+ parse_operator_expression },
+ { SYMBOL_UNARY_EXPRESSION, "UnaryExpression", parse_unary_expression },
+ { SYMBOL_POSTFIX_EXPRESSION, "PostfixExpression", parse_postfix_expression },
+ { SYMBOL_LEFT_HAND_SIDE_EXPRESSION, "LeftHandSideExpression",
+ parse_left_hand_side_expression },
+ { SYMBOL_NEW_EXPRESSION, "NewExpression", parse_new_expression },
+ { SYMBOL_MEMBER_EXPRESSION, "MemberExpression", parse_member_expression },
+ { SYMBOL_PRIMARY_EXPRESSION, "PrimaryExpression", parse_primary_expression },
+ // misc
+ { SYMBOL_IDENTIFIER, "Identifier", parse_identifier },
+ { SYMBOL_ASSIGNMENT_OPERATOR, "AssignmentOperator",
+ parse_assignment_operator },
+ { SYMBOL_NONE, NULL, NULL }
+};
+
+static int
+parse (GScanner *scanner, ParseSymbol symbol)
+{
+ int i;
+
+ for (i = 0; symbols[i].id != SYMBOL_NONE; i++) {
+ if (symbols[i].id == symbol) {
+ int ret = symbols[i].parse (scanner);
+ if (ret != 1)
+ g_print (":%i: %s\n", ret, symbols[i].name);
+ return ret;
+ }
+ }
+
+ //g_assert_not_reached ();
+ return 1;
+}
+
+static gboolean
+parse_list (GScanner *scanner, ParseSymbol symbol)
+{
+ int ret;
+
+ ret = parse (scanner, symbol);
+ if (ret != 0)
+ return ret;
+
+ do {
+ ret = parse (scanner, symbol);
+ if (ret == -1)
+ return -1;
+ } while (ret == 0);
+
+ return 0;
+}
+
+// main
+
+int
+main (int argc, char *argv[])
+{
+ GScanner *scanner;
+ char *test_text;
+ gsize test_text_len;
+ int ret;
+
+ if (argc < 2) {
+ g_print ("Usage!\n");
+ return 1;
+ }
+
+ if (!g_file_get_contents (argv[1], &test_text, &test_text_len, NULL)) {
+ g_printerr ("Couldn't open file %s", argv[1]);
+ return -1;
+ }
+
+ scanner = g_scanner_new (NULL);
+
+ scanner->config->numbers_2_int = TRUE;
+ scanner->config->int_2_float = TRUE;
+ scanner->config->symbol_2_token = TRUE;
+
+ g_scanner_set_scope (scanner, 0);
+ g_scanner_scope_add_symbol (scanner, 0, "function",
+ GINT_TO_POINTER(TOKEN_FUNCTION));
+ g_scanner_scope_add_symbol (scanner, 0, "++",
+ GINT_TO_POINTER(TOKEN_PLUSPLUS));
+ g_scanner_scope_add_symbol (scanner, 0, "--",
+ GINT_TO_POINTER(TOKEN_MINUSMINUS));
+ g_scanner_scope_add_symbol (scanner, 0, "new", GINT_TO_POINTER(TOKEN_NEW));
+
+ scanner->input_name = argv[1];
+ g_scanner_input_text (scanner, test_text, test_text_len);
+
+
+ ret = parse_list (scanner, SYMBOL_SOURCE_ELEMENT);
+ g_print ("%i: %i, %i\n", ret,
+ g_scanner_cur_line (scanner), g_scanner_cur_position (scanner));
+
+ g_scanner_peek_next_token (scanner);
+ while (scanner->next_token != G_TOKEN_EOF &&
+ scanner->next_token != G_TOKEN_ERROR)
+ {
+ g_scanner_get_next_token (scanner);
+ g_print (":: %i, %i :: ", g_scanner_cur_line (scanner),
+ g_scanner_cur_position (scanner));
+ switch (scanner->token) {
+ case G_TOKEN_SYMBOL:
+ g_print ("SYMBOL\n");
+ break;
+ case G_TOKEN_FLOAT:
+ g_print ("Primitive: %f\n", scanner->value.v_float);
+ break;
+ case G_TOKEN_STRING:
+ g_print ("Primitive: \"%s\"\n", scanner->value.v_string);
+ break;
+ case G_TOKEN_NONE:
+ g_print ("NONE\n");
+ break;
+ case G_TOKEN_IDENTIFIER:
+ g_print ("Identifier: %s\n", scanner->value.v_identifier);
+ break;
+ default:
+ if (scanner->token > 0 && scanner->token < 256) {
+ g_print ("%c\n", scanner->token);
+ } else {
+ g_print ("TOKEN %i\n", scanner->token);
+ }
+ break;
+ }
+ g_scanner_peek_next_token (scanner);
+ }
+
+ g_scanner_destroy (scanner);
+
+ return 0;
+}
More information about the Swfdec-commits
mailing list