From fae1b7a4eafbd9872d2447eab011bdf9aab97645 Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Fri, 16 Jan 2015 00:43:18 +0100 Subject: Working on XMLParser (still lot work in progress) --- src/core/parser/ParserStack.cpp | 30 +++++++++- src/core/parser/ParserStack.hpp | 79 +++++++++++++++++++-------- src/plugins/xml/XmlParser.cpp | 118 +++++++++++++++++++++++++++++----------- 3 files changed, 169 insertions(+), 58 deletions(-) (limited to 'src') diff --git a/src/core/parser/ParserStack.cpp b/src/core/parser/ParserStack.cpp index 691b9d0..caf2116 100644 --- a/src/core/parser/ParserStack.cpp +++ b/src/core/parser/ParserStack.cpp @@ -26,13 +26,30 @@ namespace ousia { namespace parser { +/* A default handler */ + +class DefaultHandler : public Handler { +public: + using Handler::Handler; + + void start(Variant::mapType &args) override {} + + void end() override {} +}; + +static Handler *createDefaultHandler(const HandlerData &handlerData) +{ + return new DefaultHandler{handlerData}; +} + /* Class Handler */ void Handler::data(const std::string &data, int field) { for (auto &c : data) { if (!Utils::isWhitespace(c)) { - throw LoggableException{"No data allowed here."}; + logger().error("Expected command but found character data."); + return; } } } @@ -49,7 +66,13 @@ HandlerInstance HandlerDescriptor::create(const ParserContext &ctx, bool isChild, Variant::mapType &args) const { - Handler *h = ctor(ctx, name, targetState, parentState, isChild); + Handler *h; + HandlerData data{ctx, name, targetState, parentState, isChild}; + if (ctor) { + h = ctor(data); + } else { + h = createDefaultHandler(data); + } // Canonicalize the arguments arguments.validateMap(args, ctx.logger, true); @@ -120,7 +143,8 @@ void ParserStack::start(std::string name, Variant::mapType &args) } // Instantiate the handler and call its start function - stack.emplace(descr->create(ctx, name, curState, isChild, args)); + stack.emplace( + descr->create(ctx, name, curState, isChild, args)); } void ParserStack::start(std::string name, const Variant::mapType &args) diff --git a/src/core/parser/ParserStack.hpp b/src/core/parser/ParserStack.hpp index d9de39e..43d6529 100644 --- a/src/core/parser/ParserStack.hpp +++ b/src/core/parser/ParserStack.hpp @@ -55,15 +55,9 @@ static const State STATE_ALL = -2; static const State STATE_NONE = -1; /** - * The handler class provides a context for handling an XML tag. It has to be - * overridden and registered in the StateStack class to form handlers for - * concrete XML tags. + * Struct collecting all the data that is being passed to a Handler instance. */ -class Handler { -private: - Rooted node; - -public: +struct HandlerData { /** * Reference to the ParserContext instance that should be used to resolve * references to nodes in the Graph. @@ -92,7 +86,7 @@ public: const bool isChild; /** - * Constructor of the Handler class. + * Constructor of the HandlerData class. * * @param ctx is the parser context the handler should be executed in. * @param name is the name of the string. @@ -101,26 +95,57 @@ public: * @param isChild specifies whether this handler was called not for the * command that was specified in the state machine but a child command. */ - Handler(const ParserContext &ctx, std::string name, State state, - State parentState, bool isChild) + HandlerData(const ParserContext &ctx, std::string name, State state, + State parentState, bool isChild) : ctx(ctx), name(std::move(name)), state(state), parentState(parentState), isChild(isChild){}; +}; +/** + * The handler class provides a context for handling an XML tag. It has to be + * overridden and registered in the StateStack class to form handlers for + * concrete XML tags. + */ +class Handler { +private: /** - * Virtual destructor. + * Structure containing the internal handler data. */ - virtual ~Handler(){}; + const HandlerData handlerData; +public: /** - * Returns the node instance that was created by the handler. + * Constructor of the Handler class. * - * @return the Node instance created by the handler. May be nullptr if no - * Node was created. + * @param data is a structure containing all data being passed to the + * handler. */ - Rooted getNode() { return node; } + Handler(const HandlerData &handlerData) : handlerData(handlerData) {}; + + /** + * Virtual destructor. + */ + virtual ~Handler(){}; + + + const std::string& name() {return handlerData.name;} + + Scope &scope() {return handlerData.ctx.scope;} + + Registry ®istry() {return handlerData.ctx.registry;} + + Manager &manager() { return handlerData.ctx.manager; } + + Logger &logger() { return handlerData.ctx.logger; } + + State state() {return handlerData.state; } + + State parentState() { return handlerData.parentState; } + + bool isChild() { return handlerData.isChild; } /** * Called when the command that was specified in the constructor is @@ -128,7 +153,7 @@ public: * * @param args is a map from strings to variants (argument name and value). */ - virtual void start(const Variant::mapType &args) = 0; + virtual void start(Variant::mapType &args) = 0; /** * Called whenever the command for which this handler is defined ends. @@ -158,10 +183,12 @@ public: /** * HandlerConstructor is a function pointer type used to create concrete * instances of the Handler class. + * + * @param handlerData is the data that should be passed to the new handler + * instance. + * @return a newly created handler instance. */ -using HandlerConstructor = Handler *(*)(const ParserContext &ctx, - std::string name, State state, - State parentState, bool isChild); +using HandlerConstructor = Handler *(*)(const HandlerData &handlerData); struct HandlerDescriptor; @@ -177,6 +204,10 @@ struct HandlerInstance { */ std::shared_ptr handler; + /** + * Pointer pointing at the descriptor from which the handler instance was + * derived. + */ const HandlerDescriptor *descr; HandlerInstance(Handler *handler, const HandlerDescriptor *descr) @@ -309,7 +340,7 @@ public: */ State currentState() { - return stack.empty() ? STATE_NONE : stack.top().handler->state; + return stack.empty() ? STATE_NONE : stack.top().handler->state(); } /** @@ -320,7 +351,7 @@ public: */ std::string currentName() { - return stack.empty() ? std::string{} : stack.top().handler->name; + return stack.empty() ? std::string{} : stack.top().handler->name(); } /** @@ -370,7 +401,7 @@ public: * * @return a reference to the parser context. */ - ParserContext& getContext() {return ctx;} + ParserContext &getContext() { return ctx; } }; } } diff --git a/src/plugins/xml/XmlParser.cpp b/src/plugins/xml/XmlParser.cpp index 46c978f..87a2016 100644 --- a/src/plugins/xml/XmlParser.cpp +++ b/src/plugins/xml/XmlParser.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "XmlParser.hpp" @@ -48,68 +49,123 @@ static const State STATE_CONSTANTS = 202; static const State STATE_CONSTANT = 203; static const State STATE_ENUM = 204; static const State STATE_STRUCT = 205; +static const State STATE_FIELD = 206; -class TestHandler : public Handler { +class TypesystemHandler : public Handler { public: using Handler::Handler; - void start(const Variant::mapType &args) override + void start(Variant::mapType &args) override + { + scope().push(new model::Typesystem(manager(), args["name"].asString())); + } + + void end() override { scope().pop(); } + + static Handler *create(const HandlerData &handlerData) { - std::cout << this->name << ": start (isChild: " << (this->isChild) - << ", args: " << Variant(args) << ")" << std::endl; + return new TypesystemHandler{handlerData}; + } +}; + +class StructHandler : public Handler { +public: + using Handler::Handler; + + std::string name; + std::string parent; + + NodeVector attributes; + + void start(Variant::mapType &args) override + { + this->name = args["name"].asString(); + this->parent = args["parent"].asString(); } void end() override { - // TODO + // Try to resolve the specified parent structure + Rooted parentStructure; + if (!parent.empty()) { + // TODO: What about (temporarily) unresolved nodes + // Idea: Provide constructor for empty node, store unresolved nodes + // in the scope, resolve later + parentStructure = + scope() + .resolve(Utils::split(parent, '.'), + (const RttiType &)RttiTypes::StructType, logger()) + .cast(); + } + + Rooted typesystem = + scope().getLeaf().cast(); } - void data(const std::string &data, int field) override + void child(std::shared_ptr handler) { - std::cout << this->name << ": data \"" << data << "\"" << std::endl; +/* std::shared_ptr structFieldHandler = + dynamic_cast(handler);*/ + + // Try to resolve } - void child(std::shared_ptr handler) override + static Handler *create(const HandlerData &handlerData) { - // TODO + return new StructHandler{handlerData}; } }; -class TypesystemHandler : public Handler { +class StructFieldHandler : public Handler { public: using Handler::Handler; -}; -static Handler *createTestHandler(const ParserContext &ctx, std::string name, - State state, State parentState, bool isChild) -{ - return new TestHandler{ctx, name, state, parentState, isChild}; -} + Rooted attribute; + + void start(Variant::mapType &args) override + { +/* this->name = args["name"].asString(); + this->type = args["parent"].asString();*/ + } + + void end() override {} +}; static const std::multimap XML_HANDLERS{ - /* Documents */ - {"document", {{STATE_NONE}, createTestHandler, STATE_DOCUMENT}}, - {"head", {{STATE_DOCUMENT}, createTestHandler, STATE_HEAD}}, - {"body", {{STATE_DOCUMENT}, createTestHandler, STATE_BODY, true}}, + /* Document tags */ + {"document", {{STATE_NONE}, nullptr, STATE_DOCUMENT}}, + {"head", {{STATE_DOCUMENT}, nullptr, STATE_HEAD}}, + {"body", {{STATE_DOCUMENT}, nullptr, STATE_BODY, true}}, /* Special commands */ - {"use", {{STATE_HEAD}, createTestHandler, STATE_USE}}, - {"include", {{STATE_ALL}, createTestHandler, STATE_INCLUDE}}, - {"inline", {{STATE_ALL}, createTestHandler, STATE_INLINE}}, + {"use", {{STATE_HEAD}, nullptr, STATE_USE}}, + {"include", {{STATE_ALL}, nullptr, STATE_INCLUDE}}, + {"inline", {{STATE_ALL}, nullptr, STATE_INLINE}}, - /* Typesystem definitions */ + /* Typesystem */ {"typesystem", {{STATE_NONE, STATE_HEAD}, - createTestHandler, + TypesystemHandler::create, STATE_TYPESYSTEM, false, {Argument::String("name")}}}, - - {"types", {{STATE_TYPESYSTEM}, createTestHandler, STATE_TYPES}}, - {"constants", {{STATE_TYPESYSTEM}, createTestHandler, STATE_CONSTANTS}}, - {"enum", {{STATE_TYPES}, createTestHandler, STATE_ENUM}}, - {"struct", {{STATE_TYPES}, createTestHandler, STATE_STRUCT}}, - {"constant", {{STATE_CONSTANTS}, createTestHandler, STATE_CONSTANT}}}; + {"types", {{STATE_TYPESYSTEM}, nullptr, STATE_TYPES}}, + {"enum", {{STATE_TYPES}, nullptr, STATE_ENUM}}, + {"struct", + {{STATE_TYPES}, + StructHandler::create, + STATE_STRUCT, + false, + {Argument::String("name"), Argument::String("parent", "")}}}, + {"field", + {{{STATE_STRUCT}}, + nullptr, + STATE_FIELD, + false, + {Argument::String("name"), Argument::String("type"), + Argument::Any("default", Variant::fromObject(nullptr))}}}, + {"constants", {{STATE_TYPESYSTEM}, nullptr, STATE_CONSTANTS}}, + {"constant", {{STATE_CONSTANTS}, nullptr, STATE_CONSTANT}}}; /** * Wrapper class around the XML_Parser pointer which safely frees it whenever -- cgit v1.2.3