From 39dd0a36bae056660c36deefdf6faccb898d98a4 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Mon, 10 Feb 2014 12:42:12 +0100 Subject: [PATCH] JSON.parse() --- jslex.c | 37 ++++++++++++++++++++++ jslex.h | 1 + json.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 132 insertions(+), 1 deletion(-) diff --git a/jslex.c b/jslex.c index 9103eff..6d6a201 100644 --- a/jslex.c +++ b/jslex.c @@ -663,3 +663,40 @@ int jsY_lex(js_State *J) { return J->lasttoken = jsY_lexx(J); } + +int jsY_lexjson(js_State *J) +{ + while (1) { + J->lexline = J->line; /* save location of beginning of token */ + + while (iswhite(PEEK) || PEEK == '\n') + NEXT(); + + if (PEEK >= '0' && PEEK <= '9') { + return lexnumber(J); + } + + switch (PEEK) { + case ',': NEXT(); return ','; + case ':': NEXT(); return ':'; + case '[': NEXT(); return '['; + case ']': NEXT(); return ']'; + case '{': NEXT(); return '{'; + case '}': NEXT(); return '}'; + + case '\'': + case '"': + return lexstring(J); + + case '.': + return lexnumber(J); + + case 0: + return 0; /* EOF */ + } + + if (PEEK >= 0x20 && PEEK <= 0x7E) + jsY_error(J, "unexpected character: '%c'", PEEK); + jsY_error(J, "unexpected character: \\u%04X", PEEK); + } +} diff --git a/jslex.h b/jslex.h index c8bbd56..6aaf5fe 100644 --- a/jslex.h +++ b/jslex.h @@ -71,5 +71,6 @@ int jsY_findword(const char *s, const char **list, int num); void jsY_initlex(js_State *J, const char *filename, const char *source); int jsY_lex(js_State *J); +int jsY_lexjson(js_State *J); #endif diff --git a/json.c b/json.c index 71985eb..3e902a4 100644 --- a/json.c +++ b/json.c @@ -1,10 +1,103 @@ #include "jsi.h" +#include "jslex.h" #include "jsvalue.h" #include "jsbuiltin.h" +static inline void jsonnext(js_State *J) +{ + J->lookahead = jsY_lexjson(J); +} + +static inline int jsonaccept(js_State *J, int t) +{ + if (J->lookahead == t) { + jsonnext(J); + return 1; + } + return 0; +} + +static inline void jsonexpect(js_State *J, int t) +{ + if (!jsonaccept(J, t)) + js_syntaxerror(J, "JSON: unexpected token: %s (expected %s)", + jsY_tokenstring(J->lookahead), jsY_tokenstring(t)); +} + +static void jsonvalue(js_State *J) +{ + int i; + const char *name; + + switch (J->lookahead) { + case TK_STRING: + js_pushliteral(J, J->text); + jsonnext(J); + break; + + case TK_NUMBER: + js_pushnumber(J, J->number); + jsonnext(J); + break; + + case '{': + js_newobject(J); + jsonnext(J); + if (J->lookahead == '}') + return; + do { + if (J->lookahead != TK_STRING) + js_syntaxerror(J, "JSON: unexpected token: %s (expected string)", jsY_tokenstring(J->lookahead)); + name = J->text; + jsonnext(J); + jsonexpect(J, ':'); + jsonvalue(J); + js_setproperty(J, -2, name); + } while (jsonaccept(J, ',')); + jsonexpect(J, '}'); + break; + + case '[': + js_newarray(J); + jsonnext(J); + i = 0; + if (J->lookahead == ']') + return; + do { + jsonvalue(J); + js_setindex(J, -2, i++); + } while (jsonaccept(J, ',')); + jsonexpect(J, ']'); + break; + + case TK_TRUE: + js_pushboolean(J, 1); + jsonnext(J); + break; + + case TK_FALSE: + js_pushboolean(J, 0); + jsonnext(J); + break; + + case TK_NULL: + js_pushnull(J); + jsonnext(J); + break; + + default: + js_syntaxerror(J, "JSON: unexpected token: %s", jsY_tokenstring(J->lookahead)); + } +} + static int JSON_parse(js_State *J, int argc) { - return 0; + const char *source = js_tostring(J, 1); + jsY_initlex(J, "JSON", source); + jsonnext(J); + jsonvalue(J); + // TODO: reviver Walk() + return 1; } static int JSON_stringify(js_State *J, int argc)