nicolas-arnaud
2 years ago
14 changed files with 10 additions and 949 deletions
@ -1,210 +0,0 @@ |
|||
#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; |
|||
} |
|||
}; |
@ -1,192 +0,0 @@ |
|||
--- |
|||
Language: Cpp |
|||
# BasedOnStyle: LLVM |
|||
AccessModifierOffset: -2 |
|||
AlignAfterOpenBracket: Align |
|||
AlignArrayOfStructures: None |
|||
AlignConsecutiveMacros: None |
|||
AlignConsecutiveAssignments: None |
|||
AlignConsecutiveBitFields: None |
|||
AlignConsecutiveDeclarations: None |
|||
AlignEscapedNewlines: Right |
|||
AlignOperands: Align |
|||
AlignTrailingComments: true |
|||
AllowAllArgumentsOnNextLine: true |
|||
AllowAllParametersOfDeclarationOnNextLine: true |
|||
AllowShortEnumsOnASingleLine: true |
|||
AllowShortBlocksOnASingleLine: Never |
|||
AllowShortCaseLabelsOnASingleLine: false |
|||
AllowShortFunctionsOnASingleLine: All |
|||
AllowShortLambdasOnASingleLine: All |
|||
AllowShortIfStatementsOnASingleLine: Never |
|||
AllowShortLoopsOnASingleLine: false |
|||
AlwaysBreakAfterDefinitionReturnType: None |
|||
AlwaysBreakAfterReturnType: None |
|||
AlwaysBreakBeforeMultilineStrings: false |
|||
AlwaysBreakTemplateDeclarations: MultiLine |
|||
AttributeMacros: |
|||
- __capability |
|||
BinPackArguments: true |
|||
BinPackParameters: true |
|||
BraceWrapping: |
|||
AfterCaseLabel: false |
|||
AfterClass: false |
|||
AfterControlStatement: Never |
|||
AfterEnum: false |
|||
AfterFunction: false |
|||
AfterNamespace: false |
|||
AfterObjCDeclaration: false |
|||
AfterStruct: false |
|||
AfterUnion: false |
|||
AfterExternBlock: false |
|||
BeforeCatch: false |
|||
BeforeElse: false |
|||
BeforeLambdaBody: false |
|||
BeforeWhile: false |
|||
IndentBraces: false |
|||
SplitEmptyFunction: true |
|||
SplitEmptyRecord: true |
|||
SplitEmptyNamespace: true |
|||
BreakBeforeBinaryOperators: None |
|||
BreakBeforeConceptDeclarations: true |
|||
BreakBeforeBraces: Attach |
|||
BreakBeforeInheritanceComma: false |
|||
BreakInheritanceList: BeforeColon |
|||
BreakBeforeTernaryOperators: true |
|||
BreakConstructorInitializersBeforeComma: false |
|||
BreakConstructorInitializers: BeforeColon |
|||
BreakAfterJavaFieldAnnotations: false |
|||
BreakStringLiterals: true |
|||
ColumnLimit: 80 |
|||
CommentPragmas: '^ IWYU pragma:' |
|||
QualifierAlignment: Leave |
|||
CompactNamespaces: false |
|||
ConstructorInitializerIndentWidth: 4 |
|||
ContinuationIndentWidth: 4 |
|||
Cpp11BracedListStyle: true |
|||
DeriveLineEnding: true |
|||
DerivePointerAlignment: false |
|||
DisableFormat: false |
|||
EmptyLineAfterAccessModifier: Never |
|||
EmptyLineBeforeAccessModifier: LogicalBlock |
|||
ExperimentalAutoDetectBinPacking: false |
|||
PackConstructorInitializers: BinPack |
|||
BasedOnStyle: '' |
|||
ConstructorInitializerAllOnOneLineOrOnePerLine: false |
|||
AllowAllConstructorInitializersOnNextLine: true |
|||
FixNamespaceComments: true |
|||
ForEachMacros: |
|||
- foreach |
|||
- Q_FOREACH |
|||
- BOOST_FOREACH |
|||
IfMacros: |
|||
- KJ_IF_MAYBE |
|||
IncludeBlocks: Preserve |
|||
IncludeCategories: |
|||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/' |
|||
Priority: 2 |
|||
SortPriority: 0 |
|||
CaseSensitive: false |
|||
- Regex: '^(<|"(gtest|gmock|isl|json)/)' |
|||
Priority: 3 |
|||
SortPriority: 0 |
|||
CaseSensitive: false |
|||
- Regex: '.*' |
|||
Priority: 1 |
|||
SortPriority: 0 |
|||
CaseSensitive: false |
|||
IncludeIsMainRegex: '(Test)?$' |
|||
IncludeIsMainSourceRegex: '' |
|||
IndentAccessModifiers: false |
|||
IndentCaseLabels: false |
|||
IndentCaseBlocks: false |
|||
IndentGotoLabels: true |
|||
IndentPPDirectives: None |
|||
IndentExternBlock: AfterExternBlock |
|||
IndentRequires: false |
|||
IndentWidth: 4 |
|||
IndentWrappedFunctionNames: false |
|||
InsertTrailingCommas: None |
|||
JavaScriptQuotes: Leave |
|||
JavaScriptWrapImports: true |
|||
KeepEmptyLinesAtTheStartOfBlocks: true |
|||
LambdaBodyIndentation: Signature |
|||
MacroBlockBegin: '' |
|||
MacroBlockEnd: '' |
|||
MaxEmptyLinesToKeep: 1 |
|||
NamespaceIndentation: None |
|||
ObjCBinPackProtocolList: Auto |
|||
ObjCBlockIndentWidth: 2 |
|||
ObjCBreakBeforeNestedBlockParam: true |
|||
ObjCSpaceAfterProperty: false |
|||
ObjCSpaceBeforeProtocolList: true |
|||
PenaltyBreakAssignment: 2 |
|||
PenaltyBreakBeforeFirstCallParameter: 19 |
|||
PenaltyBreakComment: 300 |
|||
PenaltyBreakFirstLessLess: 120 |
|||
PenaltyBreakOpenParenthesis: 0 |
|||
PenaltyBreakString: 1000 |
|||
PenaltyBreakTemplateDeclaration: 10 |
|||
PenaltyExcessCharacter: 1000000 |
|||
PenaltyReturnTypeOnItsOwnLine: 60 |
|||
PenaltyIndentedWhitespace: 0 |
|||
PointerAlignment: Right |
|||
PPIndentWidth: -1 |
|||
ReferenceAlignment: Pointer |
|||
ReflowComments: true |
|||
RemoveBracesLLVM: false |
|||
SeparateDefinitionBlocks: Leave |
|||
ShortNamespaceLines: 1 |
|||
SortIncludes: CaseSensitive |
|||
SortJavaStaticImport: Before |
|||
SortUsingDeclarations: true |
|||
SpaceAfterCStyleCast: false |
|||
SpaceAfterLogicalNot: false |
|||
SpaceAfterTemplateKeyword: true |
|||
SpaceBeforeAssignmentOperators: true |
|||
SpaceBeforeCaseColon: false |
|||
SpaceBeforeCpp11BracedList: false |
|||
SpaceBeforeCtorInitializerColon: true |
|||
SpaceBeforeInheritanceColon: true |
|||
SpaceBeforeParens: ControlStatements |
|||
SpaceBeforeParensOptions: |
|||
AfterControlStatements: true |
|||
AfterForeachMacros: true |
|||
AfterFunctionDefinitionName: false |
|||
AfterFunctionDeclarationName: false |
|||
AfterIfMacros: true |
|||
AfterOverloadedOperator: false |
|||
BeforeNonEmptyParentheses: false |
|||
SpaceAroundPointerQualifiers: Default |
|||
SpaceBeforeRangeBasedForLoopColon: true |
|||
SpaceInEmptyBlock: false |
|||
SpaceInEmptyParentheses: false |
|||
SpacesBeforeTrailingComments: 1 |
|||
SpacesInAngles: Never |
|||
SpacesInConditionalStatement: false |
|||
SpacesInContainerLiterals: true |
|||
SpacesInCStyleCastParentheses: false |
|||
SpacesInLineCommentPrefix: |
|||
Minimum: 1 |
|||
Maximum: -1 |
|||
SpacesInParentheses: false |
|||
SpacesInSquareBrackets: false |
|||
SpaceBeforeSquareBrackets: false |
|||
BitFieldColonSpacing: Both |
|||
Standard: Latest |
|||
StatementAttributeLikeMacros: |
|||
- Q_EMIT |
|||
StatementMacros: |
|||
- Q_UNUSED |
|||
- QT_REQUIRE_VERSION |
|||
TabWidth: 4 |
|||
UseCRLF: false |
|||
UseTab: Never |
|||
WhitespaceSensitiveMacros: |
|||
- STRINGIZE |
|||
- PP_STRINGIZE |
|||
- BOOST_PP_STRINGIZE |
|||
- NS_SWIFT_NAME |
|||
- CF_SWIFT_NAME |
|||
... |
|||
|
@ -0,0 +1,10 @@ |
|||
* |
|||
!srcs/*/*.cpp |
|||
!srcs/*/*.hpp |
|||
!srcs/*.hpp |
|||
!srcs/*.cpp |
|||
!Makefile |
|||
!LICENCE |
|||
!README.md |
|||
!default.json |
|||
!.gitignore |
@ -1,12 +0,0 @@ |
|||
|
|||
server { |
|||
listen 80; |
|||
server_name localhost; |
|||
|
|||
root datas; |
|||
location /site { |
|||
root datas/website; |
|||
index index.html; |
|||
try_files $uri /$uri =404; |
|||
} |
|||
} |
@ -1,32 +0,0 @@ |
|||
{ |
|||
"max_clients": 30, |
|||
"servers": |
|||
[ |
|||
{ |
|||
"listen": ["80", "[::]:80"], |
|||
"server_name": "localhost", |
|||
"return": "301 https://$host$uri" |
|||
|
|||
}, |
|||
{ |
|||
"listen": ["443", "[::]:443"], |
|||
"server_name": "localhost", |
|||
"root": "datas", |
|||
"locations": |
|||
{ |
|||
"/site": |
|||
{ |
|||
"root": "datas/website", |
|||
"index": ["index.html", "index.php"], |
|||
"try_files": "$uri /$uri =404" |
|||
}, |
|||
"/img": |
|||
{ |
|||
"index": ["datas/gallery.html"], |
|||
"autoindex": true |
|||
}, |
|||
"/": {"return": "404"} |
|||
} |
|||
} |
|||
] |
|||
} |
Binary file not shown.
@ -1,131 +0,0 @@ |
|||
#include <iostream> |
|||
#include <map> |
|||
#include <sstream> |
|||
#include <string> |
|||
#include <vector> |
|||
|
|||
#define DEBUG 0 |
|||
|
|||
using std::cout; |
|||
using std::string; |
|||
|
|||
class JSONNode; |
|||
typedef std::map<string, JSONNode *> JSONObject; |
|||
typedef std::vector<JSONNode *> JSONList; |
|||
|
|||
class JSONNode { |
|||
public: |
|||
JSONObject obj() { |
|||
if (type == OBJECT) |
|||
return *values.object; |
|||
throw std::logic_error("Improper return"); |
|||
} |
|||
JSONList lst() { |
|||
if (type == LIST) |
|||
return *values.list; |
|||
throw std::logic_error("Improper return"); |
|||
} |
|||
string str() { |
|||
if (type == STRING) |
|||
return *values.str; |
|||
throw std::logic_error("Improper return"); |
|||
} |
|||
int nbr() { |
|||
if (type == NUMBER) |
|||
return values.nbr; |
|||
throw std::logic_error("Improper return"); |
|||
} |
|||
|
|||
private: |
|||
enum Type { OBJECT, LIST, STRING, NUMBER, BOOLEAN, NULL_TYPE }; |
|||
union Values { |
|||
JSONObject *object; |
|||
JSONList *list; |
|||
string *str; |
|||
int nbr; |
|||
bool bValue; |
|||
} values; |
|||
Type type; |
|||
|
|||
void setObject(JSONObject *object) { |
|||
this->values.object = object; |
|||
type = OBJECT; |
|||
} |
|||
void setList(JSONList *list) { |
|||
this->values.list = list; |
|||
type = LIST; |
|||
} |
|||
void setString(string *str) { |
|||
this->values.str = str; |
|||
type = STRING; |
|||
} |
|||
void setNumber(int nbr) { |
|||
this->values.nbr = nbr; |
|||
type = NUMBER; |
|||
} |
|||
void setBoolean(bool v) { |
|||
this->values.bValue = v; |
|||
type = BOOLEAN; |
|||
} |
|||
void setNull() { type = NULL_TYPE; } |
|||
|
|||
string stringify(int indentationLevel) { |
|||
string spaceString = string(indentationLevel, ' '); |
|||
// sstreams
|
|||
std::stringstream output; |
|||
// cout < type << "\n";
|
|||
switch (type) { |
|||
case STRING: { |
|||
output << spaceString << *values.str; |
|||
break; |
|||
} |
|||
case NUMBER: { |
|||
output << spaceString << values.nbr; |
|||
break; |
|||
} |
|||
case BOOLEAN: { |
|||
output << spaceString << (values.bValue ? "true" : "false"); |
|||
break; |
|||
} |
|||
case NULL_TYPE: { |
|||
output << spaceString << "null"; |
|||
break; |
|||
} |
|||
case LIST: { |
|||
// cout << "[";
|
|||
output << spaceString << "[\n"; |
|||
unsigned int index = 0; |
|||
for (JSONList::iterator i = (*values.list).begin(); |
|||
i != (*values.list).end(); i++) { |
|||
output << (*i)->stringify(indentationLevel + 1); |
|||
if (index < (*values.list).size() - 1) { |
|||
output << ",\n"; |
|||
} |
|||
index++; |
|||
}; |
|||
output << "\n" << spaceString << "]\n"; |
|||
break; |
|||
} |
|||
case OBJECT: { |
|||
output << spaceString << "{\n"; |
|||
for (JSONObject::iterator i = (*values.object).begin(); |
|||
i != (*values.object).end(); i++) { |
|||
output << spaceString << " " |
|||
<< "\"" << i->first << "\"" |
|||
<< ": "; |
|||
output << i->second->stringify(indentationLevel + 1); |
|||
JSONObject::iterator next = i; |
|||
next++; |
|||
if ((next) != (*values.object).end()) { |
|||
output << ",\n"; |
|||
} |
|||
output << spaceString << "\n"; |
|||
} |
|||
output << spaceString << "}"; |
|||
return output.str(); |
|||
} |
|||
} |
|||
return output.str(); |
|||
} |
|||
friend class JSONParser; |
|||
}; |
@ -1,213 +0,0 @@ |
|||
#include "Token.hpp" |
|||
#include <cstdlib> |
|||
|
|||
class JSONParser { |
|||
std::fstream file; |
|||
JSONNode *root; |
|||
JSONNode *current; |
|||
Tokenizer tokenizer; |
|||
|
|||
public: |
|||
JSONParser(const string filename) : tokenizer(filename) {} |
|||
JSONNode *parse() { |
|||
string key = ""; |
|||
JSONNode *parsed; |
|||
while (tokenizer.hasMoreTokens()) { |
|||
Token token; |
|||
try { |
|||
token = tokenizer.getToken(); |
|||
switch (token.type) { |
|||
case CURLY_OPEN: { |
|||
parsed = parseObject(); |
|||
break; |
|||
} |
|||
case ARRAY_OPEN: { |
|||
parsed = parseList(); |
|||
break; |
|||
} |
|||
case STRING: { |
|||
tokenizer.rollBackToken(); |
|||
parsed = parseString(); |
|||
break; |
|||
} |
|||
case NUMBER: { |
|||
tokenizer.rollBackToken(); |
|||
parsed = parseNumber(); |
|||
break; |
|||
} |
|||
case BOOLEAN: { |
|||
tokenizer.rollBackToken(); |
|||
parsed = parseBoolean(); |
|||
break; |
|||
} |
|||
default: |
|||
break; |
|||
} |
|||
} catch (std::logic_error &e) { |
|||
break; |
|||
} |
|||
} |
|||
return parsed; |
|||
} |
|||
|
|||
JSONNode *parseObject() { |
|||
JSONNode *node = new JSONNode; |
|||
JSONObject *keyObjectMap = new JSONObject; |
|||
while (1) { |
|||
if (tokenizer.hasMoreTokens()) { |
|||
Token token = tokenizer.getToken(); |
|||
string key = token.value; |
|||
tokenizer.getToken(); |
|||
token = tokenizer.getToken(); |
|||
switch (token.type) { |
|||
case CURLY_OPEN: { |
|||
if (DEBUG) |
|||
cout << "=object=|" << key << "|===>>\n"; |
|||
(*keyObjectMap)[key] = parseObject(); |
|||
if (DEBUG) |
|||
cout << "<<===end object\n"; |
|||
break; |
|||
} |
|||
case ARRAY_OPEN: { |
|||
if (DEBUG) |
|||
cout << "-list-|" << key << "|--->>\n"; |
|||
(*keyObjectMap)[key] = parseList(); |
|||
if (DEBUG) |
|||
cout << "<<---end list\n"; |
|||
break; |
|||
} |
|||
case STRING: { |
|||
tokenizer.rollBackToken(); |
|||
(*keyObjectMap)[key] = parseString(); |
|||
if (DEBUG) |
|||
cout << key << "='" << (*keyObjectMap)[key]->str() |
|||
<< "'\n"; |
|||
break; |
|||
} |
|||
case NUMBER: { |
|||
tokenizer.rollBackToken(); |
|||
(*keyObjectMap)[key] = parseNumber(); |
|||
if (DEBUG) |
|||
cout << key << "=" << (*keyObjectMap)[key]->nbr() |
|||
<< "\n"; |
|||
break; |
|||
} |
|||
case BOOLEAN: { |
|||
tokenizer.rollBackToken(); |
|||
(*keyObjectMap)[key] = parseBoolean(); |
|||
if (DEBUG) |
|||
cout << key << "(BOOL)\n"; |
|||
break; |
|||
} |
|||
case NULL_TYPE: { |
|||
(*keyObjectMap)[key] = parseNull(); |
|||
break; |
|||
} |
|||
default: |
|||
break; |
|||
} |
|||
token = tokenizer.getToken(); |
|||
if (token.type == CURLY_CLOSE) |
|||
break; |
|||
|
|||
} else { |
|||
throw std::logic_error("No more tokens"); |
|||
} |
|||
} |
|||
node->setObject(keyObjectMap); |
|||
return node; |
|||
} |
|||
|
|||
JSONNode *parseList() { |
|||
JSONNode *node = new JSONNode(); |
|||
JSONList *list = new JSONList(); |
|||
bool hasCompleted = false; |
|||
while (!hasCompleted) { |
|||
if (!tokenizer.hasMoreTokens()) { |
|||
throw std::logic_error("No more tokens"); |
|||
} else { |
|||
Token token = tokenizer.getToken(); |
|||
JSONNode *subNode; |
|||
switch (token.type) { |
|||
case CURLY_OPEN: { |
|||
if (DEBUG) |
|||
cout << "=object===>>\n"; |
|||
subNode = parseObject(); |
|||
if (DEBUG) |
|||
cout << "<<===end object\n"; |
|||
break; |
|||
} |
|||
case ARRAY_OPEN: { |
|||
if (DEBUG) |
|||
cout << "-list--->>\n"; |
|||
subNode = parseList(); |
|||
if (DEBUG) |
|||
cout << "<<---end list\n"; |
|||
break; |
|||
} |
|||
case STRING: { |
|||
tokenizer.rollBackToken(); |
|||
subNode = parseString(); |
|||
if (DEBUG) |
|||
cout << "|'" << subNode->str() << "'"; |
|||
break; |
|||
} |
|||
case NUMBER: { |
|||
tokenizer.rollBackToken(); |
|||
subNode = parseNumber(); |
|||
if (DEBUG) |
|||
cout << "|" << subNode->nbr(); |
|||
break; |
|||
} |
|||
case BOOLEAN: { |
|||
tokenizer.rollBackToken(); |
|||
subNode = parseBoolean(); |
|||
break; |
|||
} |
|||
case NULL_TYPE: { |
|||
subNode = parseNull(); |
|||
break; |
|||
} |
|||
default: |
|||
break; |
|||
} |
|||
list->push_back(subNode); |
|||
token = tokenizer.getToken(); |
|||
if (token.type == ARRAY_CLOSE) { |
|||
hasCompleted = true; |
|||
} |
|||
} |
|||
} |
|||
node->setList(list); |
|||
return node; |
|||
} |
|||
|
|||
JSONNode *parseString() { |
|||
JSONNode *node = new JSONNode(); |
|||
Token token = tokenizer.getToken(); |
|||
string *sValue = new string(token.value); |
|||
node->setString(sValue); |
|||
return node; |
|||
} |
|||
|
|||
JSONNode *parseNumber() { |
|||
JSONNode *node = new JSONNode(); |
|||
Token token = tokenizer.getToken(); |
|||
string value = token.value; |
|||
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); |
|||
return node; |
|||
} |
|||
|
|||
JSONNode *parseNull() { |
|||
JSONNode *node = new JSONNode(); |
|||
node->setNull(); |
|||
return node; |
|||
} |
|||
}; |
@ -1,159 +0,0 @@ |
|||
#include "Nodes.hpp" |
|||
#include <fstream> |
|||
|
|||
enum TOKEN { |
|||
CURLY_OPEN, |
|||
CURLY_CLOSE, |
|||
COLON, |
|||
STRING, |
|||
NUMBER, |
|||
ARRAY_OPEN, |
|||
ARRAY_CLOSE, |
|||
COMMA, |
|||
BOOLEAN, |
|||
NULL_TYPE |
|||
}; |
|||
|
|||
typedef struct Token_s { |
|||
string value; |
|||
TOKEN type; |
|||
string toString() { |
|||
switch (type) { |
|||
case CURLY_OPEN: { |
|||
return "Curly open"; |
|||
} |
|||
case CURLY_CLOSE: { |
|||
return "Curly close"; |
|||
} |
|||
case COLON: { |
|||
return "COLON"; |
|||
} |
|||
case NUMBER: { |
|||
return "Number: " + value; |
|||
} |
|||
case STRING: { |
|||
return "String: " + value; |
|||
} |
|||
|
|||
case ARRAY_OPEN: { |
|||
return "Array open"; |
|||
} |
|||
case ARRAY_CLOSE: { |
|||
return "Array close"; |
|||
} |
|||
case COMMA: { |
|||
return "Comma"; |
|||
} |
|||
case BOOLEAN: { |
|||
return "Boolean: " + value; |
|||
} |
|||
|
|||
case NULL_TYPE: { |
|||
return "Null"; |
|||
} |
|||
default: |
|||
return "Other..."; |
|||
} |
|||
} |
|||
} Token; |
|||
|
|||
class Tokenizer { |
|||
std::fstream file; |
|||
size_t prevPos; |
|||
|
|||
public: |
|||
Tokenizer(string fileName) { |
|||
file.open(fileName.c_str(), std::ios::in); |
|||
if (!file.good()) |
|||
cout << "File open error" |
|||
<< "\n"; |
|||
}; |
|||
bool hasMoreTokens() { return !file.eof(); } |
|||
char getWithoutWhiteSpace() { |
|||
char c = ' '; |
|||
while ((c == ' ' || c == '\n') || c == '\t') { |
|||
file.get(c); // check
|
|||
|
|||
if ((c == ' ' || c == '\n') && !file.good()) { |
|||
// cout << file.eof() << " " << file.fail() << "\n";
|
|||
throw std::logic_error("Ran out of tokens"); |
|||
} else if (!file.good()) { |
|||
return c; |
|||
} |
|||
} |
|||
|
|||
return c; |
|||
}; |
|||
void rollBackToken() { |
|||
if (file.eof()) |
|||
file.clear(); |
|||
file.seekg(prevPos); |
|||
}; |
|||
Token getToken() { |
|||
char c; |
|||
if (file.eof()) { |
|||
cout << "Exhaused tokens" |
|||
<< "\n"; |
|||
// throw std::exception("Exhausted tokens");
|
|||
} |
|||
prevPos = file.tellg(); |
|||
c = getWithoutWhiteSpace(); |
|||
|
|||
Token token; |
|||
token.type = NULL_TYPE; |
|||
if (c == '"') { |
|||
token.type = STRING; |
|||
token.value = ""; |
|||
file.get(c); |
|||
while (c != '"') { |
|||
token.value += c; |
|||
file.get(c); |
|||
} |
|||
} else if (c == '{') { |
|||
token.type = CURLY_OPEN; |
|||
} else if (c == '}') { |
|||
token.type = CURLY_CLOSE; |
|||
} else if (c == '-' || (c >= '0' && c <= '9')) { |
|||
// Check if string is numeric
|
|||
token.type = NUMBER; |
|||
token.value = ""; |
|||
token.value += c; |
|||
std::streampos prevCharPos = file.tellg(); |
|||
while ((c == '-') || (c >= '0' && c <= '9') || c == '.') { |
|||
prevCharPos = file.tellg(); |
|||
file.get(c); |
|||
|
|||
if (file.eof()) { |
|||
break; |
|||
} else { |
|||
if ((c == '-') || (c >= '0' && c <= '9') || (c == '.')) { |
|||
token.value += c; |
|||
} else { |
|||
file.seekg(prevCharPos); |
|||
} |
|||
} |
|||
} |
|||
} else if (c == 'f') { |
|||
token.type = BOOLEAN; |
|||
token.value = "False"; |
|||
file.seekg(4, std::ios_base::cur); |
|||
} else if (c == 't') { |
|||
token.type = BOOLEAN; |
|||
token.value = "True"; |
|||
file.seekg(3, std::ios_base::cur); |
|||
} else if (c == 'n') { |
|||
token.type = NULL_TYPE; |
|||
file.seekg(3, std::ios_base::cur); |
|||
} else if (c == '[') { |
|||
token.type = ARRAY_OPEN; |
|||
} else if (c == ']') { |
|||
token.type = ARRAY_CLOSE; |
|||
} else if (c == ':') { |
|||
token.type = COLON; |
|||
} else if (c == ',') { |
|||
token.type = COMMA; |
|||
} |
|||
// cout << token.type << " : " << token.value << "\n";
|
|||
return token; |
|||
}; |
|||
}; |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in new issue