diff options
author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-02-03 02:30:01 +0100 |
---|---|---|
committer | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-02-03 02:30:01 +0100 |
commit | bcccee31179c0259b203870b10278033ffc29804 (patch) | |
tree | a7aceb08baf58e5a24285f38aeb8f73de9d694e7 /src/plugins/xml | |
parent | bf8ffac02747a2f3c9bd4e7c1f19300f205232d1 (diff) |
Implemented Including files
Diffstat (limited to 'src/plugins/xml')
-rw-r--r-- | src/plugins/xml/XmlParser.cpp | 176 |
1 files changed, 148 insertions, 28 deletions
diff --git a/src/plugins/xml/XmlParser.cpp b/src/plugins/xml/XmlParser.cpp index 45320ca..48dd1c2 100644 --- a/src/plugins/xml/XmlParser.cpp +++ b/src/plugins/xml/XmlParser.cpp @@ -294,19 +294,55 @@ public: } }; -class ImportHandler : public Handler { +class ImportIncludeHandler : public Handler { public: using Handler::Handler; + bool srcInArgs = false; + std::string rel; + std::string type; + std::string src; + + void start(Variant::mapType &args) override + { + rel = args["rel"].asString(); + type = args["type"].asString(); + src = args["src"].asString(); + srcInArgs = !src.empty(); + } + + void data(const std::string &data, int field) override + { + if (srcInArgs) { + logger().error("\"src\" attribute has already been set"); + return; + } + if (field != 0) { + logger().error("Command has only one field."); + return; + } + src.append(data); + } +}; + +class ImportHandler : public ImportIncludeHandler { +public: + using ImportIncludeHandler::ImportIncludeHandler; + void start(Variant::mapType &args) override { + ImportIncludeHandler::start(args); + // Make sure imports are still possible if (scope().getFlag(ParserFlag::POST_HEAD)) { logger().error("Imports must be listed before other commands.", location()); return; } + } + void end() override + { // Fetch the last node and check whether an import is valid at this // position Rooted<Node> leaf = scope().getLeaf(); @@ -319,11 +355,6 @@ public: } Rooted<RootNode> leafRootNode = leaf.cast<RootNode>(); - // Fetch the parameters - const std::string &rel = args["rel"].asString(); - const std::string &type = args["type"].asString(); - const std::string &src = args["src"].asString(); - // Perform the actual import, register the imported node within the leaf // node Rooted<Node> imported = @@ -333,30 +364,51 @@ public: } } - void end() override {} - static Handler *create(const HandlerData &handlerData) { return new ImportHandler{handlerData}; } }; +class IncludeHandler : public ImportIncludeHandler { +public: + using ImportIncludeHandler::ImportIncludeHandler; + + void start(Variant::mapType &args) override + { + ImportIncludeHandler::start(args); + } + + void end() override + { + context().include(src, type, rel, {&RttiTypes::Node}); + } + + static Handler *create(const HandlerData &handlerData) + { + return new IncludeHandler{handlerData}; + } +}; + namespace ParserStates { /* Document states */ static const ParserState Document = ParserStateBuilder() .parent(&None) + .createdNodeType(&RttiTypes::Document) .elementHandler(DocumentHandler::create) .arguments({Argument::String("name", "")}); /* Domain states */ static const ParserState Domain = ParserStateBuilder() .parents({&None, &Document}) + .createdNodeType(&RttiTypes::Domain) .elementHandler(DomainHandler::create) .arguments({Argument::String("name")}); static const ParserState DomainStruct = ParserStateBuilder() .parent(&Domain) + .createdNodeType(&RttiTypes::StructuredClass) .elementHandler(DomainStructHandler::create) .arguments({Argument::String("name"), Argument::Cardinality("cardinality", AnyCardinality), @@ -366,9 +418,12 @@ static const ParserState DomainStruct = static const ParserState DomainStructFields = ParserStateBuilder().parent(&DomainStruct).arguments({}); static const ParserState DomainStructField = - ParserStateBuilder().parent(&DomainStructFields).arguments( - {Argument::String("name", ""), Argument::Bool("isSubtree", false), - Argument::Bool("optional", false)}); + ParserStateBuilder() + .parent(&DomainStructFields) + .createdNodeType(&RttiTypes::FieldDescriptor) + .arguments({Argument::String("name", ""), + Argument::Bool("isSubtree", false), + Argument::Bool("optional", false)}); static const ParserState DomainStructPrimitive = ParserStateBuilder().parent(&DomainStructFields).arguments( {Argument::String("name", ""), Argument::Bool("optional", false), @@ -378,13 +433,17 @@ static const ParserState DomainStructPrimitive = static const ParserState Typesystem = ParserStateBuilder() .parents({&None, &Domain}) + .createdNodeType(&RttiTypes::Typesystem) .elementHandler(TypesystemHandler::create) .arguments({Argument::String("name", "")}); static const ParserState TypesystemEnum = - ParserStateBuilder().parent(&Typesystem); + ParserStateBuilder().createdNodeType(&RttiTypes::EnumType).parent( + &Typesystem); static const ParserState TypesystemStruct = ParserStateBuilder() .parent(&Typesystem) + .createdNodeType(&RttiTypes::StructType) + .elementHandler(TypesystemStructHandler::create) .arguments({Argument::String("name"), Argument::String("parent", "")}); static const ParserState TypesystemStructField = @@ -396,6 +455,8 @@ static const ParserState TypesystemStructField = static const ParserState TypesystemConstant = ParserStateBuilder() .parent(&Typesystem) + .createdNodeType(&RttiTypes::Constant) + .elementHandler(TypesystemConstantHandler::create) .arguments({Argument::String("name"), Argument::String("type"), Argument::Any("value")}); @@ -406,10 +467,13 @@ static const ParserState Import = .parents({&Document, &Typesystem, &Domain}) .elementHandler(ImportHandler::create) .arguments({Argument::String("rel", ""), Argument::String("type", ""), - Argument::String("src")}); -static const ParserState Include = ParserStateBuilder().parent(&All).arguments( - {Argument::String("rel", ""), Argument::String("type", ""), - Argument::String("src")}); + Argument::String("src", "")}); +static const ParserState Include = + ParserStateBuilder() + .parent(&All) + .elementHandler(IncludeHandler::create) + .arguments({Argument::String("rel", ""), Argument::String("type", ""), + Argument::String("src", "")}); static const std::multimap<std::string, const ParserState *> XmlStates{ {"document", &Document}, @@ -424,8 +488,35 @@ static const std::multimap<std::string, const ParserState *> XmlStates{ {"field", &TypesystemStructField}, {"constant", &TypesystemConstant}, {"import", &Import}, - {"include", &Include}}; + {"include", &Include} + }; } + +/** + * Structue containing the private data that is being passed to the + * XML-Handlers. + */ +struct XMLUserData { + /** + * Containing the depth of the current XML file + */ + size_t depth; + + /** + * Reference at the ParserStack instance. + */ + ParserStack *stack; + + /** + * Constructor of the XMLUserData struct. + * + * @param stack is a pointer at the ParserStack instance. + */ + XMLUserData(ParserStack *stack) : depth(0), stack(stack){ + + } +}; + /** * Wrapper class around the XML_Parser pointer which safely frees it whenever * the scope is left (e.g. because an exception was thrown). @@ -477,7 +568,8 @@ public: static SourceLocation syncLoggerPosition(XML_Parser p, size_t len = 0) { // Fetch the parser stack and the associated user data - ParserStack *stack = static_cast<ParserStack *>(XML_GetUserData(p)); + XMLUserData *userData = static_cast<XMLUserData *>(XML_GetUserData(p)); + ParserStack *stack = userData->stack; // Fetch the current location in the XML file size_t offs = XML_GetCurrentByteIndex(p); @@ -494,10 +586,12 @@ static void xmlStartElementHandler(void *p, const XML_Char *name, const XML_Char **attrs) { XML_Parser parser = static_cast<XML_Parser>(p); - SourceLocation loc = syncLoggerPosition(parser); + XMLUserData *userData = static_cast<XMLUserData *>(XML_GetUserData(p)); + ParserStack *stack = userData->stack; - ParserStack *stack = static_cast<ParserStack *>(XML_GetUserData(parser)); + SourceLocation loc = syncLoggerPosition(parser); + // Assemble the arguments Variant::mapType args; const XML_Char **attr = attrs; while (*attr) { @@ -506,22 +600,40 @@ static void xmlStartElementHandler(void *p, const XML_Char *name, *(attr++), stack->getContext().getLogger()); args.emplace(std::make_pair(key, value.second)); } - stack->start(std::string(name), args, loc); + + // Call the start function + std::string nameStr(name); + if (nameStr != "ousia" || userData->depth > 0) { + stack->start(std::string(name), args, loc); + } + + // Increment the current depth + userData->depth++; } static void xmlEndElementHandler(void *p, const XML_Char *name) { XML_Parser parser = static_cast<XML_Parser>(p); - ParserStack *stack = static_cast<ParserStack *>(XML_GetUserData(parser)); + XMLUserData *userData = static_cast<XMLUserData *>(XML_GetUserData(p)); + ParserStack *stack = userData->stack; syncLoggerPosition(parser); - stack->end(); + + // Decrement the current depth + userData->depth--; + + // Call the end function + std::string nameStr(name); + if (nameStr != "ousia" || userData->depth > 0) { + stack->end(); + } } static void xmlCharacterDataHandler(void *p, const XML_Char *s, int len) { XML_Parser parser = static_cast<XML_Parser>(p); - ParserStack *stack = static_cast<ParserStack *>(XML_GetUserData(parser)); + XMLUserData *userData = static_cast<XMLUserData *>(XML_GetUserData(p)); + ParserStack *stack = userData->stack; size_t ulen = len > 0 ? static_cast<size_t>(len) : 0; syncLoggerPosition(parser, ulen); @@ -538,10 +650,18 @@ void XmlParser::doParse(CharReader &reader, ParserContext &ctx) // Create the parser object ScopedExpatXmlParser p{"UTF-8"}; - // Create the parser stack instance and pass the reference to the state - // machine descriptor - ParserStack stack{ctx, ParserStates::XmlStates}; - XML_SetUserData(&p, &stack); + // Create the parser stack instance, if we're starting on a non-empty scope, + // try to deduce the parser state + ParserStack stack(ctx, ParserStates::XmlStates); + if (!ctx.getScope().isEmpty()) { + if (!stack.deduceState()) { + return; + } + } + + // Pass the reference to the ParserStack to the XML handler + XMLUserData data(&stack); + XML_SetUserData(&p, &data); XML_UseParserAsHandlerArg(&p); // Set the callback functions |