You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
264 lines
8.4 KiB
264 lines
8.4 KiB
#include "json_parser.h" |
|
|
|
namespace Bk::Json |
|
{ |
|
Parser::Parser(File& file) |
|
{ |
|
Type::DataStream data; |
|
if (file.exists()) |
|
{ |
|
data = file.read(file.size()); |
|
data.reverse(); |
|
} |
|
lexer = Lexer(data); |
|
} |
|
|
|
Parser::Parser(const char* str, int length) |
|
{ |
|
Type::DataStream data; |
|
data.payload = std::vector<char>(str, str + length); |
|
data.reverse(); |
|
lexer = Lexer(data); |
|
} |
|
|
|
Parser::Parser(const std::string& str) |
|
{ |
|
Type::DataStream data; |
|
data.payload = std::vector<char>(str.c_str(), str.c_str() + str.length()); |
|
data.reverse(); |
|
lexer = Lexer(data); |
|
} |
|
|
|
std::shared_ptr<Json::Node> Parser::parse() |
|
{ |
|
Token token; |
|
while (lexer.has_more_tokens()) { |
|
try |
|
{ |
|
token = lexer.get_token(); |
|
switch (token.type) |
|
{ |
|
case TokenType::CURLY_OPEN: |
|
{ |
|
std::shared_ptr<Json::Node> parsed_object = parse_object(); |
|
if (!root) { |
|
root = parsed_object; |
|
} |
|
break; |
|
} |
|
case TokenType::ARRAY_OPEN: { |
|
std::shared_ptr<Json::Node> parsed_list = parse_list(); |
|
if (!root) { |
|
root = parsed_list; |
|
} |
|
break; |
|
} |
|
|
|
case TokenType::STRING: { |
|
|
|
std::shared_ptr<Json::Node> parsed_string = parse_string(); |
|
if (!root) { |
|
root = parsed_string; |
|
} |
|
break; |
|
} |
|
case TokenType::NUMBER: { |
|
std::shared_ptr<Json::Node> parsed_number = parse_number(); |
|
if (!root) { |
|
root = parsed_number; |
|
} |
|
break; |
|
} |
|
|
|
case TokenType::BOOLEAN: { |
|
std::shared_ptr<Json::Node> parsed_boolean = parse_boolean(); |
|
break; |
|
} |
|
} |
|
} |
|
catch(std::logic_error& e) |
|
{ |
|
BK_INFO(e.what()); |
|
auto node = std::shared_ptr<Json::Node>(); |
|
node->set_null(); |
|
root = node; |
|
break; |
|
} |
|
} |
|
return root; |
|
} |
|
|
|
std::shared_ptr<Json::Node> Parser::parse_list() |
|
{ |
|
std::shared_ptr<Json::Node> node = std::make_shared<Json::Node>(); |
|
Json::List *list = new Json::List(); |
|
bool has_completed = false; |
|
Token next_token; |
|
while (!has_completed) { |
|
if (!lexer.has_more_tokens()) |
|
{ |
|
throw std::logic_error("No more tokens"); |
|
} |
|
else |
|
{ |
|
next_token = lexer.get_token(); |
|
if (next_token.type == TokenType::COLON || next_token.type == TokenType::COMMA) |
|
continue; |
|
std::shared_ptr<Json::Node> node; |
|
switch (next_token.type) |
|
{ |
|
case TokenType::ARRAY_OPEN: |
|
{ |
|
node = parse_list(); |
|
break; |
|
} |
|
case TokenType::CURLY_OPEN: |
|
{ |
|
node = parse_object(); |
|
break; |
|
} |
|
case TokenType::STRING: |
|
{ |
|
node = parse_string(); |
|
break; |
|
} |
|
case TokenType::NUMBER: |
|
{ |
|
node = parse_number(); |
|
break; |
|
} |
|
case TokenType::BOOLEAN: |
|
{ |
|
node = parse_boolean(); |
|
break; |
|
} |
|
case TokenType::NULL_TYPE: { |
|
node = parse_null(); |
|
break; |
|
} |
|
} |
|
list->push_back(node); |
|
if (next_token.type == TokenType::ARRAY_CLOSE) { |
|
has_completed = true; |
|
} |
|
} |
|
} |
|
node->set_list(list); |
|
return node; |
|
} |
|
|
|
std::shared_ptr<Json::Node> Parser::parse_object() |
|
{ |
|
std::string key = ""; |
|
std::shared_ptr<Json::Node> node = std::make_shared<Json::Node>(); |
|
Json::Object *key_object_map = new Json::Object(); |
|
bool has_completed = false; |
|
bool no_key = true; |
|
Token next_token; |
|
while (!has_completed) |
|
{ |
|
if (lexer.has_more_tokens()) |
|
{ |
|
if (no_key) |
|
{ |
|
next_token = lexer.get_token(); |
|
if (next_token.type == TokenType::CURLY_CLOSE) |
|
{ |
|
has_completed = true; |
|
break; |
|
} |
|
if (next_token.type == TokenType::COLON || next_token.type == TokenType::COMMA) |
|
continue; |
|
key = next_token.value; |
|
no_key = false; |
|
} |
|
next_token = lexer.get_token(); |
|
if (next_token.type == TokenType::COLON || next_token.type == TokenType::COMMA) |
|
continue; |
|
std::shared_ptr<Json::Node> node; |
|
switch (next_token.type) |
|
{ |
|
case TokenType::STRING: |
|
{ |
|
(*key_object_map)[key] = parse_string(); |
|
break; |
|
} |
|
case TokenType::ARRAY_OPEN: |
|
{ |
|
(*key_object_map)[key] = parse_list(); |
|
break; |
|
} |
|
case TokenType::NUMBER: |
|
{ |
|
(*key_object_map)[key] = parse_number(); |
|
break; |
|
} |
|
case TokenType::CURLY_OPEN: |
|
{ |
|
(*key_object_map)[key] = parse_object(); |
|
break; |
|
} |
|
case TokenType::BOOLEAN: |
|
{ |
|
(*key_object_map)[key] = parse_boolean(); |
|
break; |
|
|
|
} |
|
case TokenType::NULL_TYPE: |
|
{ |
|
(*key_object_map)[key] = parse_null(); |
|
break; |
|
} |
|
} |
|
if (next_token.type == TokenType::CURLY_CLOSE) |
|
{ |
|
has_completed = true; |
|
break; |
|
} |
|
no_key = true; |
|
key = ""; |
|
} |
|
else |
|
{ |
|
throw std::logic_error("No more tokens"); |
|
} |
|
} |
|
node->set_object(key_object_map); |
|
return node; |
|
} |
|
|
|
std::shared_ptr<Json::Node> Parser::parse_string() |
|
{ |
|
std::shared_ptr<Json::Node> node = std::make_shared<Json::Node>(); |
|
Token token = lexer.roll_back_token(); |
|
std::string *sValue = new std::string(token.value); |
|
node->set_string(sValue); |
|
return node; |
|
} |
|
|
|
std::shared_ptr<Json::Node> Parser::parse_number() |
|
{ |
|
std::shared_ptr<Json::Node> node = std::make_shared<Json::Node>(); |
|
Token token = lexer.roll_back_token(); |
|
float fValue = std::stof(token.value); |
|
node->set_float(fValue); |
|
return node; |
|
} |
|
|
|
std::shared_ptr<Json::Node> Parser::parse_boolean() |
|
{ |
|
std::shared_ptr<Json::Node> node = std::make_shared<Json::Node>(); |
|
Token token = lexer.roll_back_token(); |
|
bool bValue = token.value == "True" ? true : false; |
|
node->set_bool(bValue); |
|
return node; |
|
} |
|
|
|
std::shared_ptr<Json::Node> Parser::parse_null() |
|
{ |
|
std::shared_ptr<Json::Node> node = std::make_shared<Json::Node>(); |
|
Token token = lexer.roll_back_token(); |
|
node->set_null(); |
|
return node; |
|
} |
|
} |