parent
							
								
									2ea548678b
								
							
						
					
					
						commit
						fc90bfb982
					
				
				 9 changed files with 630 additions and 3 deletions
			
			
		@ -0,0 +1,144 @@ | 
				
			|||||||
 | 
					#include "json_lexer.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Bk::Json 
 | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    std::string Token::to_string() | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        return Tools::string_format("%s %d", this->value, (int)this->type); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    char Lexer::get_next_char() | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        char c = data.pull<char>(); | 
				
			||||||
 | 
					        return c; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool Lexer::has_more_tokens() | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        return (bool)data.size(); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char Lexer::get_without_white_space() | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        char c = ' '; | 
				
			||||||
 | 
					        while ((c == ' ' || c == '\n')) | 
				
			||||||
 | 
					        { | 
				
			||||||
 | 
					            c = get_next_char(); // check
 | 
				
			||||||
 | 
					            if ((c == ' ' || c == '\n') && !data.size()) | 
				
			||||||
 | 
					            { | 
				
			||||||
 | 
					                throw std::logic_error("Ran out of tokens"); | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					            else if (!data.size()) | 
				
			||||||
 | 
					            { | 
				
			||||||
 | 
					                return c; | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        return c; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Token Lexer::get_token() | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        char c; | 
				
			||||||
 | 
					        if (!data.size()) | 
				
			||||||
 | 
					        { | 
				
			||||||
 | 
					            throw std::logic_error("Exhausted tokens"); | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        c = get_without_white_space(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Token token; | 
				
			||||||
 | 
					        if (c == '"') | 
				
			||||||
 | 
					        { | 
				
			||||||
 | 
					            token.type = TokenType::STRING; | 
				
			||||||
 | 
					            token.value = ""; | 
				
			||||||
 | 
					            c = get_next_char(); | 
				
			||||||
 | 
					            while (c != '"') | 
				
			||||||
 | 
					            { | 
				
			||||||
 | 
					                token.value += c; | 
				
			||||||
 | 
					                c = get_next_char(); | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        else if (c == '{') | 
				
			||||||
 | 
					        { | 
				
			||||||
 | 
					            token.type = TokenType::CURLY_OPEN; | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        else if (c == '}') | 
				
			||||||
 | 
					        { | 
				
			||||||
 | 
					            token.type = TokenType::CURLY_CLOSE; | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        else if (c=='-' || (c >= '0' && c <= '9')) | 
				
			||||||
 | 
					        { | 
				
			||||||
 | 
					            token.type = TokenType::NUMBER; | 
				
			||||||
 | 
					            token.value = ""; | 
				
			||||||
 | 
					            token.value += c; | 
				
			||||||
 | 
					            while ((c=='-')||(c >= '0' && c <= '9') || c == '.') | 
				
			||||||
 | 
					            { | 
				
			||||||
 | 
					                c = get_next_char(); | 
				
			||||||
 | 
					                if (!data.size()) | 
				
			||||||
 | 
					                { | 
				
			||||||
 | 
					                    break; | 
				
			||||||
 | 
					                } | 
				
			||||||
 | 
					                else | 
				
			||||||
 | 
					                { | 
				
			||||||
 | 
					                    if ((c=='-')||(c >= '0' && c <= '9')||(c=='.')) | 
				
			||||||
 | 
					                    { | 
				
			||||||
 | 
					                        token.value += c; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                    else if (c == ',') | 
				
			||||||
 | 
					                    { | 
				
			||||||
 | 
					                        roll_back_char(c); | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                    else if (c == '\n') break; | 
				
			||||||
 | 
					                    else | 
				
			||||||
 | 
					                    { | 
				
			||||||
 | 
					                        throw std::logic_error("Bad Numeric format"); | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                } | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        else if(c=='f'){ | 
				
			||||||
 | 
					            token.type = TokenType::BOOLEAN; | 
				
			||||||
 | 
					            token.value = "false"; | 
				
			||||||
 | 
					            data.pull<char>(4); | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        else if(c=='t'){ | 
				
			||||||
 | 
					            token.type = TokenType::BOOLEAN; | 
				
			||||||
 | 
					            token.value = "true"; | 
				
			||||||
 | 
					            data.pull<char>(3); | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        else if(c=='n'){ | 
				
			||||||
 | 
					            token.type = TokenType::NULL_TYPE; | 
				
			||||||
 | 
					            token.value = "null"; | 
				
			||||||
 | 
					            data.pull<char>(3); | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        else if (c == '[') | 
				
			||||||
 | 
					        { | 
				
			||||||
 | 
					            token.type = TokenType::ARRAY_OPEN; | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        else if (c == ']') | 
				
			||||||
 | 
					        { | 
				
			||||||
 | 
					            token.type = TokenType::ARRAY_CLOSE; | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        else if (c == ':') | 
				
			||||||
 | 
					        { | 
				
			||||||
 | 
					            token.type = TokenType::COLON; | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        else if (c == ',') | 
				
			||||||
 | 
					        { | 
				
			||||||
 | 
					            token.type = TokenType::COMMA; | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        lexed_token.push_back(token); | 
				
			||||||
 | 
					        return token; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Token Lexer::roll_back_token() | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        auto token = lexed_token.back(); | 
				
			||||||
 | 
					        return token; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Lexer::roll_back_char(char c) | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        data.push<char>(c); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,52 @@ | 
				
			|||||||
 | 
					#pragma once | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <bakatoolspch.h> | 
				
			||||||
 | 
					#include <bakatools/file_system/file.h> | 
				
			||||||
 | 
					#include <bakatools/container/data_stream.h> | 
				
			||||||
 | 
					#include <bakatools/string/format.h> | 
				
			||||||
 | 
					#include <bakatools/logging/log.h> | 
				
			||||||
 | 
					#include "json_node.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Bk::Json 
 | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    enum class TokenType | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        CURLY_OPEN, | 
				
			||||||
 | 
					        CURLY_CLOSE, | 
				
			||||||
 | 
					        COLON, | 
				
			||||||
 | 
					        STRING, | 
				
			||||||
 | 
					        NUMBER, | 
				
			||||||
 | 
					        ARRAY_OPEN, | 
				
			||||||
 | 
					        ARRAY_CLOSE, | 
				
			||||||
 | 
					        COMMA, | 
				
			||||||
 | 
					        BOOLEAN, | 
				
			||||||
 | 
					        NULL_TYPE | 
				
			||||||
 | 
					    }; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct Token | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        std::string value; | 
				
			||||||
 | 
					        TokenType type; | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        std::string to_string(); | 
				
			||||||
 | 
					    }; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Lexer | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        std::vector<Token> lexed_token; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public: | 
				
			||||||
 | 
					            Lexer() {} | 
				
			||||||
 | 
					            Lexer(Type::DataStream data) | 
				
			||||||
 | 
					            : data(data) {} | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Type::DataStream data; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            char get_next_char(); | 
				
			||||||
 | 
					            char get_without_white_space(); | 
				
			||||||
 | 
					            Token get_token(); | 
				
			||||||
 | 
					            bool has_more_tokens(); | 
				
			||||||
 | 
					            Token roll_back_token(); | 
				
			||||||
 | 
					            void roll_back_char(char c); | 
				
			||||||
 | 
					    }; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,78 @@ | 
				
			|||||||
 | 
					#include "json_node.h" | 
				
			||||||
 | 
					namespace Bk::Json 
 | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    void Node::set_object(Object *object) 
 | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        values.object = object; | 
				
			||||||
 | 
					        type = Type::OBJECT; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Object Node::get_object() | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        if (type == Type::OBJECT) 
 | 
				
			||||||
 | 
					            return *values.object; | 
				
			||||||
 | 
					        throw std::logic_error("Improper return"); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Node::set_list(List* list) | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        values.list = list; | 
				
			||||||
 | 
					        type = Type::LIST; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    List Node::get_list() | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        if (type == Type::LIST) 
 | 
				
			||||||
 | 
					            return *values.list; | 
				
			||||||
 | 
					        throw std::logic_error("Improper return"); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Node::set_string(std::string* str) | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        values.s = str; | 
				
			||||||
 | 
					        type = Type::STRING; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::string Node::get_string() | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        if (type == Type::STRING) 
 | 
				
			||||||
 | 
					            return *values.s; | 
				
			||||||
 | 
					        throw std::logic_error("Improper return"); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Node::set_bool(bool value) | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        values.bValue = value; | 
				
			||||||
 | 
					        type = Type::BOOLEAN; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool Node::get_bool() | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        if (type == Type::BOOLEAN) 
 | 
				
			||||||
 | 
					            return values.bValue; | 
				
			||||||
 | 
					        throw std::logic_error("Improper return"); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Node::set_float(float value) | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        values.fValue = value; | 
				
			||||||
 | 
					        type = Type::NUMBER; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    float Node::get_float() | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        if (type == Type::NUMBER) 
 | 
				
			||||||
 | 
					            return values.fValue; | 
				
			||||||
 | 
					        throw std::logic_error("Improper return"); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    void Node::set_null() | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        type = Type::NULL_TYPE; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    bool Node::is_null() | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        return type == Type::NULL_TYPE; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,53 @@ | 
				
			|||||||
 | 
					#pragma once | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <bakatoolspch.h> | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Bk::Json | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    class Node; | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    using Object = std::map<std::string, std::shared_ptr<Node>>; | 
				
			||||||
 | 
					    using List = std::vector<std::shared_ptr<Node>>; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Node 
 | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        public: | 
				
			||||||
 | 
					            enum class Type 
 | 
				
			||||||
 | 
					            { 
 | 
				
			||||||
 | 
					                OBJECT, 
 | 
				
			||||||
 | 
					                LIST, 
 | 
				
			||||||
 | 
					                STRING, 
 | 
				
			||||||
 | 
					                NUMBER, 
 | 
				
			||||||
 | 
					                BOOLEAN, 
 | 
				
			||||||
 | 
					                NULL_TYPE | 
				
			||||||
 | 
					            }; 
 | 
				
			||||||
 | 
					            void set_object(Object* object); | 
				
			||||||
 | 
					            Object get_object(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void set_list(List* list); | 
				
			||||||
 | 
					            List get_list(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void set_string(std::string* str); | 
				
			||||||
 | 
					            std::string get_string(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void set_bool(bool value); | 
				
			||||||
 | 
					            bool get_bool(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void set_float(float value); | 
				
			||||||
 | 
					            float get_float(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            void set_null(); | 
				
			||||||
 | 
					            bool is_null(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private: | 
				
			||||||
 | 
					            union Values { | 
				
			||||||
 | 
					                Object* object; | 
				
			||||||
 | 
					                List* list; | 
				
			||||||
 | 
					                std::string* s; | 
				
			||||||
 | 
					                float fValue; | 
				
			||||||
 | 
					                bool bValue; | 
				
			||||||
 | 
					            }; | 
				
			||||||
 | 
					            Values values; | 
				
			||||||
 | 
					            Type type; | 
				
			||||||
 | 
					    }; | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,264 @@ | 
				
			|||||||
 | 
					#include "json_parser.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Bk::Json | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    Parser::Parser(File& file) | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        Type::DataStream data; | 
				
			||||||
 | 
					        if (file.exists()) | 
				
			||||||
 | 
					        { | 
				
			||||||
 | 
					            data = file.read(file.size()); | 
				
			||||||
 | 
					            data.reverse(); | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        lexer = Lexer(data); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Parser::Parser(const char* str, int length) | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        Type::DataStream data; | 
				
			||||||
 | 
					        data.payload = std::vector<char>(str, str + length); | 
				
			||||||
 | 
					        data.reverse(); | 
				
			||||||
 | 
					        lexer = Lexer(data); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Parser::Parser(const std::string& str) | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        Type::DataStream data; | 
				
			||||||
 | 
					        data.payload = std::vector<char>(str.c_str(), str.c_str() + str.length()); | 
				
			||||||
 | 
					        data.reverse(); | 
				
			||||||
 | 
					        lexer = Lexer(data); | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<Json::Node> Parser::parse() 
 | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        Token token; | 
				
			||||||
 | 
					        while (lexer.has_more_tokens()) { | 
				
			||||||
 | 
					            try 
 | 
				
			||||||
 | 
					            { | 
				
			||||||
 | 
					                token = lexer.get_token(); | 
				
			||||||
 | 
					                switch (token.type) 
 | 
				
			||||||
 | 
					                { | 
				
			||||||
 | 
					                    case TokenType::CURLY_OPEN: 
 | 
				
			||||||
 | 
					                    { | 
				
			||||||
 | 
					                        std::shared_ptr<Json::Node> parsed_object = parse_object(); | 
				
			||||||
 | 
					                        if (!root) { | 
				
			||||||
 | 
					                            root = parsed_object; | 
				
			||||||
 | 
					                        } | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                    case TokenType::ARRAY_OPEN: { | 
				
			||||||
 | 
					                        std::shared_ptr<Json::Node> parsed_list = parse_list(); | 
				
			||||||
 | 
					                        if (!root) { | 
				
			||||||
 | 
					                            root = parsed_list; | 
				
			||||||
 | 
					                        } | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    case TokenType::STRING: { | 
				
			||||||
 | 
					                        
 | 
				
			||||||
 | 
					                        std::shared_ptr<Json::Node> parsed_string = parse_string(); | 
				
			||||||
 | 
					                        if (!root) { | 
				
			||||||
 | 
					                            root = parsed_string; | 
				
			||||||
 | 
					                        } | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                    case TokenType::NUMBER: { | 
				
			||||||
 | 
					                        std::shared_ptr<Json::Node> parsed_number = parse_number(); | 
				
			||||||
 | 
					                        if (!root) { | 
				
			||||||
 | 
					                            root = parsed_number; | 
				
			||||||
 | 
					                        } | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    case TokenType::BOOLEAN: { | 
				
			||||||
 | 
					                        std::shared_ptr<Json::Node> parsed_boolean = parse_boolean(); | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                } | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					            catch(std::logic_error e) | 
				
			||||||
 | 
					            { | 
				
			||||||
 | 
					                BK_INFO(e.what()); | 
				
			||||||
 | 
					                auto node = std::shared_ptr<Json::Node>(); | 
				
			||||||
 | 
					                node->set_null(); | 
				
			||||||
 | 
					                root = node; | 
				
			||||||
 | 
					                break; | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        return root; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<Json::Node> Parser::parse_list() 
 | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        std::shared_ptr<Json::Node> node = std::make_shared<Json::Node>(); | 
				
			||||||
 | 
					        Json::List *list = new Json::List(); | 
				
			||||||
 | 
					        bool has_completed = false; | 
				
			||||||
 | 
					        Token next_token; | 
				
			||||||
 | 
					        while (!has_completed) { | 
				
			||||||
 | 
					            if (!lexer.has_more_tokens()) 
 | 
				
			||||||
 | 
					            { | 
				
			||||||
 | 
					                throw std::logic_error("No more tokens"); | 
				
			||||||
 | 
					            } 
 | 
				
			||||||
 | 
					            else 
 | 
				
			||||||
 | 
					            { | 
				
			||||||
 | 
					                next_token = lexer.get_token(); | 
				
			||||||
 | 
					                if (next_token.type == TokenType::COLON || next_token.type == TokenType::COMMA) | 
				
			||||||
 | 
					                    continue; | 
				
			||||||
 | 
					                std::shared_ptr<Json::Node> node; | 
				
			||||||
 | 
					                switch (next_token.type) 
 | 
				
			||||||
 | 
					                { | 
				
			||||||
 | 
					                    case TokenType::ARRAY_OPEN: 
 | 
				
			||||||
 | 
					                    { | 
				
			||||||
 | 
					                        node = parse_list(); | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                    case TokenType::CURLY_OPEN: 
 | 
				
			||||||
 | 
					                    { | 
				
			||||||
 | 
					                        node = parse_object(); | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                    case TokenType::STRING: 
 | 
				
			||||||
 | 
					                    { | 
				
			||||||
 | 
					                        node = parse_string(); | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                    case TokenType::NUMBER: 
 | 
				
			||||||
 | 
					                    { | 
				
			||||||
 | 
					                        node = parse_number(); | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                    case TokenType::BOOLEAN: 
 | 
				
			||||||
 | 
					                    { | 
				
			||||||
 | 
					                        node = parse_boolean(); | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                    case TokenType::NULL_TYPE: { | 
				
			||||||
 | 
					                        node = parse_null(); | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                } | 
				
			||||||
 | 
					                list->push_back(node); | 
				
			||||||
 | 
					                if (next_token.type == TokenType::ARRAY_CLOSE) { | 
				
			||||||
 | 
					                    has_completed = true; | 
				
			||||||
 | 
					                } | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        node->set_list(list); | 
				
			||||||
 | 
					        return node; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<Json::Node> Parser::parse_object() 
 | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        std::string key = ""; | 
				
			||||||
 | 
					        std::shared_ptr<Json::Node> node = std::make_shared<Json::Node>(); | 
				
			||||||
 | 
					        Json::Object *key_object_map = new Json::Object(); | 
				
			||||||
 | 
					        bool has_completed = false; | 
				
			||||||
 | 
					        bool no_key = true; | 
				
			||||||
 | 
					        Token next_token; | 
				
			||||||
 | 
					        while (!has_completed) 
 | 
				
			||||||
 | 
					        { | 
				
			||||||
 | 
					            if (lexer.has_more_tokens()) 
 | 
				
			||||||
 | 
					            { | 
				
			||||||
 | 
					                if (no_key) | 
				
			||||||
 | 
					                { | 
				
			||||||
 | 
					                    next_token = lexer.get_token(); | 
				
			||||||
 | 
					                    if (next_token.type == TokenType::CURLY_CLOSE) 
 | 
				
			||||||
 | 
					                    { | 
				
			||||||
 | 
					                        has_completed = true; | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                    if (next_token.type == TokenType::COLON || next_token.type == TokenType::COMMA) | 
				
			||||||
 | 
					                        continue; | 
				
			||||||
 | 
					                    key = next_token.value; | 
				
			||||||
 | 
					                    no_key = false; | 
				
			||||||
 | 
					                } | 
				
			||||||
 | 
					                next_token = lexer.get_token(); | 
				
			||||||
 | 
					                if (next_token.type == TokenType::COLON || next_token.type == TokenType::COMMA) | 
				
			||||||
 | 
					                    continue; | 
				
			||||||
 | 
					                std::shared_ptr<Json::Node> node; | 
				
			||||||
 | 
					                switch (next_token.type) 
 | 
				
			||||||
 | 
					                { | 
				
			||||||
 | 
					                    case TokenType::STRING: 
 | 
				
			||||||
 | 
					                    { | 
				
			||||||
 | 
					                        (*key_object_map)[key] = parse_string(); | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                    case TokenType::ARRAY_OPEN: 
 | 
				
			||||||
 | 
					                    { | 
				
			||||||
 | 
					                        (*key_object_map)[key] = parse_list(); | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                    case TokenType::NUMBER: 
 | 
				
			||||||
 | 
					                    { | 
				
			||||||
 | 
					                        (*key_object_map)[key] = parse_number(); | 
				
			||||||
 | 
					                    break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                    case TokenType::CURLY_OPEN: 
 | 
				
			||||||
 | 
					                    { | 
				
			||||||
 | 
					                        (*key_object_map)[key] = parse_object(); | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                    case TokenType::BOOLEAN: 
 | 
				
			||||||
 | 
					                    { | 
				
			||||||
 | 
					                        (*key_object_map)[key] = parse_boolean(); | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                    case TokenType::NULL_TYPE: 
 | 
				
			||||||
 | 
					                    { | 
				
			||||||
 | 
					                        (*key_object_map)[key] = parse_null(); | 
				
			||||||
 | 
					                        break; | 
				
			||||||
 | 
					                    } | 
				
			||||||
 | 
					                } | 
				
			||||||
 | 
					                if (next_token.type == TokenType::CURLY_CLOSE) 
 | 
				
			||||||
 | 
					                { | 
				
			||||||
 | 
					                    has_completed = true; | 
				
			||||||
 | 
					                    break; | 
				
			||||||
 | 
					                } | 
				
			||||||
 | 
					                no_key = true; | 
				
			||||||
 | 
					                key = ""; | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					            else 
 | 
				
			||||||
 | 
					            { | 
				
			||||||
 | 
					                throw std::logic_error("No more tokens"); | 
				
			||||||
 | 
					            } | 
				
			||||||
 | 
					        } | 
				
			||||||
 | 
					        node->set_object(key_object_map); | 
				
			||||||
 | 
					        return node;    
 | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<Json::Node> Parser::parse_string() 
 | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        std::shared_ptr<Json::Node> node = std::make_shared<Json::Node>(); | 
				
			||||||
 | 
					        Token token = lexer.roll_back_token(); | 
				
			||||||
 | 
					        std::string *sValue = new std::string(token.value); | 
				
			||||||
 | 
					        node->set_string(sValue); | 
				
			||||||
 | 
					        return node; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<Json::Node> Parser::parse_number() 
 | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        std::shared_ptr<Json::Node> node = std::make_shared<Json::Node>(); | 
				
			||||||
 | 
					        Token token = lexer.roll_back_token(); | 
				
			||||||
 | 
					        float fValue = std::stof(token.value); | 
				
			||||||
 | 
					        node->set_float(fValue); | 
				
			||||||
 | 
					        return node; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<Json::Node> Parser::parse_boolean() 
 | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        std::shared_ptr<Json::Node> node = std::make_shared<Json::Node>(); | 
				
			||||||
 | 
					        Token token = lexer.roll_back_token(); | 
				
			||||||
 | 
					        bool bValue = token.value == "True" ? true : false; | 
				
			||||||
 | 
					        node->set_bool(bValue); | 
				
			||||||
 | 
					        return node; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<Json::Node> Parser::parse_null() 
 | 
				
			||||||
 | 
					    { | 
				
			||||||
 | 
					        std::shared_ptr<Json::Node> node = std::make_shared<Json::Node>(); | 
				
			||||||
 | 
					        Token token = lexer.roll_back_token(); | 
				
			||||||
 | 
					        node->set_null(); | 
				
			||||||
 | 
					        return node; | 
				
			||||||
 | 
					    } | 
				
			||||||
 | 
					} | 
				
			||||||
@ -0,0 +1,32 @@ | 
				
			|||||||
 | 
					#pragma once | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <bakatoolspch.h> | 
				
			||||||
 | 
					#include <bakatools/file_system/file.h> | 
				
			||||||
 | 
					#include <bakatools/container/data_stream.h> | 
				
			||||||
 | 
					#include "json_lexer.h" | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Bk::Json | 
				
			||||||
 | 
					{ | 
				
			||||||
 | 
					    class Parser { | 
				
			||||||
 | 
					        Type::DataStream data; | 
				
			||||||
 | 
					        std::shared_ptr<Json::Node> root; | 
				
			||||||
 | 
					        std::unique_ptr<Json::Node> current; | 
				
			||||||
 | 
					        Lexer lexer; | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        std::shared_ptr<Json::Node> parse_object(); | 
				
			||||||
 | 
					        std::shared_ptr<Json::Node> parse_string(); | 
				
			||||||
 | 
					        std::shared_ptr<Json::Node> parse_number(); | 
				
			||||||
 | 
					        std::shared_ptr<Json::Node> parse_list(); | 
				
			||||||
 | 
					        std::shared_ptr<Json::Node> parse_boolean(); | 
				
			||||||
 | 
					        std::shared_ptr<Json::Node> parse_null(); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        public: | 
				
			||||||
 | 
					            Parser(const Type::DataStream data) | 
				
			||||||
 | 
					            :lexer(data) {} | 
				
			||||||
 | 
					            Parser(File& file); | 
				
			||||||
 | 
					            Parser(const char* data, int length); | 
				
			||||||
 | 
					            Parser(const std::string& str); | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            std::shared_ptr<Json::Node> parse(); | 
				
			||||||
 | 
					    }; | 
				
			||||||
 | 
					} | 
				
			||||||
					Loading…
					
					
				
		Reference in New Issue