/* * Parsodus - A language agnostic parser generator * Copyright © 2016-2017 Thomas Avé, Robin Jadoul, Kobe Wullaert * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "parser.h" #include #include #include #include #include #include #include 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, 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(), 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 subparts) { return std::move(subparts[0].value); } JSON Parser::reduce_1(std::deque subparts) { return std::move(subparts[0].value); } JSON Parser::reduce_2(std::deque subparts) { return std::move(subparts[0].value); } JSON Parser::reduce_3(std::deque subparts) { return std::move(subparts[0].value); } JSON Parser::reduce_4(std::deque subparts) { return std::move(subparts[0].value); } JSON Parser::reduce_5(std::deque subparts) { return std::move(subparts[0].value); } JSON Parser::reduce_6(std::deque subparts) { return std::move(subparts[0].value); } JSON Parser::reduce_7(std::deque subparts) { return std::move(subparts[1].value); } JSON Parser::reduce_8(std::deque) { return JSON::object(); } JSON Parser::reduce_9(std::deque subparts) { JSON obj = JSON::object(); obj[std::move(subparts[0].value)] = std::move(subparts[2].value); return obj; } JSON Parser::reduce_10(std::deque 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 subparts) { return std::move(subparts[1].value); } JSON Parser::reduce_12(std::deque) { return JSON::array(); } JSON Parser::reduce_13(std::deque subparts) { JSON arr = JSON::array(); arr.push_front(std::move(subparts[0].value)); return arr; } JSON Parser::reduce_14(std::deque subparts) { JSON arr = std::move(subparts[2].value); arr.push_front(std::move(subparts[0].value)); return arr; } }