1 #include <msp/stringcodec/utf8.h>
4 #include "jsonparser.h"
11 JsonParser::JsonParser(Input &i, const string &s):
13 toplevel_state(STATE_INIT)
16 Statement JsonParser::parse()
18 if(toplevel_state==STATE_END)
21 bool was_init = (toplevel_state==STATE_INIT);
22 Token token = parse_token();
23 if(toplevel_state==STATE_INIT)
26 toplevel_state = STATE_ARRAY;
27 else if(token.str=="{")
28 toplevel_state = STATE_OBJECT;
31 // TODO Standalone simple values; does anyone use them?
32 toplevel_state = STATE_END;
33 throw syntax_error(token.str);
36 token = parse_token();
39 if((toplevel_state==STATE_ARRAY && token.str=="]") || (toplevel_state==STATE_OBJECT && token.str=="}"))
41 toplevel_state = STATE_END;
47 throw syntax_error(token.str);
49 token = parse_token();
52 return parse_statement(&token, toplevel_state, string());
55 Statement JsonParser::parse_statement(const Token *t, State outer_state, const string &outer_kw)
71 ParseState state = INIT;
73 if(outer_state==STATE_ARRAY)
75 result.keyword = outer_kw+"[]";
88 token = parse_token();
94 result.line = in.get_line_number();
99 if(token.type!=Token::STRING)
100 throw syntax_error(token.str);
102 result.keyword = token.str;
105 else if((state==ARRAY_INIT || state==ARRAY_ELEMENT) && token.str=="]")
107 else if((state==ARRAY_INIT || state==ARRAY))
109 Statement ss = parse_statement(&token, STATE_ARRAY, result.keyword);
110 result.sub.push_back(ss);
111 state = ARRAY_ELEMENT;
113 else if(state==ARRAY_ELEMENT && token.str==",")
115 else if((state==OBJECT_INIT || state==OBJECT_MEMBER) && token.str=="}")
117 else if((state==OBJECT_INIT || state==OBJECT))
119 Statement ss = parse_statement(&token, STATE_OBJECT, result.keyword);
120 result.sub.push_back(ss);
121 state = OBJECT_MEMBER;
123 else if(state==OBJECT_MEMBER && token.str==",")
125 else if(state==NAME && token.str==":")
127 else if(state==VALUE)
131 else if(token.str=="{")
133 else if(token.type!=Token::SPECIAL)
135 result.append_from_token(token);
139 throw syntax_error(token.str);
142 throw syntax_error(token.str);
148 Token JsonParser::parse_token()
160 return Token(Token::SPECIAL, "");
178 static Token::Type token_type[]=
194 ParseState state = INIT;
201 int next = in.peek();
214 else if(c=='{' || c=='}' || c=='[' || c==']' || c==':' || c==',')
215 return Token(Token::SPECIAL, string(1, c));
221 throw parse_error(buf);
230 throw parse_error(buf);
236 else if(c=='e' || c=='E')
237 state = FLOATEXPINIT;
239 throw parse_error(buf);
244 state = FLOATEXPINIT;
246 throw parse_error(buf);
251 state = FLOATEXPSIGN;
255 throw parse_error(buf);
262 throw parse_error(buf);
267 throw parse_error(buf);
272 state = STRING_ESCAPE;
283 throw parse_error(buf);
287 throw parse_error(buf);
290 throw logic_error("bad parser state");
293 if(is_delimiter(next) && state>=ACCEPT)
295 if(state==STRING_END)
296 return Token(Token::STRING, unescape(buf.substr(1, buf.size()-2)));
298 return Token(token_type[state], buf);
303 bool JsonParser::is_delimiter(int c)
305 return (isspace(c) || c=='{' || c=='}' || c=='[' || c==']' || c==':' || c==',');
308 string JsonParser::unescape(const string &str)
311 StringCodec::Utf8::Decoder dec;
312 StringCodec::Utf8::Encoder enc;
315 for(string::const_iterator i=str.begin(); i!=str.end(); )
317 StringCodec::unichar c = dec.decode_char(str, i);
322 enc.encode_char('\"', result);
324 enc.encode_char('\\', result);
326 enc.encode_char('/', result);
328 enc.encode_char('\b', result);
330 enc.encode_char('\f', result);
332 enc.encode_char('\n', result);
334 enc.encode_char('\r', result);
336 enc.encode_char('\t', result);
340 for(unsigned n=0; n<4; ++n)
343 throw invalid_argument("JsonParser::unescape");
345 c = dec.decode_char(str, i);
350 else if(c>='a' && c<='f')
352 else if(c>='A' && c<='F')
355 throw invalid_argument("JsonParser::unescape");
357 code = (code<<4)+digit;
360 enc.encode_char(code, result);
363 throw invalid_argument("JsonParser::unescape");
370 enc.encode_char(c, result);
376 } // namespace DataFile