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