Parsodus/examples/json/parser.cpp

181 lines
5.6 KiB
C++

#include "parser.h"
#include <algorithm>
#include <cassert>
#include <codecvt>
#include <deque>
#include <locale>
#include <sstream>
#include <iostream>
namespace {
double readNumber(std::string in) {
std::istringstream iss(in);
double d;
iss >> d;
return d;
}
std::string readString(std::string in) {
std::string result;
for (std::size_t i = 1; i < in.length() - 1; i++) {
if (in[i] == '\\' && in[i + 1] != 'u') {
char c = 0;
switch (in[i + 1]) {
case '"':
case '\\':
case '/':
c = in[i + 1];
break;
case 'b':
c = '\b';
break;
case 'f':
c = '\f';
break;
case 'n':
c = '\n';
break;
case 'r':
c = '\r';
break;
case 't':
c = '\t';
break;
default:
break;
}
result.push_back(c);
i++;
} else if (in[i] == '\\'){
char16_t unicode_value;
std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t > utf8converter;
unicode_value = 0;
for (int j = 0; j < 4; j++, i++) {
char hex = in[i + 2];
unicode_value *= 16;
if (hex >= '0' && hex <= '9')
unicode_value += hex - '0';
else if (hex >= 'A' && hex <= '9')
unicode_value += hex - 'A' + 10;
else
unicode_value += hex - 'a' + 10;
}
result.append(utf8converter.to_bytes(unicode_value));
i++;
} else {
if (iscntrl(in[i])) {
throw SyntaxError("Control character inside string");
}
result.push_back(in[i]);
}
}
return result;
}
}
namespace json {
Parser::Parser(JSONLexer lex) : JSONParser<JSON>(), m_lex(lex)
{}
Parser::Token Parser::lex() {
try {
JSONLexer::Token orig = m_lex.nextToken();
JSONParser_Symbol s;
switch (orig.type) {
case JSONLexer::COLON:
s = JSONParser_Symbol::T_COLON;
break;
case JSONLexer::COMMA:
s = JSONParser_Symbol::T_COMMA;
break;
case JSONLexer::LBRACE:
s = JSONParser_Symbol::T_LBRACE;
break;
case JSONLexer::RBRACE:
s = JSONParser_Symbol::T_RBRACE;
break;
case JSONLexer::LBRACKET:
s = JSONParser_Symbol::T_LBRACKET;
break;
case JSONLexer::RBRACKET:
s = JSONParser_Symbol::T_RBRACKET;
break;
case JSONLexer::STRING:
return Token{JSONParser_Symbol::T_STRING, JSON::string(readString(orig.content))};
case JSONLexer::NUMBER:
return Token{JSONParser_Symbol::T_NUMBER, JSON::num(readNumber(orig.content))};
case JSONLexer::TTRUE:
return Token{JSONParser_Symbol::T_TTRUE, JSON::boolean(true)};
case JSONLexer::TFALSE:
return Token{JSONParser_Symbol::T_TFALSE, JSON::boolean(false)};
case JSONLexer::TNULL:
return Token{JSONParser_Symbol::T_TNULL, JSON::null()};
default:
//impossible
break;
}
return Token{s, JSON()};
}
catch (JSONLexer::NoMoreTokens) {
return Token{JSONParser_Symbol::T_EOF, JSON()};
}
}
JSON Parser::reduce_0(std::deque<Token> subparts) {
return std::move(subparts[0].value);
}
JSON Parser::reduce_1(std::deque<Token> subparts) {
return std::move(subparts[0].value);
}
JSON Parser::reduce_2(std::deque<Token> subparts) {
return std::move(subparts[0].value);
}
JSON Parser::reduce_3(std::deque<Token> subparts) {
return std::move(subparts[0].value);
}
JSON Parser::reduce_4(std::deque<Token> subparts) {
return std::move(subparts[0].value);
}
JSON Parser::reduce_5(std::deque<Token> subparts) {
return std::move(subparts[0].value);
}
JSON Parser::reduce_6(std::deque<Token> subparts) {
return std::move(subparts[0].value);
}
JSON Parser::reduce_7(std::deque<Token> subparts) {
return std::move(subparts[1].value);
}
JSON Parser::reduce_8(std::deque<Token>) {
return JSON::object();
}
JSON Parser::reduce_9(std::deque<Token> subparts) {
JSON obj = JSON::object();
obj[std::move(subparts[0].value)] = std::move(subparts[2].value);
return obj;
}
JSON Parser::reduce_10(std::deque<Token> subparts) {
JSON obj = std::move(subparts[4].value);
obj[std::move(subparts[0].value)] = std::move(subparts[2].value);
return obj;
}
JSON Parser::reduce_11(std::deque<Token> subparts) {
return std::move(subparts[1].value);
}
JSON Parser::reduce_12(std::deque<Token>) {
return JSON::array();
}
JSON Parser::reduce_13(std::deque<Token> subparts) {
JSON arr = JSON::array();
arr.push_front(std::move(subparts[0].value));
return arr;
}
JSON Parser::reduce_14(std::deque<Token> subparts) {
JSON arr = std::move(subparts[2].value);
arr.push_front(std::move(subparts[0].value));
return arr;
}
}