From a5ebf986574bdcdad968962751d9ab8dbe90980d Mon Sep 17 00:00:00 2001 From: Ognyan Date: Sun, 18 Nov 2018 22:59:44 +0200 Subject: JSON is now parsed to AST --- JSImpl/src/JSONParser.cpp | 368 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 JSImpl/src/JSONParser.cpp (limited to 'JSImpl/src/JSONParser.cpp') diff --git a/JSImpl/src/JSONParser.cpp b/JSImpl/src/JSONParser.cpp new file mode 100644 index 0000000..13ad9d6 --- /dev/null +++ b/JSImpl/src/JSONParser.cpp @@ -0,0 +1,368 @@ +#include "JSONParser.h" +#include "ExpressionDefinitions.h" + +#include +#include + +void SkipWhitespaces(const char*& json) +{ + while (*json && (*json == ' ' || *json == '\t' || *json == '\n')) + { + ++json; + } +} + +inline void PassStringToVal(const char*& json, const char* name) +{ + SkipWhitespaces(json); + json += 1/*"*/ + strlen(name) + 3/*": */; +} + +inline void PassStringToString(const char*& json, const char* name) +{ + PassStringToVal(json, name); + ++json; //" +} + +inline void PassStringToArray(const char*& json, const char* name) +{ + PassStringToString(json, name); +} + +inline void PassStatementEnd(const char*& json, bool isLast) +{ + if (!isLast) + { + ++json; //, + } +} + +void JSONParse(const char*& json, const char* name, bool isLast, bool& value); +void JSONParse(const char*& json, const char* name, bool isLast, double& value); +void JSONParse(const char*& json, const char* name, bool isLast, IPLString& value); +void JSONParse(const char*& json, const char* name, bool isLast, TokenType& value); +void JSONParse(const char*& json, const char* name, bool isLast, ExpressionPtr& value); +void JSONParse(const char*& json, const char* name, bool isLast, IPLVector& value); +void JSONParse(const char*& json, const char* name, bool isLast, IPLVector& value); + +#define GENERATE_EXPRESSION_TYPE_ENUMS(ClassName, MEMBERS_ITERATOR) \ +enum class ClassName##Type : unsigned char \ +{ \ + Invalid \ +}; +EXPRESSION_DEFINITION_ITERATOR(GENERATE_EXPRESSION_TYPE_ENUMS); +#undef GENERATE_EXPRESSION_TYPE_ENUM_MEMBERS + +template +ExpressionPtr JSONParseWrap(const char*& json, const char* eName) +{ + assert(false); + return nullptr; +} + +#define MEMBERS_COUNT(type, name, def) \ + ++membersCount; + +#define VISIT_MEMBER(type, name, def) \ + ++currentVisitCount; \ + JSONParse(json, #name, currentVisitCount == membersCount, ptr->Get##name##ByRef()); \ + +#define GENERATE_JSON_PARSE_FUNCTION_DEFINITIONS(ClassName, MEMBERS_ITERATOR) \ +template <> \ +ExpressionPtr JSONParseWrap(const char*& json, const char* eName) \ +{ \ + auto ptr = IPLMakeSharePtr<::##ClassName>(); \ + int membersCount = 0, currentVisitCount = 0; \ + (void)currentVisitCount; \ + json += strlen("{"); \ + SkipWhitespaces(json); \ + json += strlen("\"ExpresionType\": \"") + strlen(eName) + strlen("\","); \ + SkipWhitespaces(json); \ + MEMBERS_ITERATOR(MEMBERS_COUNT); \ + SkipWhitespaces(json); \ + if (membersCount) \ + { \ + json += strlen(","); \ + } \ + SkipWhitespaces(json); \ + MEMBERS_ITERATOR(VISIT_MEMBER); \ + SkipWhitespaces(json); \ + json += strlen("}"); \ + return ptr; \ +} + +EXPRESSION_DEFINITION_ITERATOR(GENERATE_JSON_PARSE_FUNCTION_DEFINITIONS); +#undef GENERATE_JSON_PARSE_FUNCTION_DEFINITIONS +#undef MEMBERS_COUNT +#undef VISIT_MEMBER + +IPLString ReadExpressionType(const char* json) +{ + IPLString str; + + SkipWhitespaces(json); + ++json; //{ + SkipWhitespaces(json); + json += strlen("\"ExpressionType\": \""); + + while (*json != '"') + { + str += *json++; + } + + return str; +} + +#define EXPRESSION_PARSE_CALLER_CASES(ClassName, MEMBERS_ITERATOR) \ + if (type.compare(#ClassName) == 0) \ + return JSONParseWrap(json, #ClassName); + +ExpressionPtr ExpressionParseCaller(const IPLString& type, const char*& json) +{ + EXPRESSION_DEFINITION_ITERATOR(EXPRESSION_PARSE_CALLER_CASES); + + assert(false); + return nullptr; +} + +#undef EXPRESSION_PARSE_CALLER_CASES + +std::unordered_map GetTokenTable() +{ + std::unordered_map table; + table["LeftParen"] = TokenType::LeftParen; + table["RightParen"] = TokenType::RightParen; + table["LeftBrace"] = TokenType::LeftBrace; + table["RightBrace"] = TokenType::RightBrace; + table["Comma"] = TokenType::Comma; + table["Dot"] = TokenType::Dot; + table["Minus"] = TokenType::Minus; + table["Plus"] = TokenType::Plus; + table["Semicolon"] = TokenType::Semicolon; + table["Star"] = TokenType::Star; + table["Division"] = TokenType::Division; + table["Modulo"] = TokenType::Modulo; + table["BitwiseNot"] = TokenType::BitwiseNot; + table["BitwiseAnd"] = TokenType::BitwiseAnd; + table["BitwiseXor"] = TokenType::BitwiseXor; + table["BitwiseOr"] = TokenType::BitwiseOr; + table["QuestionMark"] = TokenType::QuestionMark; + table["Colon"] = TokenType::Colon; + table["LeftSquareBracket"] = TokenType::LeftSquareBracket; + table["RightSquareBracket"] = TokenType::RightSquareBracket; + table["Bang"] = TokenType::Bang; + table["BangEqual"] = TokenType::BangEqual; + table["Equal"] = TokenType::Equal; + table["EqualEqual"] = TokenType::EqualEqual; + table["StrictEqual"] = TokenType::StrictEqual; + table["StrictNotEqual"] = TokenType::StrictNotEqual; + table["Greater"] = TokenType::Greater; + table["GreaterEqual"] = TokenType::GreaterEqual; + table["Less"] = TokenType::Less; + table["LessEqual"] = TokenType::LessEqual; + table["MinusMinus"] = TokenType::MinusMinus; + table["PlusPlus"] = TokenType::PlusPlus; + table["LeftShift"] = TokenType::LeftShift; + table["RightShift"] = TokenType::RightShift; + table["LogicalAnd"] = TokenType::LogicalAnd; + table["LogicalOr"] = TokenType::LogicalOr; + table["StarEqual"] = TokenType::StarEqual; + table["DivideEqual"] = TokenType::DivideEqual; + table["ModuloEqual"] = TokenType::ModuloEqual; + table["PlusEqual"] = TokenType::PlusEqual; + table["MinusEqual"] = TokenType::MinusEqual; + table["LeftShiftEqual"] = TokenType::LeftShiftEqual; + table["RightShiftEqual"] = TokenType::RightShiftEqual; + table["BitwiseAndEqual"] = TokenType::BitwiseAndEqual; + table["BitwiseXorEqual"] = TokenType::BitwiseXorEqual; + table["BitwiseOrEqual"] = TokenType::BitwiseOrEqual; + table["Identifier"] = TokenType::Identifier; + table["String"] = TokenType::String; + table["Number"] = TokenType::Number; + table["Break"] = TokenType::Break; + table["Case"] = TokenType::Case; + table["Catch"] = TokenType::Catch; + table["Class"] = TokenType::Class; + table["Const"] = TokenType::Const; + table["Continue"] = TokenType::Continue; + table["Debugger"] = TokenType::Debugger; + table["Default"] = TokenType::Default; + table["Delete"] = TokenType::Delete; + table["Do"] = TokenType::Do; + table["Else"] = TokenType::Else; + table["Export"] = TokenType::Export; + table["Extends"] = TokenType::Extends; + table["Finally"] = TokenType::Finally; + table["For"] = TokenType::For; + table["Function"] = TokenType::Function; + table["If"] = TokenType::If; + table["Import"] = TokenType::Import; + table["In"] = TokenType::In; + table["Instanceof"] = TokenType::Instanceof; + table["New"] = TokenType::New; + table["Return"] = TokenType::Return; + table["Super"] = TokenType::Super; + table["Switch"] = TokenType::Switch; + table["This"] = TokenType::This; + table["Throw"] = TokenType::Throw; + table["Try"] = TokenType::Try; + table["Typeof"] = TokenType::Typeof; + table["Var"] = TokenType::Var; + table["Void"] = TokenType::Void; + table["While"] = TokenType::While; + table["With"] = TokenType::With; + table["Yield"] = TokenType::Yield; + table["Null"] = TokenType::Null; + table["Undefined"] = TokenType::Undefined; + table["True"] = TokenType::True; + table["False"] = TokenType::False; + table["Eof"] = TokenType::Eof; + return table; +} + +TokenType StringToToken(IPLString str) +{ + static const auto table = GetTokenTable(); + + auto it = table.find(str); + if (it == table.end()) + { + assert(false); + return TokenType::Invalid; + } + + return it->second; +} + +void JSONParse(const char*& json, const char* name, bool isLast, bool& value) +{ + PassStringToVal(json, name); + + if (*json == '1') + { + value = true; + } + else + { + value = false; + } + + ++json; + + PassStatementEnd(json, isLast); +} + +void JSONParse(const char*& json, const char* name, bool isLast, double& value) +{ + PassStringToVal(json, name); + + value = atof(json); + + while ((*json >= '0' && *json <= '9') || *json == '.') + { + ++json; + } + + PassStatementEnd(json, isLast); +} + +void JSONParse(const char*& json, const char* name, bool isLast, IPLString& value) +{ + PassStringToString(json, name); + + while (*json != '"') + { + value += *json++; + } + + ++json; //" + + PassStatementEnd(json, isLast); +} + +void JSONParse(const char*& json, const char* name, bool isLast, TokenType& value) +{ + PassStringToString(json, name); + + IPLString str; + while (*json != '"') + { + str += *json++; + } + + value = StringToToken(str.c_str()); + + ++json; //" + + PassStatementEnd(json, isLast); +} + +void JSONParse(const char*& json, const char* name, bool isLast, ExpressionPtr& value) +{ + PassStringToVal(json, name); + + const IPLString& type = ReadExpressionType(json); + value = ExpressionParseCaller(type, json); + + PassStatementEnd(json, isLast); +} + +void JSONParse(const char*& json, const char* name, bool isLast, IPLVector& value) +{ + PassStringToArray(json, name); + + while (true) + { + SkipWhitespaces(json); + if (*json == ']') + { + ++json; + PassStatementEnd(json, isLast); + return; + } + + const IPLString& type = ReadExpressionType(json); + value.push_back(ExpressionParseCaller(type, json)); + + if (*json == ',') + { + ++json; + } + } +} + +void JSONParse(const char*& json, const char* name, bool isLast, IPLVector& value) +{ + PassStringToArray(json, name); + + while (true) + { + SkipWhitespaces(json); + if (*json == ']') + { + ++json; + PassStatementEnd(json, isLast); + return; + } + + value.push_back(IPLString()); + + ++json; + while (*json != '"') + { + value.back() += *json; + ++json; + } + ++json; + + if (*json == ',') + { + ++json; + } + } +} + +ExpressionPtr ParseJSON(const char* json) +{ + return JSONParseWrap(json, "TopStatements"); +} -- cgit v1.3.1-23-gd82d