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
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;
|
|
}
|
|
};
|
|
|