diff options
Diffstat (limited to 'src/plugins/xml/XmlParser.cpp')
-rw-r--r-- | src/plugins/xml/XmlParser.cpp | 157 |
1 files changed, 132 insertions, 25 deletions
diff --git a/src/plugins/xml/XmlParser.cpp b/src/plugins/xml/XmlParser.cpp index 51c52bc..d71ceac 100644 --- a/src/plugins/xml/XmlParser.cpp +++ b/src/plugins/xml/XmlParser.cpp @@ -22,34 +22,103 @@ #include <expat.h> #include <core/common/CharReader.hpp> +#include <core/common/RttiBuilder.hpp> #include <core/common/Utils.hpp> #include <core/common/VariantReader.hpp> #include <core/parser/ParserStack.hpp> #include <core/parser/ParserScope.hpp> +#include <core/model/Document.hpp> +#include <core/model/Domain.hpp> +#include <core/model/Project.hpp> #include <core/model/Typesystem.hpp> #include "XmlParser.hpp" namespace ousia { -/* Document structure */ -static const State STATE_DOCUMENT = 0; -static const State STATE_HEAD = 1; -static const State STATE_BODY = 2; +/* HeadNode Helper class */ -/* Special commands */ -static const State STATE_USE = 100; -static const State STATE_INCLUDE = 101; -static const State STATE_INLINE = 102; +namespace { +class HeadNode : public Node { +public: + using Node::Node; +}; +} -/* Type system definitions */ -static const State STATE_TYPESYSTEM = 200; -static const State STATE_TYPES = 201; -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; +namespace RttiTypes { +static Rtti HeadNode = RttiBuilder<ousia::HeadNode>("HeadNode"); +} + +/* Element Handler Classes */ + +class DocumentHandler : public Handler { +public: + using Handler::Handler; + + void start(Variant::mapType &args) override + { + Rooted<Document> document = + project()->createDocument(args["name"].asString()); + document->setLocation(location()); + scope().push(document); + scope().setFlag(ParserFlag::POST_HEAD, false); + } + + void end() override { scope().pop(); } + + static Handler *create(const HandlerData &handlerData) + { + return new DocumentHandler{handlerData}; + } +}; + +class HeadHandler : public Handler { +public: + using Handler::Handler; + + void start(Variant::mapType &args) override + { + // Make sure the "HEAD" node is actually allowed here + if (scope().getFlag(ParserFlag::POST_HEAD)) { + throw LoggableException{ + "\"head\" tag not allowed here, head was already specified or " + "another command was given first", + location()}; + } + + // Insert a new HeadNode instance + scope().push(new HeadNode{manager()}); + } + + void end() override + { + // Remove the HeadNode instance from the stack + scope().pop(); + scope().setFlag(ParserFlag::POST_HEAD, true); + } + + static Handler *create(const HandlerData &handlerData) + { + return new HeadHandler{handlerData}; + } +}; + +class DisableHeadHandler : public Handler { +public: + using Handler::Handler; + + void start(Variant::mapType &args) override + { + scope().setFlag(ParserFlag::POST_HEAD, true); + } + + void end() override {} + + static Handler *create(const HandlerData &handlerData) + { + return new DisableHeadHandler{handlerData}; + } +}; class TypesystemHandler : public Handler { public: @@ -57,10 +126,20 @@ public: void start(Variant::mapType &args) override { + // Create the typesystem instance Rooted<Typesystem> typesystem = project()->createTypesystem(args["name"].asString()); typesystem->setLocation(location()); + + // Check whether this typesystem is a direct child of a domain + Handle<Node> parent = scope().select({&RttiTypes::Domain}); + if (parent != nullptr) { + parent.cast<Domain>()->referenceTypesystem(typesystem); + } + + // Push the typesystem onto the scope, set the POST_HEAD flag to true scope().push(typesystem); + scope().setFlag(ParserFlag::POST_HEAD, false); } void end() override { scope().pop(); } @@ -148,25 +227,52 @@ public: } }; +/* Document structure */ +static const State STATE_DOCUMENT = 0; +static const State STATE_DOCUMENT_HEAD = 1; + +/* Special commands */ +static const State STATE_IMPORT = 100; +static const State STATE_INCLUDE = 101; + +/* Type system definitions */ +static const State STATE_TYPESYSTEM = 200; +static const State STATE_TYPESYSTEM_HEAD = 201; +static const State STATE_TYPES = 202; +static const State STATE_CONSTANTS = 203; +static const State STATE_CONSTANT = 204; +static const State STATE_ENUM = 205; +static const State STATE_STRUCT = 206; +static const State STATE_FIELD = 207; + +/* Domain definitions */ +static const State STATE_DOMAIN = 300; +static const State STATE_DOMAIN_HEAD = 301; + static const std::multimap<std::string, HandlerDescriptor> XML_HANDLERS{ /* Document tags */ - {"document", {{STATE_NONE}, nullptr, STATE_DOCUMENT}}, - {"head", {{STATE_DOCUMENT}, nullptr, STATE_HEAD}}, - {"body", {{STATE_DOCUMENT}, nullptr, STATE_BODY, true}}, + {"document", + {{STATE_NONE}, + DocumentHandler::create, + STATE_DOCUMENT, + true, + {Argument::String("name", "")}}}, + {"head", {{STATE_DOCUMENT}, HeadHandler::create, STATE_DOCUMENT_HEAD}}, /* Special commands */ - {"use", {{STATE_HEAD}, nullptr, STATE_USE}}, + {"import", + {{STATE_DOCUMENT_HEAD, STATE_TYPESYSTEM_HEAD}, nullptr, STATE_IMPORT}}, {"include", {{STATE_ALL}, nullptr, STATE_INCLUDE}}, - {"inline", {{STATE_ALL}, nullptr, STATE_INLINE}}, /* Typesystem */ {"typesystem", - {{STATE_NONE, STATE_HEAD}, + {{STATE_NONE, STATE_DOMAIN_HEAD}, TypesystemHandler::create, STATE_TYPESYSTEM, false, {Argument::String("name")}}}, - {"types", {{STATE_TYPESYSTEM}, nullptr, STATE_TYPES}}, + {"head", {{STATE_TYPESYSTEM}, HeadHandler::create, STATE_TYPESYSTEM}}, + {"types", {{STATE_TYPESYSTEM}, DisableHeadHandler::create, STATE_TYPES}}, {"enum", {{STATE_TYPES}, nullptr, STATE_ENUM}}, {"struct", {{STATE_TYPES}, @@ -175,13 +281,14 @@ static const std::multimap<std::string, HandlerDescriptor> XML_HANDLERS{ false, {Argument::String("name"), Argument::String("parent", "")}}}, {"field", - {{{STATE_STRUCT}}, + {{STATE_STRUCT}, StructFieldHandler::create, STATE_FIELD, false, {Argument::String("name"), Argument::String("type"), Argument::Any("default", Variant::fromObject(nullptr))}}}, - {"constants", {{STATE_TYPESYSTEM}, nullptr, STATE_CONSTANTS}}, + {"constants", + {{STATE_TYPESYSTEM}, DisableHeadHandler::create, STATE_CONSTANTS}}, {"constant", {{STATE_CONSTANTS}, nullptr, STATE_CONSTANT}}}; /** |