11 #define JSON_TOKEN_INVALID -1
12 #define JSON_TOKEN_EOF 0
13 #define JSON_TOKEN_STRING 256
14 #define JSON_TOKEN_NUMBER 257
15 #define JSON_TOKEN_TRUE 258
16 #define JSON_TOKEN_FALSE 259
17 #define JSON_TOKEN_NULL 260
31 /*** error reporting ***/
33 static __thread char *json_error_msg = NULL;
35 static void json_set_error(const json_lex *lex, const char *msg)
39 asprintf(&json_error_msg, "%s near '%.*s' on line %d", msg,
40 (int)(lex->input - lex->start), lex->start, lex->line);
42 asprintf(&json_error_msg, "%s near end of file", msg);
45 const char *json_get_error(void)
48 json_error_msg = strdup("success");
49 return json_error_msg;
53 /*** lexical analyzer ***/
55 static void json_scan_string(json_lex *lex)
58 const char *p = lex->input + 1;
61 lex->token = JSON_TOKEN_INVALID;
65 /* unterminated string literal */
69 if(0 <= *p && *p <= 31) {
70 /* control character */
77 for(int i = 0; i < 4; i++, p++) {
82 if(*p == '"' || *p == '\\' || *p == '/' || *p == 'b' ||
83 *p == 'f' || *p == 'n' || *p == 'r' || *p == 't')
92 /* the actual value is at most of the same length as the source
94 lex->value.string = malloc(p - lex->start);
95 if(!lex->value.string) {
96 /* this is not very nice, since TOKEN_INVALID is returned */
101 t = lex->value.string;
108 /* TODO: \uXXXX not supported yet */
109 free(lex->value.string);
110 lex->value.string = NULL;
114 case '"': case '\\': case '/':
116 case 'b': *t = '\b'; break;
117 case 'f': *t = '\f'; break;
118 case 'n': *t = '\n'; break;
119 case 'r': *t = '\r'; break;
120 case 't': *t = '\t'; break;
135 lex->token = JSON_TOKEN_STRING;
141 static void json_scan_number(json_lex *lex)
143 const char *p = lex->input;
146 lex->token = JSON_TOKEN_INVALID;
153 else /* *p != '0' */ {
168 if(*p == 'E' || *p == 'e') {
170 if(*p == '+' || *p == '-')
180 lex->token = JSON_TOKEN_NUMBER;
182 lex->value.number = strtod(lex->start, &end);
189 static int json_lex_scan(json_lex *lex)
193 if(lex->token == JSON_TOKEN_STRING) {
194 free(lex->value.string);
195 lex->value.string = NULL;
198 while(isspace(*lex->input)) {
199 if(*lex->input == '\n')
205 lex->start = lex->input;
209 lex->token = JSON_TOKEN_EOF;
211 else if(c == '{' || c == '}' || c == '[' || c == ']' ||
212 c == ':' || c == ',') {
218 json_scan_string(lex);
220 else if(isdigit(c) || c == '-')
221 json_scan_number(lex);
223 else if(isalpha(c)) {
224 /* eat up the whole identifier for clearer error messages */
227 while(isalpha(*lex->input))
229 len = lex->input - lex->start;
231 if(strncmp(lex->start, "true", len) == 0)
232 lex->token = JSON_TOKEN_TRUE;
233 else if(strncmp(lex->start, "false", len) == 0)
234 lex->token = JSON_TOKEN_FALSE;
235 else if(strncmp(lex->start, "null", len) == 0)
236 lex->token = JSON_TOKEN_NULL;
238 lex->token = JSON_TOKEN_INVALID;
242 lex->token = JSON_TOKEN_INVALID;
249 static int json_lex_init(json_lex *lex, const char *input)
252 lex->token = JSON_TOKEN_INVALID;
259 static void json_lex_close(json_lex *lex)
261 if(lex->token == JSON_TOKEN_STRING)
262 free(lex->value.string);
268 static json_t *json_parse(json_lex *lex);
270 static json_t *json_parse_object(json_lex *lex)
272 json_t *object = json_object();
277 if(lex->token == '}')
284 if(lex->token != JSON_TOKEN_STRING) {
285 json_set_error(lex, "string expected");
289 key = strdup(lex->value.string);
294 if(lex->token != ':') {
295 json_set_error(lex, "':' expected");
301 value = json_parse(lex);
305 if(json_object_set(object, key, value)) {
313 if(lex->token != ',')
319 if(lex->token != '}') {
320 json_set_error(lex, "'}' expected");
331 static json_t *json_parse_array(json_lex *lex)
333 json_t *array = json_array();
338 if(lex->token != ']') {
340 json_t *elem = json_parse(lex);
344 if(json_array_append(array, elem)) {
350 if(lex->token != ',')
357 if(lex->token != ']') {
358 json_set_error(lex, "']' expected");
369 static json_t *json_parse(json_lex *lex)
374 case JSON_TOKEN_STRING: {
375 json = json_string(lex->value.string);
379 case JSON_TOKEN_NUMBER: {
380 json = json_number(lex->value.number);
384 case JSON_TOKEN_TRUE:
388 case JSON_TOKEN_FALSE:
392 case JSON_TOKEN_NULL:
397 json = json_parse_object(lex);
401 json = json_parse_array(lex);
404 case JSON_TOKEN_INVALID:
405 json_set_error(lex, "invalid token");
409 json_set_error(lex, "unexpected token");
420 json_t *json_loads(const char *string)
423 json_t *result = NULL;
425 if(json_lex_init(&lex, string))
428 if(lex.token != '[' && lex.token != '{') {
429 json_set_error(&lex, "'[' or '{' expected");
433 result = json_parse(&lex);
437 if(lex.token != JSON_TOKEN_EOF) {
438 json_set_error(&lex, "end of file expected");
444 json_lex_close(&lex);