diff options
author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-03-03 20:20:40 +0100 |
---|---|---|
committer | Andreas Stöckel <andreas@somweyr.de> | 2015-03-03 20:20:40 +0100 |
commit | 42c0480b4fbf80afa0c5b13650a0af74311d7202 (patch) | |
tree | 13f40104b4d8ebcb394f9adbf0b6a723889acea9 /src/core/parser/stack/DocumentHandler.cpp | |
parent | b6ec0740e027fc1bc7f6d2513583187061bc8f0a (diff) |
Implemented annotation handling
Diffstat (limited to 'src/core/parser/stack/DocumentHandler.cpp')
-rw-r--r-- | src/core/parser/stack/DocumentHandler.cpp | 151 |
1 files changed, 129 insertions, 22 deletions
diff --git a/src/core/parser/stack/DocumentHandler.cpp b/src/core/parser/stack/DocumentHandler.cpp index 26b9b6e..486ce81 100644 --- a/src/core/parser/stack/DocumentHandler.cpp +++ b/src/core/parser/stack/DocumentHandler.cpp @@ -127,19 +127,23 @@ void DocumentChildHandler::createPath(const size_t &firstFieldIdx, scope().setFlag(ParserFlag::POST_EXPLICIT_FIELDS, false); } -bool DocumentChildHandler::startCommand(Variant::mapType &args) +static std::string extractNameAttribute(Variant::mapType &args) { // Extract the special "name" attribute from the input arguments. // The remaining attributes will be forwarded to the newly constructed // element. - std::string nameAttr; - { - auto it = args.find("name"); - if (it != args.end()) { - nameAttr = it->second.asString(); - args.erase(it); - } + std::string res; + auto it = args.find("name"); + if (it != args.end()) { + res = it->second.asString(); + args.erase(it); } + return res; +} + +bool DocumentChildHandler::startCommand(Variant::mapType &args) +{ + std::string nameAttr = extractNameAttribute(args); scope().setFlag(ParserFlag::POST_HEAD, true); while (true) { @@ -190,9 +194,9 @@ bool DocumentChildHandler::startCommand(Variant::mapType &args) "Data or structure commands have already been " "given, command \"") + name() + std::string( - "\" is not interpreted explicit " - "field. Move explicit field " - "references to the beginning."), + "\" is not interpreted explicit " + "field. Move explicit field " + "references to the beginning."), location()); } else { Rooted<DocumentField> field{new DocumentField( @@ -252,18 +256,109 @@ bool DocumentChildHandler::startCommand(Variant::mapType &args) // parent structure element scope().setFlag(ParserFlag::POST_EXPLICIT_FIELDS, true); - // Bush the entity onto the stack + // Push the entity onto the stack entity->setLocation(location()); scope().push(entity); return true; } } -bool DocumentChildHandler::startAnnotation(Variant::mapType &args, - AnnotationType annotationType) +bool DocumentChildHandler::startAnnotation(Variant::mapType &args) { - // TODO: Handle annotation - return false; + std::string nameAttr = extractNameAttribute(args); + + scope().setFlag(ParserFlag::POST_HEAD, true); + + size_t fieldIdx; + DocumentEntity *parent; + while (true) { + Rooted<Node> parentNode = scope().getLeaf(); + + // Make sure the parent node is a DocumentField + if (parentNode->isa(&RttiTypes::Document)) { + logger().error( + "Cannot start or end annotation at the document level.", + location()); + return false; + } + assert(parentNode->isa(&RttiTypes::DocumentField)); + + preamble(parentNode, fieldIdx, parent); + + if (!parent->getDescriptor() + ->getFieldDescriptors()[fieldIdx] + ->isPrimitive()) { + break; + } + + // If we are inside a primitive field and have transparent elements on + // the stack we unwind the stack until we are inside + // a non-primitive field. + if (scope().getLeaf().cast<DocumentField>()->transparent) { + // if we have transparent elements above us in the structure + // tree we try to unwind them before we give up. + // pop the implicit field. + scope().pop(logger()); + // pop the implicit element. + scope().pop(logger()); + continue; + } + } + + // Create the anchor + Rooted<Anchor> anchor = parent->createChildAnchor(fieldIdx); + anchor->setLocation(location()); + + // resolve the AnnotationClass + Rooted<AnnotationClass> annoClass; + if (!name().empty()) { + annoClass = scope().resolve<AnnotationClass>(Utils::split(name(), ':'), + logger()); + } + + switch (type()) { + case HandlerType::ANNOTATION_START: { + // Create the AnnotationEntity itself. + if (annoClass == nullptr) { + // if we could not resolve the name, throw an exception. + throw LoggableException( + std::string("\"") + name() + "\" could not be resolved.", + location()); + } + Rooted<Document> doc = scope().selectOrThrow<Document>(); + Rooted<AnnotationEntity> anno = doc->createChildAnnotation( + annoClass, anchor, nullptr, args, nameAttr); + + // Push the entity onto the stack + anno->setLocation(location()); + scope().push(anno); + break; + } + case HandlerType::ANNOTATION_END: { + // if we want to end an annotation, look for the matching start + // Anchor ... + Rooted<Anchor> start = + parent->searchStartAnchor(fieldIdx, annoClass, nameAttr); + if (start == nullptr) { + logger().error( + "Did not find matching annotation start for annotation " + "end.", + *anchor); + parent->removeStructureNodeFromField(anchor, fieldIdx); + return false; + } + // ... and set the end Anchor. + start->getAnnotation()->setEnd(anchor); + break; + } + default: + throw OusiaException( + "Internal Error: Invalid handler type in startAnnotation"); + } + // We're past the region in which explicit fields can be defined in the + // parent structure element + scope().setFlag(ParserFlag::POST_EXPLICIT_FIELDS, true); + return true; } bool DocumentChildHandler::startToken(Handle<Node> node) @@ -281,11 +376,23 @@ DocumentChildHandler::EndTokenResult DocumentChildHandler::endToken( void DocumentChildHandler::end() { - // In case of explicit fields we do not want to pop something from the - // stack. - if (!isExplicitField) { - // pop the "main" element. - scope().pop(logger()); + switch (type()) { + case HandlerType::COMMAND: + case HandlerType::ANNOTATION_START: + // In case of explicit fields we do not want to pop something from + // the + // stack. + if (!isExplicitField) { + // pop the "main" element. + scope().pop(logger()); + } + break; + case HandlerType::ANNOTATION_END: + // We have nothing to pop from the stack + break; + case HandlerType::TOKEN: + // TODO + break; } } @@ -481,4 +588,4 @@ namespace RttiTypes { const Rtti DocumentField = RttiBuilder<ousia::parser_stack::DocumentField>( "DocumentField").parent(&Node); } -} +}
\ No newline at end of file |