diff --git a/readme.md b/readme.md index 04d33557..e0157d43 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,7 @@ # 从零开始的 JSON 库教程 * Milo Yip -* 2016/9/15 +* 2017/9/15 也许有很多同学上过 C/C++ 的课后,可以完成一些简单的编程练习,又能在一些网站刷题,但对于如何开发有实际用途的程序可能感到束手无策。本教程希望能以一个简单的项目开发形式,让同学能逐步理解如何从无到有去开发软件。 diff --git a/tutorial01/leptjson.c b/tutorial01/leptjson.c index 5299fe1d..9f38fffb 100644 --- a/tutorial01/leptjson.c +++ b/tutorial01/leptjson.c @@ -23,10 +23,29 @@ static int lept_parse_null(lept_context* c, lept_value* v) { v->type = LEPT_NULL; return LEPT_PARSE_OK; } +static int lept_parse_false(lept_context* c, lept_value* v) { + EXPECT(c, 'f'); + if (c->json[0] != 'a' || c->json[1] != 'l' + || c->json[2] != 's' || c->json[3] != 'e') + return LEPT_PARSE_INVALID_VALUE; + c->json += 4; + v->type = LEPT_FALSE; + return LEPT_PARSE_OK; +} +static int lept_parse_true(lept_context* c, lept_value* v) { + EXPECT(c, 't'); + if (c->json[0] != 'r' || c->json[1] != 'u' || c->json[2] != 'e') + return LEPT_PARSE_INVALID_VALUE; + c->json += 3; + v->type = LEPT_TRUE; + return LEPT_PARSE_OK; +} static int lept_parse_value(lept_context* c, lept_value* v) { switch (*c->json) { case 'n': return lept_parse_null(c, v); + case 't': return lept_parse_true(c, v); + case 'f': return lept_parse_false(c, v); case '\0': return LEPT_PARSE_EXPECT_VALUE; default: return LEPT_PARSE_INVALID_VALUE; } @@ -34,11 +53,23 @@ static int lept_parse_value(lept_context* c, lept_value* v) { int lept_parse(lept_value* v, const char* json) { lept_context c; + int res; assert(v != NULL); c.json = json; v->type = LEPT_NULL; lept_parse_whitespace(&c); - return lept_parse_value(&c, v); + res = lept_parse_value(&c, v); + if (res == LEPT_PARSE_OK) + { + lept_parse_whitespace(&c); + if (*c.json != '\0') { + /* unnecessary mutiple returns */ + /* return LEPT_PARSE_ROOT_NOT_SINGULAR; */ + res = LEPT_PARSE_ROOT_NOT_SINGULAR; + } + } + return res; + } lept_type lept_get_type(const lept_value* v) { diff --git a/tutorial01/leptjson.h b/tutorial01/leptjson.h index 9b65d22a..f15ae96d 100644 --- a/tutorial01/leptjson.h +++ b/tutorial01/leptjson.h @@ -1,7 +1,8 @@ #ifndef LEPTJSON_H__ #define LEPTJSON_H__ -typedef enum { LEPT_NULL, LEPT_FALSE, LEPT_TRUE, LEPT_NUMBER, LEPT_STRING, LEPT_ARRAY, LEPT_OBJECT } lept_type; +typedef enum { LEPT_NULL, LEPT_FALSE, LEPT_TRUE, + LEPT_NUMBER, LEPT_STRING, LEPT_ARRAY, LEPT_OBJECT } lept_type; typedef struct { lept_type type; diff --git a/tutorial01/test.c b/tutorial01/test.c index e7672181..a601f157 100644 --- a/tutorial01/test.c +++ b/tutorial01/test.c @@ -27,6 +27,20 @@ static void test_parse_null() { EXPECT_EQ_INT(LEPT_NULL, lept_get_type(&v)); } +static void test_parse_true() { + lept_value v; + v.type = LEPT_FALSE; + EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, "true")); + EXPECT_EQ_INT(LEPT_TRUE, lept_get_type(&v)); +} + +static void test_parse_false() { + lept_value v; + v.type = LEPT_TRUE; + EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, "false")); + EXPECT_EQ_INT(LEPT_FALSE, lept_get_type(&v)); +} + static void test_parse_expect_value() { lept_value v; @@ -59,6 +73,8 @@ static void test_parse_root_not_singular() { static void test_parse() { test_parse_null(); + test_parse_true(); + test_parse_false(); test_parse_expect_value(); test_parse_invalid_value(); test_parse_root_not_singular(); diff --git a/tutorial02/leptjson.c b/tutorial02/leptjson.c index 7693e43b..e4d782c0 100644 --- a/tutorial02/leptjson.c +++ b/tutorial02/leptjson.c @@ -1,8 +1,10 @@ #include "leptjson.h" #include /* assert() */ #include /* NULL, strtod() */ +#include /* HUGE_VAL */ +#include -#define EXPECT(c, ch) do { assert(*c->json == (ch)); c->json++; } while(0) +#define EXPECT(c, ch) do { assert(*c->json == (ch));} while(0) typedef struct { const char* json; @@ -14,50 +16,76 @@ static void lept_parse_whitespace(lept_context* c) { p++; c->json = p; } +static int lept_parse_literal(lept_context* c, lept_value* v, + const char* s, lept_type t) { + size_t i=1; + EXPECT(c, *s); + while(s[i] != '\0') { + if (c->json[i] != s[i]) { + return LEPT_PARSE_INVALID_VALUE; + } + i++; + } -static int lept_parse_true(lept_context* c, lept_value* v) { - EXPECT(c, 't'); - if (c->json[0] != 'r' || c->json[1] != 'u' || c->json[2] != 'e') - return LEPT_PARSE_INVALID_VALUE; - c->json += 3; - v->type = LEPT_TRUE; + c->json += i; + v->type = t; return LEPT_PARSE_OK; -} -static int lept_parse_false(lept_context* c, lept_value* v) { - EXPECT(c, 'f'); - if (c->json[0] != 'a' || c->json[1] != 'l' || c->json[2] != 's' || c->json[3] != 'e') - return LEPT_PARSE_INVALID_VALUE; - c->json += 4; - v->type = LEPT_FALSE; - return LEPT_PARSE_OK; } -static int lept_parse_null(lept_context* c, lept_value* v) { - EXPECT(c, 'n'); - if (c->json[0] != 'u' || c->json[1] != 'l' || c->json[2] != 'l') - return LEPT_PARSE_INVALID_VALUE; - c->json += 3; - v->type = LEPT_NULL; - return LEPT_PARSE_OK; +static int lept_parse_some_digit(lept_context* c) { + if ('0'>*c->json || *c->json >'9') + return 1; + do { + c->json++; + } while('0' <= *c->json && *c->json <= '9'); + return 0; } - static int lept_parse_number(lept_context* c, lept_value* v) { - char* end; - /* \TODO validate number */ - v->n = strtod(c->json, &end); - if (c->json == end) + const char* start=c->json; + /* optional minus */ + if (*c->json=='-') c->json++; + /* integer part */ + if (*c->json!='0') { + if (lept_parse_some_digit(c) != 0) + return LEPT_PARSE_INVALID_VALUE; + } else { + c->json++; + } + /* dot? */ + if (*c->json=='.') { + c->json++; + if (lept_parse_some_digit(c) != 0) + return LEPT_PARSE_INVALID_VALUE; + } + /* e? */ + if (*c->json=='e' || *c->json=='E') + { + c->json++; + if (*c->json=='-' || *c->json=='+') c->json++; + if (lept_parse_some_digit(c) != 0) + return LEPT_PARSE_INVALID_VALUE; + } + if (c->json == start) return LEPT_PARSE_INVALID_VALUE; - c->json = end; + + lept_parse_whitespace(c); + if (*c->json != '\0') + return LEPT_PARSE_ROOT_NOT_SINGULAR; + errno = 0; + v->n = strtod(start, NULL); + if (errno == ERANGE && (v->n == HUGE_VAL || v->n == -HUGE_VAL)) + return LEPT_PARSE_NUMBER_TOO_BIG; + v->type = LEPT_NUMBER; return LEPT_PARSE_OK; } static int lept_parse_value(lept_context* c, lept_value* v) { switch (*c->json) { - case 't': return lept_parse_true(c, v); - case 'f': return lept_parse_false(c, v); - case 'n': return lept_parse_null(c, v); + case 't': return lept_parse_literal(c,v,"true", LEPT_TRUE); + case 'f': return lept_parse_literal(c,v,"false",LEPT_FALSE); + case 'n': return lept_parse_literal(c,v,"null",LEPT_NULL); default: return lept_parse_number(c, v); case '\0': return LEPT_PARSE_EXPECT_VALUE; } diff --git a/tutorial02/test.c b/tutorial02/test.c index 6e3ebed2..560a06fc 100644 --- a/tutorial02/test.c +++ b/tutorial02/test.c @@ -19,7 +19,7 @@ static int test_pass = 0; } while(0) #define EXPECT_EQ_INT(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%d") -#define EXPECT_EQ_DOUBLE(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%.17g") +#define EXPECT_EQ_DOUBLE(expect, actual) EXPECT_EQ_BASE(abs((expect)-(actual))<1e-12, expect, actual, "%.17g") static void test_parse_null() { lept_value v; @@ -70,6 +70,8 @@ static void test_parse_number() { TEST_NUMBER(1.234E+10, "1.234E+10"); TEST_NUMBER(1.234E-10, "1.234E-10"); TEST_NUMBER(0.0, "1e-10000"); /* must underflow */ + + } #define TEST_ERROR(error, json)\ @@ -89,7 +91,7 @@ static void test_parse_invalid_value() { TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "nul"); TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "?"); -#if 0 +#if 1 /* invalid number */ TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "+0"); TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "+1"); @@ -105,7 +107,7 @@ static void test_parse_invalid_value() { static void test_parse_root_not_singular() { TEST_ERROR(LEPT_PARSE_ROOT_NOT_SINGULAR, "null x"); -#if 0 +#if 1 /* invalid number */ TEST_ERROR(LEPT_PARSE_ROOT_NOT_SINGULAR, "0123"); /* after zero should be '.' or nothing */ TEST_ERROR(LEPT_PARSE_ROOT_NOT_SINGULAR, "0x0"); @@ -114,7 +116,7 @@ static void test_parse_root_not_singular() { } static void test_parse_number_too_big() { -#if 0 +#if 1 TEST_ERROR(LEPT_PARSE_NUMBER_TOO_BIG, "1e309"); TEST_ERROR(LEPT_PARSE_NUMBER_TOO_BIG, "-1e309"); #endif diff --git a/tutorial03/leptjson.c b/tutorial03/leptjson.c index 07f7e2c7..350fd9f0 100644 --- a/tutorial03/leptjson.c +++ b/tutorial03/leptjson.c @@ -94,6 +94,22 @@ static int lept_parse_string(lept_context* c, lept_value* v) { for (;;) { char ch = *p++; switch (ch) { + case '\\': + ch = *p++; + switch (ch) { + case '\"': PUTC(c,'\"');break; + case '\\': PUTC(c,'\\');break; + case '/': PUTC(c,'/');break; + case 'b': PUTC(c,'\b');break; + case 'f': PUTC(c,'\f');break; + case 'n': PUTC(c,'\n');break; + case 'r': PUTC(c,'\r');break; + case 't': PUTC(c,'\t');break; + default: + c->top=head; + return LEPT_PARSE_INVALID_STRING_ESCAPE; + } + break; case '\"': len = c->top - head; lept_set_string(v, (const char*)lept_context_pop(c, len), len); @@ -103,9 +119,14 @@ static int lept_parse_string(lept_context* c, lept_value* v) { c->top = head; return LEPT_PARSE_MISS_QUOTATION_MARK; default: + if ((unsigned char)ch < 32){ + c->top=head; + return LEPT_PARSE_INVALID_STRING_CHAR; + } PUTC(c, ch); } } + } static int lept_parse_value(lept_context* c, lept_value* v) { @@ -153,12 +174,14 @@ lept_type lept_get_type(const lept_value* v) { } int lept_get_boolean(const lept_value* v) { - /* \TODO */ - return 0; + assert(v != NULL && (v->type == LEPT_TRUE || v->type == LEPT_FALSE)); + + return v->type == LEPT_TRUE; } void lept_set_boolean(lept_value* v, int b) { - /* \TODO */ + lept_free(v); + v->type = b?LEPT_TRUE:LEPT_FALSE; } double lept_get_number(const lept_value* v) { @@ -167,7 +190,10 @@ double lept_get_number(const lept_value* v) { } void lept_set_number(lept_value* v, double n) { - /* \TODO */ + lept_free(v); + + v->type = LEPT_NUMBER; + v->u.n = n; } const char* lept_get_string(const lept_value* v) { @@ -181,7 +207,7 @@ size_t lept_get_string_length(const lept_value* v) { } void lept_set_string(lept_value* v, const char* s, size_t len) { - assert(v != NULL && (s != NULL || len == 0)); + assert(s != NULL || len == 0); lept_free(v); v->u.s.s = (char*)malloc(len + 1); memcpy(v->u.s.s, s, len); diff --git a/tutorial03/test.c b/tutorial03/test.c index ac788aca..bf4b6873 100644 --- a/tutorial03/test.c +++ b/tutorial03/test.c @@ -19,7 +19,7 @@ static int test_pass = 0; } while(0) #define EXPECT_EQ_INT(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%d") -#define EXPECT_EQ_DOUBLE(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%.17g") +#define EXPECT_EQ_DOUBLE(expect, actual) EXPECT_EQ_BASE(abs((expect) - (actual))<1e-6, expect, actual, "%.17g") #define EXPECT_EQ_STRING(expect, actual, alength) \ EXPECT_EQ_BASE(sizeof(expect) - 1 == alength && memcmp(expect, actual, alength) == 0, expect, actual, "%s") #define EXPECT_TRUE(actual) EXPECT_EQ_BASE((actual) != 0, "true", "false", "%s") @@ -107,7 +107,7 @@ static void test_parse_number() { static void test_parse_string() { TEST_STRING("", "\"\""); TEST_STRING("Hello", "\"Hello\""); -#if 0 +#if 1 TEST_STRING("Hello\nWorld", "\"Hello\\nWorld\""); TEST_STRING("\" \\ / \b \f \n \r \t", "\"\\\" \\\\ \\/ \\b \\f \\n \\r \\t\""); #endif @@ -163,7 +163,7 @@ static void test_parse_missing_quotation_mark() { } static void test_parse_invalid_string_escape() { -#if 0 +#if 1 TEST_ERROR(LEPT_PARSE_INVALID_STRING_ESCAPE, "\"\\v\""); TEST_ERROR(LEPT_PARSE_INVALID_STRING_ESCAPE, "\"\\'\""); TEST_ERROR(LEPT_PARSE_INVALID_STRING_ESCAPE, "\"\\0\""); @@ -172,7 +172,7 @@ static void test_parse_invalid_string_escape() { } static void test_parse_invalid_string_char() { -#if 0 +#if 1 TEST_ERROR(LEPT_PARSE_INVALID_STRING_CHAR, "\"\x01\""); TEST_ERROR(LEPT_PARSE_INVALID_STRING_CHAR, "\"\x1F\""); #endif @@ -188,12 +188,25 @@ static void test_access_null() { } static void test_access_boolean() { - /* \TODO */ - /* Use EXPECT_TRUE() and EXPECT_FALSE() */ + lept_value v; + lept_init(&v); + lept_set_string(&v, "a", 1); + lept_set_boolean(&v, 0); + EXPECT_FALSE(lept_get_boolean(&v)); + + lept_set_boolean(&v,1); + EXPECT_TRUE(lept_get_boolean(&v)); + lept_free(&v); } static void test_access_number() { - /* \TODO */ + lept_value v; + lept_init(&v); + lept_set_string(&v, "a", 1); + lept_set_number(&v, 100.01); + + EXPECT_EQ_DOUBLE(100.01, lept_get_number(&v)); + lept_free(&v); } static void test_access_string() { diff --git a/tutorial04/leptjson.c b/tutorial04/leptjson.c index 0a123bf2..1b59a022 100644 --- a/tutorial04/leptjson.c +++ b/tutorial04/leptjson.c @@ -90,20 +90,49 @@ static int lept_parse_number(lept_context* c, lept_value* v) { return LEPT_PARSE_OK; } -static const char* lept_parse_hex4(const char* p, unsigned* u) { - /* \TODO */ +static const char* lept_parse_hex4(const char* p, unsigned* pu) { + const char* end=p+4; + unsigned u=0; + for(;p> 6) & 0x1F)); + PUTC(c, 0x80 | ( u & 0x3F)); + } else if (u <= 0xFFFF) { + PUTC(c, 0xE0 | ((u >> 12) & 0x0F)); + PUTC(c, 0x80 | ((u >> 6) & 0x3F)); + PUTC(c, 0x80 | ( u & 0x3F)); + } else { + PUTC(c, 0xF0 | ((u >> 18) & 0x07)); + PUTC(c, 0x80 | ((u >> 12) & 0x3F)); + PUTC(c, 0x80 | ((u >> 6) & 0x3F)); + PUTC(c, 0x80 | ( u & 0x3F)); + } } #define STRING_ERROR(ret) do { c->top = head; return ret; } while(0) static int lept_parse_string(lept_context* c, lept_value* v) { size_t head = c->top, len; - unsigned u; + unsigned u, u2; const char* p; EXPECT(c, '\"'); p = c->json; @@ -128,7 +157,20 @@ static int lept_parse_string(lept_context* c, lept_value* v) { case 'u': if (!(p = lept_parse_hex4(p, &u))) STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_HEX); - /* \TODO surrogate handling */ + if ((u & 0xFC00) == 0xDC00) + STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_SURROGATE); + + if ((u & 0xFC00) == 0xD800) { + if (p[0] != '\\' || p[1] != 'u') + STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_SURROGATE); + p+=2; + if (!(p = lept_parse_hex4(p, &u2))) + STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_SURROGATE); + if ((u2 & 0xFC00) != 0xDC00) + STRING_ERROR(LEPT_PARSE_INVALID_UNICODE_SURROGATE); + + u = 0x10000 + ((u & (~0xD800)) << 10) + (u2 & (~0xDC00)); + } lept_encode_utf8(c, u); break; default: diff --git a/tutorial04/test.c b/tutorial04/test.c index beaa8724..28511840 100644 --- a/tutorial04/test.c +++ b/tutorial04/test.c @@ -23,7 +23,7 @@ static int test_pass = 0; } while(0) #define EXPECT_EQ_INT(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%d") -#define EXPECT_EQ_DOUBLE(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%.17g") +#define EXPECT_EQ_DOUBLE(expect, actual) EXPECT_EQ_BASE(abs((expect) -(actual))<1e-6, expect, actual, "%.17g") #define EXPECT_EQ_STRING(expect, actual, alength) \ EXPECT_EQ_BASE(sizeof(expect) - 1 == alength && memcmp(expect, actual, alength) == 0, expect, actual, "%s") #define EXPECT_TRUE(actual) EXPECT_EQ_BASE((actual) != 0, "true", "false", "%s") diff --git a/tutorial05/leptjson.c b/tutorial05/leptjson.c index d2c83f34..15c0326b 100644 --- a/tutorial05/leptjson.c +++ b/tutorial05/leptjson.c @@ -187,6 +187,7 @@ static int lept_parse_array(lept_context* c, lept_value* v) { size_t size = 0; int ret; EXPECT(c, '['); + lept_parse_whitespace(c); if (*c->json == ']') { c->json++; v->type = LEPT_ARRAY; @@ -197,10 +198,14 @@ static int lept_parse_array(lept_context* c, lept_value* v) { for (;;) { lept_value e; lept_init(&e); - if ((ret = lept_parse_value(c, &e)) != LEPT_PARSE_OK) + lept_parse_whitespace(c); + if ((ret = lept_parse_value(c, &e)) != LEPT_PARSE_OK){ + return ret; + } memcpy(lept_context_push(c, sizeof(lept_value)), &e, sizeof(lept_value)); size++; + lept_parse_whitespace(c); if (*c->json == ',') c->json++; else if (*c->json == ']') { @@ -253,6 +258,16 @@ void lept_free(lept_value* v) { assert(v != NULL); if (v->type == LEPT_STRING) free(v->u.s.s); + else if (v->type == LEPT_ARRAY) + { + size_t i,sz=v->u.a.size; + lept_value* start = v->u.a.e; + for (i = 0; i < sz; ++i) + { + lept_free(start+i); + } + free(start); + } v->type = LEPT_NULL; } diff --git a/tutorial05/test.c b/tutorial05/test.c index 2d4dd21e..157688b1 100644 --- a/tutorial05/test.c +++ b/tutorial05/test.c @@ -23,7 +23,7 @@ static int test_pass = 0; } while(0) #define EXPECT_EQ_INT(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%d") -#define EXPECT_EQ_DOUBLE(expect, actual) EXPECT_EQ_BASE((expect) == (actual), expect, actual, "%.17g") +#define EXPECT_EQ_DOUBLE(expect, actual) EXPECT_EQ_BASE(abs((expect) -(actual))<1e-6, expect, actual, "%.17g") #define EXPECT_EQ_STRING(expect, actual, alength) \ EXPECT_EQ_BASE(sizeof(expect) - 1 == alength && memcmp(expect, actual, alength) == 0, expect, actual, "%s") #define EXPECT_TRUE(actual) EXPECT_EQ_BASE((actual) != 0, "true", "false", "%s") @@ -134,6 +134,18 @@ static void test_parse_array() { EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, "[ ]")); EXPECT_EQ_INT(LEPT_ARRAY, lept_get_type(&v)); EXPECT_EQ_SIZE_T(0, lept_get_array_size(&v)); + + EXPECT_EQ_INT(LEPT_PARSE_OK, lept_parse(&v, "[ null , false , true , 123 , \"abc\" ]")); + EXPECT_EQ_INT(LEPT_ARRAY, lept_get_type(&v)); + EXPECT_EQ_SIZE_T(5, lept_get_array_size(&v)); + EXPECT_EQ_INT(LEPT_NULL, lept_get_type(lept_get_array_element(&v,0))); + EXPECT_FALSE(lept_get_boolean(lept_get_array_element(&v,1))); + EXPECT_TRUE(lept_get_boolean(lept_get_array_element(&v,2))); + EXPECT_EQ_INT(LEPT_NUMBER, lept_get_type(lept_get_array_element(&v,3))); + EXPECT_EQ_DOUBLE(123,lept_get_number(lept_get_array_element(&v,3))); + EXPECT_EQ_INT(LEPT_STRING, lept_get_type(lept_get_array_element(&v,4))); + EXPECT_EQ_STRING("abc",lept_get_string(lept_get_array_element(&v,4)),3); + lept_free(&v); } @@ -167,7 +179,7 @@ static void test_parse_invalid_value() { TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "nan"); /* invalid value in array */ -#if 0 +#if 1 TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "[1,]"); TEST_ERROR(LEPT_PARSE_INVALID_VALUE, "[\"a\", nul]"); #endif @@ -229,7 +241,7 @@ static void test_parse_invalid_unicode_surrogate() { } static void test_parse_miss_comma_or_square_bracket() { -#if 0 +#if 1 TEST_ERROR(LEPT_PARSE_MISS_COMMA_OR_SQUARE_BRACKET, "[1"); TEST_ERROR(LEPT_PARSE_MISS_COMMA_OR_SQUARE_BRACKET, "[1}"); TEST_ERROR(LEPT_PARSE_MISS_COMMA_OR_SQUARE_BRACKET, "[1 2");