You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

210 lines
6.1 KiB

#include "Token.hpp"
#include <cstdlib>
class JSONParser {
std::fstream file;
JSONNode *root;
JSONNode *current;
Tokenizer tokenizer;
public:
JSONParser(const string filename) : tokenizer(filename) {}
void parse() {
string key = "";
while (tokenizer.hasMoreTokens()) {
Token *token;
JSONNode *parsed;
try {
token = tokenizer.getToken();
switch (token->type) {
case CURLY_OPEN: {
parsed = parseObject();
if (!root) {
root = parsed;
}
break;
}
case ARRAY_OPEN: {
parsed = parseList();
if (!root) {
root = parsed;
}
break;
}
case STRING: {
tokenizer.rollBackToken();
parsed = parseString();
break;
}
case NUMBER: {
tokenizer.rollBackToken();
parsed = parseNumber();
break;
}
case BOOLEAN: {
tokenizer.rollBackToken();
parsed = parseBoolean();
break;
}
default:
break;
}
parsed->stringify(0);
}
catch (std::logic_error &e) {
break;
}
delete token;
}
// assert token not valid
}
JSONNode *parseObject() {
//cout << "Parse Object\n";
JSONNode *node = new JSONNode();
JSONObject *keyObjectMap = new JSONObject();
bool hasCompleted = false;
Token *token = tokenizer.getToken();
while (!hasCompleted) {
if (tokenizer.hasMoreTokens()) {
string key = token->value;
tokenizer.getToken();
token = tokenizer.getToken();
switch (token->type) {
case STRING: {
tokenizer.rollBackToken();
(*keyObjectMap)[key] = parseString();
break;
}
case ARRAY_OPEN: {
(*keyObjectMap)[key] = parseList();
break;
}
case NUMBER: {
tokenizer.rollBackToken();
(*keyObjectMap)[key] = parseNumber();
break;
}
case CURLY_OPEN: {
(*keyObjectMap)[key] = parseObject();
break;
}
case BOOLEAN: {
tokenizer.rollBackToken();
(*keyObjectMap)[key] = parseBoolean();
break;
}
case NULL_TYPE: {
(*keyObjectMap)[key] = parseNull();
break;
}
default:
break;
}
delete token;
token = tokenizer.getToken();
if (token->type == CURLY_CLOSE) {
hasCompleted = true;
delete token;
break;
}
} else {
throw std::logic_error("No more tokens");
}
}
node->setObject(keyObjectMap);
return node;
}
JSONNode *parseList() {
//cout << "Parse List\n";
JSONNode *node = new JSONNode();
JSONList *list = new JSONList();
bool hasCompleted = false;
Token *token = tokenizer.getToken();
while (!hasCompleted) {
if (!tokenizer.hasMoreTokens()) {
throw std::logic_error("No more tokens");
} else {
JSONNode *node;
switch (token->type) {
case ARRAY_OPEN: {
node = parseList();
break;
}
case CURLY_OPEN: {
node = parseObject();
break;
}
case STRING: {
tokenizer.rollBackToken();
node = parseString();
break;
}
case NUMBER: {
tokenizer.rollBackToken();
node = parseNumber();
break;
}
case BOOLEAN: {
tokenizer.rollBackToken();
node = parseBoolean();
break;
}
case NULL_TYPE: {
node = parseNull();
break;
}
default:
break;
}
list->push_back(node);
delete token;
token = tokenizer.getToken();
if (token->type == ARRAY_CLOSE) {
hasCompleted = true;
}
}
}
delete token;
node->setList(list);
return node;
}
JSONNode *parseString() {
//cout << "Parse string\n";
JSONNode *node = new JSONNode();
Token *token = tokenizer.getToken();
string *sValue = new string(token->value);
delete token;
node->setString(sValue);
return node;
}
JSONNode *parseNumber() {
//cout << "Parse number\n";
JSONNode *node = new JSONNode();
Token *token = tokenizer.getToken();
string value = token->value;
delete token;
// cout << value << "\n";
int nbr = std::atoi(value.c_str());
node->setNumber(nbr);
return node;
}
JSONNode *parseBoolean() {
JSONNode *node = new JSONNode();
Token *token = tokenizer.getToken();
node->setBoolean(token->value == "True" ? true : false);
delete token;
return node;
}
JSONNode *parseNull() {
JSONNode *node = new JSONNode();
node->setNull();
return node;
}
};