ref: 39dd0a36bae056660c36deefdf6faccb898d98a4
parent: b8aa34d91910785c37b35e950c1c4d626ba59a1a
author: Tor Andersson <tor@ccxvii.net>
date: Mon Feb 10 07:42:12 EST 2014
JSON.parse()
--- a/jslex.c
+++ b/jslex.c
@@ -663,3 +663,40 @@
{
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);
+ }
+}
--- a/jslex.h
+++ b/jslex.h
@@ -71,5 +71,6 @@
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
--- a/json.c
+++ b/json.c
@@ -1,10 +1,103 @@
#include "jsi.h"
+#include "jslex.h"
#include "jsvalue.h"
#include "jsbuiltin.h"
-static int JSON_parse(js_State *J, int argc)
+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)
+{
+ 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)