summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-02-15 14:58:46 +0100
committerAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-02-15 14:58:46 +0100
commit69ebaddbeaea1aa651a0f0babbf9283240d9c07b (patch)
tree4b590c8ae6e634b8445a2f2d0f580a970bc1b669 /src/core
parent2aced1289813b3dae9c79f3c6878788343e3d997 (diff)
Slightly adapted Handler instances to new Handler, once again passing non-const references to data and start, using "parseGenericString" in DocumentHandler for resolving non-string values, added unit test for testing whether "end()" is not called if "start()" fails.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/parser/stack/DocumentHandler.cpp141
-rw-r--r--src/core/parser/stack/DocumentHandler.hpp96
-rw-r--r--src/core/parser/stack/DomainHandler.cpp51
-rw-r--r--src/core/parser/stack/DomainHandler.hpp28
-rw-r--r--src/core/parser/stack/Handler.cpp20
-rw-r--r--src/core/parser/stack/Handler.hpp31
-rw-r--r--src/core/parser/stack/ImportIncludeHandler.cpp54
-rw-r--r--src/core/parser/stack/ImportIncludeHandler.hpp13
-rw-r--r--src/core/parser/stack/Stack.cpp18
-rw-r--r--src/core/parser/stack/TypesystemHandler.cpp48
-rw-r--r--src/core/parser/stack/TypesystemHandler.hpp131
11 files changed, 388 insertions, 243 deletions
diff --git a/src/core/parser/stack/DocumentHandler.cpp b/src/core/parser/stack/DocumentHandler.cpp
index ba7430d..b28f0fb 100644
--- a/src/core/parser/stack/DocumentHandler.cpp
+++ b/src/core/parser/stack/DocumentHandler.cpp
@@ -22,22 +22,28 @@
#include <core/common/RttiBuilder.hpp>
#include <core/common/Utils.hpp>
+#include <core/common/VariantReader.hpp>
#include <core/model/Document.hpp>
#include <core/model/Domain.hpp>
+#include <core/model/Project.hpp>
#include <core/model/Typesystem.hpp>
#include <core/parser/ParserScope.hpp>
+#include <core/parser/ParserContext.hpp>
namespace ousia {
+namespace parser_stack {
/* DocumentHandler */
-void DocumentHandler::start(Variant::mapType &args)
+bool DocumentHandler::start(Variant::mapType &args)
{
Rooted<Document> document =
- project()->createDocument(args["name"].asString());
+ context().getProject()->createDocument(args["name"].asString());
document->setLocation(location());
scope().push(document);
scope().setFlag(ParserFlag::POST_HEAD, false);
+
+ return true;
}
void DocumentHandler::end() { scope().pop(); }
@@ -48,7 +54,7 @@ void DocumentChildHandler::preamble(Handle<Node> parentNode,
std::string &fieldName,
DocumentEntity *&parent, bool &inField)
{
- // check if the parent in the structure tree was an explicit field
+ // Check if the parent in the structure tree was an explicit field
// reference.
inField = parentNode->isa(&RttiTypes::DocumentField);
if (inField) {
@@ -56,10 +62,11 @@ void DocumentChildHandler::preamble(Handle<Node> parentNode,
parentNode = scope().selectOrThrow(
{&RttiTypes::StructuredEntity, &RttiTypes::AnnotationEntity});
} else {
- // if it wasn't an explicit reference, we use the default field.
+ // If it wasn't an explicit reference, we use the default field.
fieldName = DEFAULT_FIELD_NAME;
}
- // reference the parent entity explicitly.
+
+ // Reference the parent entity explicitly.
parent = nullptr;
if (parentNode->isa(&RttiTypes::StructuredEntity)) {
parent = static_cast<DocumentEntity *>(
@@ -73,6 +80,8 @@ void DocumentChildHandler::preamble(Handle<Node> parentNode,
void DocumentChildHandler::createPath(const NodeVector<Node> &path,
DocumentEntity *&parent)
{
+ // TODO (@benjamin): These should be pushed onto the scope and poped once
+ // the scope is left. Otherwise stuff may not be correclty resolved.
size_t S = path.size();
for (size_t p = 1; p < S; p = p + 2) {
parent = static_cast<DocumentEntity *>(
@@ -82,7 +91,7 @@ void DocumentChildHandler::createPath(const NodeVector<Node> &path,
}
}
-void DocumentChildHandler::start(Variant::mapType &args)
+bool DocumentChildHandler::start(Variant::mapType &args)
{
scope().setFlag(ParserFlag::POST_HEAD, true);
Rooted<Node> parentNode = scope().selectOrThrow(
@@ -95,7 +104,7 @@ void DocumentChildHandler::start(Variant::mapType &args)
preamble(parentNode, fieldName, parent, inField);
- // try to find a FieldDescriptor for the given tag if we are not in a
+ // Try to find a FieldDescriptor for the given tag if we are not in a
// field already. This does _not_ try to construct transparent paths
// in between.
if (!inField && parent != nullptr &&
@@ -104,7 +113,7 @@ void DocumentChildHandler::start(Variant::mapType &args)
new DocumentField(parentNode->getManager(), fieldName, parentNode)};
field->setLocation(location());
scope().push(field);
- return;
+ return true;
}
// Otherwise create a new StructuredEntity
@@ -147,27 +156,39 @@ void DocumentChildHandler::start(Variant::mapType &args)
}
entity->setLocation(location());
scope().push(entity);
+ return true;
}
void DocumentChildHandler::end() { scope().pop(); }
-std::pair<bool, Variant> DocumentChildHandler::convertData(
- Handle<FieldDescriptor> field, Logger &logger, const std::string &data)
+bool DocumentChildHandler::convertData(Handle<FieldDescriptor> field,
+ Variant &data, Logger &logger)
{
- // if the content is supposed to be of type string, we can finish
- // directly.
- auto vts = field->getPrimitiveType()->getVariantTypes();
- if (std::find(vts.begin(), vts.end(), VariantType::STRING) != vts.end()) {
- return std::make_pair(true, Variant::fromString(data));
+ bool valid = true;
+ Rooted<Type> type = field->getPrimitiveType();
+
+ // If the content is supposed to be of type string, we only need to check
+ // for "magic" values -- otherwise just call the "parseGenericString"
+ // function on the string data
+ if (type->isa(&RttiTypes::StringType)) {
+ const std::string &str = data.asString();
+ // TODO: Referencing constants with "." separator should also work
+ if (Utils::isIdentifier(str)) {
+ data.markAsMagic();
+ }
+ } else {
+ // Parse the string as generic string, assign the result
+ auto res = VariantReader::parseGenericString(
+ data.asString(), logger, data.getLocation().getSourceId(),
+ data.getLocation().getStart());
+ data = res.second;
}
- // then try to parse the content using the type specification.
- auto res = field->getPrimitiveType()->read(
- data, logger, location().getSourceId(), location().getStart());
- return res;
+ // Now try to resolve the value for the primitive type
+ return valid && scope().resolveValue(data, type, logger);
}
-void DocumentChildHandler::data(const std::string &data, int fieldIdx)
+bool DocumentChildHandler::data(Variant &data)
{
Rooted<Node> parentNode = scope().selectOrThrow(
{&RttiTypes::StructuredEntity, &RttiTypes::AnnotationEntity,
@@ -180,11 +201,10 @@ void DocumentChildHandler::data(const std::string &data, int fieldIdx)
preamble(parentNode, fieldName, parent, inField);
Rooted<Descriptor> desc = parent->getDescriptor();
- /*
- * We distinguish two cases here: One for fields that are given.
- */
+
+ // We distinguish two cases here: One for fields that are given.
if (fieldName != DEFAULT_FIELD_NAME) {
- // retrieve the actual FieldDescriptor
+ // Retrieve the actual FieldDescriptor
Rooted<FieldDescriptor> field = desc->getFieldDescriptor(fieldName);
if (field == nullptr) {
logger().error(
@@ -192,49 +212,57 @@ void DocumentChildHandler::data(const std::string &data, int fieldIdx)
fieldName + "\" exists in descriptor\"" + desc->getName() +
"\".",
location());
- return;
+ return false;
}
- // if it is not primitive at all, we can't parse the content.
+ // If it is not primitive at all, we can't parse the content.
if (!field->isPrimitive()) {
logger().error(std::string("Can't handle data because field \"") +
fieldName + "\" of descriptor \"" +
desc->getName() + "\" is not primitive!",
location());
- return;
+ return false;
}
- // then try to parse the content using the type specification.
- auto res = convertData(field, logger(), data);
- // add it as primitive content.
- if (res.first) {
- parent->createChildDocumentPrimitive(res.second, fieldName);
+
+ // Try to convert the data variable to the correct format, abort if this
+ // does not work
+ if (!convertData(field, data, logger())) {
+ return false;
}
+
+ // Add it as primitive content
+ parent->createChildDocumentPrimitive(data, fieldName);
+ return true;
} else {
- /*
- * The second case is for primitive fields. Here we search through
- * all FieldDescriptors that allow primitive content at this point
- * and could be constructed via transparent intermediate entities.
- * We then try to parse the data using the type specified by the
- * respective field. If that does not work we proceed to the next
- * possible field.
- */
- // retrieve all fields.
+ // The second case is for primitive fields. Here we search through
+ // all FieldDescriptors that allow primitive content at this point
+ // and could be constructed via transparent intermediate entities.
+ // We then try to parse the data using the type specified by the
+ // respective field. If that does not work we proceed to the next
+ // possible field.
NodeVector<FieldDescriptor> fields = desc->getDefaultFields();
std::vector<LoggerFork> forks;
for (auto field : fields) {
- // then try to parse the content using the type specification.
+ // Then try to parse the content using the type specification
forks.emplace_back(logger().fork());
- auto res = convertData(field, forks.back(), data);
- if (res.first) {
- forks.back().commit();
- // if that worked, construct the necessary path.
- auto pathRes = desc->pathTo(field, logger());
- assert(pathRes.second);
- NodeVector<Node> path = pathRes.first;
- createPath(path, parent);
- // then create the primitive element.
- parent->createChildDocumentPrimitive(res.second, fieldName);
- return;
+
+ // Try to convert the data variable to the correct format, abort if
+ // this does not work
+ if (!convertData(field, data, forks.back())) {
+ return false;
}
+
+ // Show possible warnings that were emitted by this type conversion
+ forks.back().commit();
+
+ // If that worked, construct the necessary path
+ auto pathRes = desc->pathTo(field, logger());
+ assert(pathRes.second);
+ NodeVector<Node> path = pathRes.first;
+ createPath(path, parent);
+
+ // Then create the primitive element
+ parent->createChildDocumentPrimitive(data, fieldName);
+ return true;
}
logger().error("Could not read data with any of the possible fields:");
for (size_t f = 0; f < fields.size(); f++) {
@@ -242,11 +270,14 @@ void DocumentChildHandler::data(const std::string &data, int fieldIdx)
SourceLocation{}, MessageMode::NO_CONTEXT);
forks[f].commit();
}
+ return false;
}
+ return true;
+}
}
namespace RttiTypes {
-const Rtti DocumentField =
- RttiBuilder<ousia::DocumentField>("DocumentField").parent(&Node);
+const Rtti DocumentField = RttiBuilder<ousia::parser_stack::DocumentField>(
+ "DocumentField").parent(&Node);
}
}
diff --git a/src/core/parser/stack/DocumentHandler.hpp b/src/core/parser/stack/DocumentHandler.hpp
index 475fe69..7dc4c86 100644
--- a/src/core/parser/stack/DocumentHandler.hpp
+++ b/src/core/parser/stack/DocumentHandler.hpp
@@ -19,13 +19,19 @@
/**
* @file DocumentHandler.hpp
*
- * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de)
+ * Contains the Handler instances used for parsing actual documents. This file
+ * declares to classes: The Document handler which parses the "document" command
+ * that introduces a new document and the "DocumentChildHandler" which parses
+ * the actual user defined tags.
+ *
+ * @author Benjamin Paaßen (bpaassen@techfak.uni-bielefeld.de)
*/
-#ifndef _OUSIA_DOCUMENT_HANDLER_HPP_
-#define _OUSIA_DOCUMENT_HANDLER_HPP_
+#ifndef _OUSIA_PARSER_STACK_DOCUMENT_HANDLER_HPP_
+#define _OUSIA_PARSER_STACK_DOCUMENT_HANDLER_HPP_
#include <core/common/Variant.hpp>
+#include <core/model/Node.hpp>
#include "Handler.hpp"
@@ -36,53 +42,117 @@ class Rtti;
class DocumentEntity;
class FieldDescriptor;
+namespace parser_stack {
+/**
+ * The DocumentHandler class parses the "document" tag that is used to introduce
+ * a new document. Note that this tag is not mandatory in osml files -- if the
+ * first command is not a typesystem, domain or any other declarative command,
+ * the DocumentHandler will be implicitly called.
+ */
class DocumentHandler : public StaticHandler {
public:
using StaticHandler::StaticHandler;
bool start(Variant::mapType &args) override;
-
void end() override;
+ /**
+ * Creates a new instance of the ImportHandler.
+ *
+ * @param handlerData is the data that is passed to the constructor of the
+ * Handler base class and used there to e.g. access the ParserContext and
+ * the Callbacks instance.
+ */
static Handler *create(const HandlerData &handlerData)
{
return new DocumentHandler{handlerData};
}
};
+/**
+ * Temporary Node that is being pushed onto the ParserScope in order to indicate
+ * the field the parser is currently in. The name of the Node is stored in the
+ * "name" field of the parent Node class.
+ */
class DocumentField : public Node {
public:
using Node::Node;
};
+/**
+ * The DocumentChildHandler class performs the actual parsing of the user
+ * defined elements in an Ousía document.
+ */
class DocumentChildHandler : public StaticHandler {
private:
+ /**
+ * Code shared by both the start() and the end() method. Checks whether the
+ * parser currently is in a field and returns the name of this field.
+ *
+ * @param parentNode is the next possible parent node (a document,
+ * a structured entity, an annotation entity or a field).
+ * @param fieldName is an output parameter to which the name of the current
+ * field is written (or unchanged if we're not in a field).
+ * @param parent is an output parameter to which the parent document entity
+ * will be written.
+ * @param inField is set to true if we actually are in a field.
+ */
void preamble(Handle<Node> parentNode, std::string &fieldName,
DocumentEntity *&parent, bool &inField);
+ /**
+ * Constructs all structured entites along the given path and inserts them
+ * into the document graph.
+ *
+ * @param path is a path containing an alternating series of structured
+ * classes and fields.
+ * @pram parent is the root entity from which the process should be started.
+ */
void createPath(const NodeVector<Node> &path, DocumentEntity *&parent);
- std::pair<bool, Variant> convertData(Handle<FieldDescriptor> field,
- Logger &logger,
- const std::string &data);
+ /**
+ * Tries to convert the given data to the type that is specified in the
+ * given primitive field.
+ *
+ * @param field is the primitive field for which the data is intended.
+ * @param data is the is the data that should be converted, the result is
+ * written into this argument as output variable.
+ * @param logger is the Logger instance to which error messages should be
+ * written. Needed to allow the convertData function to write to a forked
+ * Logger instance.
+ * @return true if the operation was successful, false otherwise.
+ */
+ bool convertData(Handle<FieldDescriptor> field, Variant &data,
+ Logger &logger);
public:
- using Handler::Handler;
+ using StaticHandler::StaticHandler;
bool start(Variant::mapType &args) override;
-
void end() override;
-
- bool data(const Variant &data) override;
-
+ bool data(Variant &data) override;
+
+ /**
+ * Creates a new instance of the DocumentChildHandler.
+ *
+ * @param handlerData is the data that is passed to the constructor of the
+ * Handler base class and used there to e.g. access the ParserContext and
+ * the Callbacks instance.
+ */
static Handler *create(const HandlerData &handlerData)
{
return new DocumentChildHandler{handlerData};
}
};
+}
namespace RttiTypes {
+/**
+ * RttiType for the internally used DocumentField class.
+ */
extern const Rtti DocumentField;
}
}
-#endif
+
+#endif /* _OUSIA_PARSER_STACK_DOCUMENT_HANDLER_HPP_ */
+
diff --git a/src/core/parser/stack/DomainHandler.cpp b/src/core/parser/stack/DomainHandler.cpp
index 6571717..cb12543 100644
--- a/src/core/parser/stack/DomainHandler.cpp
+++ b/src/core/parser/stack/DomainHandler.cpp
@@ -20,25 +20,30 @@
#include <core/common/RttiBuilder.hpp>
#include <core/model/Domain.hpp>
+#include <core/model/Project.hpp>
#include <core/parser/ParserScope.hpp>
+#include <core/parser/ParserContext.hpp>
namespace ousia {
+namespace parser_stack {
/* DomainHandler */
-void DomainHandler::start(Variant::mapType &args)
+bool DomainHandler::start(Variant::mapType &args)
{
- Rooted<Domain> domain = project()->createDomain(args["name"].asString());
+ Rooted<Domain> domain =
+ context().getProject()->createDomain(args["name"].asString());
domain->setLocation(location());
scope().push(domain);
+ return true;
}
void DomainHandler::end() { scope().pop(); }
/* DomainStructHandler */
-void DomainStructHandler::start(Variant::mapType &args)
+bool DomainStructHandler::start(Variant::mapType &args)
{
scope().setFlag(ParserFlag::POST_HEAD, true);
@@ -63,12 +68,13 @@ void DomainStructHandler::start(Variant::mapType &args)
}
scope().push(structuredClass);
+ return true;
}
void DomainStructHandler::end() { scope().pop(); }
/* DomainAnnotationHandler */
-void DomainAnnotationHandler::start(Variant::mapType &args)
+bool DomainAnnotationHandler::start(Variant::mapType &args)
{
scope().setFlag(ParserFlag::POST_HEAD, true);
@@ -79,13 +85,14 @@ void DomainAnnotationHandler::start(Variant::mapType &args)
annotationClass->setLocation(location());
scope().push(annotationClass);
+ return true;
}
void DomainAnnotationHandler::end() { scope().pop(); }
/* DomainAttributesHandler */
-void DomainAttributesHandler::start(Variant::mapType &args)
+bool DomainAttributesHandler::start(Variant::mapType &args)
{
// Fetch the current typesystem and create the struct node
Rooted<Descriptor> parent = scope().selectOrThrow<Descriptor>();
@@ -94,13 +101,14 @@ void DomainAttributesHandler::start(Variant::mapType &args)
attrDesc->setLocation(location());
scope().push(attrDesc);
+ return true;
}
void DomainAttributesHandler::end() { scope().pop(); }
/* DomainFieldHandler */
-void DomainFieldHandler::start(Variant::mapType &args)
+bool DomainFieldHandler::start(Variant::mapType &args)
{
FieldDescriptor::FieldType type;
if (args["isSubtree"].asBool()) {
@@ -116,13 +124,14 @@ void DomainFieldHandler::start(Variant::mapType &args)
field->setLocation(location());
scope().push(field);
+ return true;
}
void DomainFieldHandler::end() { scope().pop(); }
/* DomainFieldRefHandler */
-void DomainFieldRefHandler::start(Variant::mapType &args)
+bool DomainFieldRefHandler::start(Variant::mapType &args)
{
Rooted<Descriptor> parent = scope().selectOrThrow<Descriptor>();
@@ -135,13 +144,14 @@ void DomainFieldRefHandler::start(Variant::mapType &args)
field.cast<FieldDescriptor>(), logger);
}
});
+ return true;
}
void DomainFieldRefHandler::end() {}
/* DomainPrimitiveHandler */
-void DomainPrimitiveHandler::start(Variant::mapType &args)
+bool DomainPrimitiveHandler::start(Variant::mapType &args)
{
Rooted<Descriptor> parent = scope().selectOrThrow<Descriptor>();
@@ -167,13 +177,14 @@ void DomainPrimitiveHandler::start(Variant::mapType &args)
});
scope().push(field);
+ return true;
}
void DomainPrimitiveHandler::end() { scope().pop(); }
/* DomainChildHandler */
-void DomainChildHandler::start(Variant::mapType &args)
+bool DomainChildHandler::start(Variant::mapType &args)
{
Rooted<FieldDescriptor> field = scope().selectOrThrow<FieldDescriptor>();
@@ -186,13 +197,12 @@ void DomainChildHandler::start(Variant::mapType &args)
child.cast<StructuredClass>());
}
});
+ return true;
}
-void DomainChildHandler::end() {}
-
/* DomainParentHandler */
-void DomainParentHandler::start(Variant::mapType &args)
+bool DomainParentHandler::start(Variant::mapType &args)
{
Rooted<StructuredClass> strct = scope().selectOrThrow<StructuredClass>();
@@ -200,12 +210,14 @@ void DomainParentHandler::start(Variant::mapType &args)
new DomainParent(strct->getManager(), args["ref"].asString(), strct)};
parent->setLocation(location());
scope().push(parent);
+ return true;
}
void DomainParentHandler::end() { scope().pop(); }
/* DomainParentFieldHandler */
-void DomainParentFieldHandler::start(Variant::mapType &args)
+
+bool DomainParentFieldHandler::start(Variant::mapType &args)
{
Rooted<DomainParent> parentNameNode = scope().selectOrThrow<DomainParent>();
FieldDescriptor::FieldType type;
@@ -233,13 +245,12 @@ void DomainParentFieldHandler::start(Variant::mapType &args)
field->addChild(strct.cast<StructuredClass>());
}
});
+ return true;
}
-void DomainParentFieldHandler::end() {}
-
/* DomainParentFieldRefHandler */
-void DomainParentFieldRefHandler::start(Variant::mapType &args)
+bool DomainParentFieldRefHandler::start(Variant::mapType &args)
{
Rooted<DomainParent> parentNameNode = scope().selectOrThrow<DomainParent>();
@@ -265,12 +276,12 @@ void DomainParentFieldRefHandler::start(Variant::mapType &args)
field->addChild(strct.cast<StructuredClass>());
}
});
+ return true;
+}
}
-
-void DomainParentFieldRefHandler::end() {}
namespace RttiTypes {
-const Rtti DomainParent =
- RttiBuilder<ousia::DomainParent>("DomainParent").parent(&Node);
+const Rtti DomainParent = RttiBuilder<ousia::parser_stack::DomainParent>(
+ "DomainParent").parent(&Node);
}
}
diff --git a/src/core/parser/stack/DomainHandler.hpp b/src/core/parser/stack/DomainHandler.hpp
index 5e8ea60..917d65d 100644
--- a/src/core/parser/stack/DomainHandler.hpp
+++ b/src/core/parser/stack/DomainHandler.hpp
@@ -19,17 +19,24 @@
/**
* @file DomainHandler.hpp
*
- * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de)
+ * Contains the Handler classes used for parsing Domain descriptors. This
+ * includes the "domain" tag and all describing tags below the "domain" tag.
+ *
+ * @author Benjamin Paaßen (bpaassen@techfak.uni-bielefeld.de)
*/
#ifndef _OUSIA_DOMAIN_HANDLER_HPP_
#define _OUSIA_DOMAIN_HANDLER_HPP_
#include <core/common/Variant.hpp>
+#include <core/model/Node.hpp>
#include "Handler.hpp"
namespace ousia {
+namespace parser_stack {
+
+// TODO: Documentation
// Forward declarations
class Rtti;
@@ -39,7 +46,6 @@ public:
using StaticHandler::StaticHandler;
bool start(Variant::mapType &args) override;
-
void end() override;
static Handler *create(const HandlerData &handlerData)
@@ -53,7 +59,6 @@ public:
using StaticHandler::StaticHandler;
bool start(Variant::mapType &args) override;
-
void end() override;
static Handler *create(const HandlerData &handlerData)
@@ -67,7 +72,6 @@ public:
using StaticHandler::StaticHandler;
bool start(Variant::mapType &args) override;
-
void end() override;
static Handler *create(const HandlerData &handlerData)
@@ -81,7 +85,6 @@ public:
using StaticHandler::StaticHandler;
bool start(Variant::mapType &args) override;
-
void end() override;
static Handler *create(const HandlerData &handlerData)
@@ -95,7 +98,6 @@ public:
using StaticHandler::StaticHandler;
bool start(Variant::mapType &args) override;
-
void end() override;
static Handler *create(const HandlerData &handlerData)
@@ -109,7 +111,6 @@ public:
using StaticHandler::StaticHandler;
bool start(Variant::mapType &args) override;
-
void end() override;
static Handler *create(const HandlerData &handlerData)
@@ -123,7 +124,6 @@ public:
using StaticHandler::StaticHandler;
bool start(Variant::mapType &args) override;
-
void end() override;
static Handler *create(const HandlerData &handlerData)
@@ -138,8 +138,6 @@ public:
bool start(Variant::mapType &args) override;
- void end() override;
-
static Handler *create(const HandlerData &handlerData)
{
return new DomainChildHandler{handlerData};
@@ -160,7 +158,6 @@ public:
using StaticHandler::StaticHandler;
bool start(Variant::mapType &args) override;
-
void end() override;
static Handler *create(const HandlerData &handlerData)
@@ -175,8 +172,6 @@ public:
bool start(Variant::mapType &args) override;
- void end() override;
-
static Handler *create(const HandlerData &handlerData)
{
return new DomainParentFieldHandler{handlerData};
@@ -189,12 +184,15 @@ public:
bool start(Variant::mapType &args) override;
- void end() override;
-
static Handler *create(const HandlerData &handlerData)
{
return new DomainParentFieldRefHandler{handlerData};
}
};
}
+
+namespace RttiTypes {
+extern const Rtti DomainParent;
+}
+}
#endif
diff --git a/src/core/parser/stack/Handler.cpp b/src/core/parser/stack/Handler.cpp
index a608f7f..86000c4 100644
--- a/src/core/parser/stack/Handler.cpp
+++ b/src/core/parser/stack/Handler.cpp
@@ -65,6 +65,8 @@ Logger &Handler::logger()
const SourceLocation &Handler::location() const { return handlerData.location; }
+const std::string &Handler::name() const { return handlerData.name; }
+
void Handler::setWhitespaceMode(WhitespaceMode whitespaceMode)
{
/*handlerData.callbacks.setWhitespaceMode(whitespaceMode);*/
@@ -80,7 +82,7 @@ void Handler::unregisterToken(const std::string &token)
/*handlerData.callbacks.unregisterToken(token);*/
}
-const std::string &Handler::getName() const { return handlerData.name; }
+const std::string &Handler::getName() const { return name(); }
const State &Handler::getState() const { return handlerData.state; }
@@ -92,7 +94,7 @@ const SourceLocation &Handler::getLocation() const { return location(); }
/* Class EmptyHandler */
-bool EmptyHandler::start(const Variant::mapType &args)
+bool EmptyHandler::start(Variant::mapType &args)
{
// Just accept anything
return true;
@@ -115,7 +117,7 @@ void EmptyHandler::fieldEnd()
}
bool EmptyHandler::annotationStart(const Variant &className,
- const Variant::mapType &args)
+ Variant::mapType &args)
{
// Accept any data
return true;
@@ -128,7 +130,7 @@ bool EmptyHandler::annotationEnd(const Variant &className,
return true;
}
-bool EmptyHandler::data(const Variant &data)
+bool EmptyHandler::data(Variant &data)
{
// Support any data
return true;
@@ -141,7 +143,7 @@ Handler *EmptyHandler::create(const HandlerData &handlerData)
/* Class StaticHandler */
-bool StaticHandler::start(const Variant::mapType &args)
+bool StaticHandler::start(Variant::mapType &args)
{
// Do nothing in the default implementation, accept anything
return true;
@@ -169,7 +171,7 @@ void StaticHandler::fieldEnd()
}
bool StaticHandler::annotationStart(const Variant &className,
- const Variant::mapType &args)
+ Variant::mapType &args)
{
// No annotations supported
return false;
@@ -182,7 +184,7 @@ bool StaticHandler::annotationEnd(const Variant &className,
return false;
}
-bool StaticHandler::data(const Variant &data)
+bool StaticHandler::data(Variant &data)
{
logger().error("Did not expect any data here", data);
return false;
@@ -196,7 +198,7 @@ StaticFieldHandler::StaticFieldHandler(const HandlerData &handlerData,
{
}
-bool StaticFieldHandler::start(const Variant::mapType &args)
+bool StaticFieldHandler::start(Variant::mapType &args)
{
if (!argName.empty()) {
auto it = args.find(argName);
@@ -225,7 +227,7 @@ void StaticFieldHandler::end()
}
}
-bool StaticFieldHandler::data(const Variant &data)
+bool StaticFieldHandler::data(Variant &data)
{
// Call the doHandle function if this has not been done before
if (!handled) {
diff --git a/src/core/parser/stack/Handler.hpp b/src/core/parser/stack/Handler.hpp
index eeaf555..7cda7a4 100644
--- a/src/core/parser/stack/Handler.hpp
+++ b/src/core/parser/stack/Handler.hpp
@@ -151,6 +151,13 @@ protected:
*/
const SourceLocation &location() const;
+ /**
+ * Returns the command name for which the handler was created.
+ *
+ * @return a const reference at the command name.
+ */
+ const std::string &name() const;
+
public:
/**
* Virtual destructor.
@@ -229,7 +236,7 @@ public:
* @return true if the handler was successful in starting the element it
* represents, false otherwise.
*/
- virtual bool start(const Variant::mapType &args) = 0;
+ virtual bool start(Variant::mapType &args) = 0;
/**
* Called before the command for which this handler is defined ends (is
@@ -270,7 +277,7 @@ public:
* if an error occurred.
*/
virtual bool annotationStart(const Variant &className,
- const Variant::mapType &args) = 0;
+ Variant::mapType &args) = 0;
/**
* Called whenever an annotation ends while this handler is active. The
@@ -296,7 +303,7 @@ public:
* location.
* @return true if the data could be handled, false otherwise.
*/
- virtual bool data(const Variant &data) = 0;
+ virtual bool data(Variant &data) = 0;
};
/**
@@ -318,15 +325,15 @@ protected:
using Handler::Handler;
public:
- bool start(const Variant::mapType &args) override;
+ bool start(Variant::mapType &args) override;
void end() override;
bool fieldStart(bool &isDefault, size_t fieldIdx) override;
void fieldEnd() override;
bool annotationStart(const Variant &className,
- const Variant::mapType &args) override;
+ Variant::mapType &args) override;
bool annotationEnd(const Variant &className,
const Variant &elementName) override;
- bool data(const Variant &data) override;
+ bool data(Variant &data) override;
/**
* Creates an instance of the EmptyHandler class.
@@ -344,15 +351,15 @@ protected:
using Handler::Handler;
public:
- bool start(const Variant::mapType &args) override;
+ bool start(Variant::mapType &args) override;
void end() override;
bool fieldStart(bool &isDefault, size_t fieldIdx) override;
void fieldEnd() override;
bool annotationStart(const Variant &className,
- const Variant::mapType &args) override;
+ Variant::mapType &args) override;
bool annotationEnd(const Variant &className,
const Variant &elementName) override;
- bool data(const Variant &data) override;
+ bool data(Variant &data) override;
};
/**
@@ -400,12 +407,12 @@ protected:
* @param args are the arguments that were given in the "start" function.
*/
virtual void doHandle(const Variant &fieldData,
- const Variant::mapType &args) = 0;
+ Variant::mapType &args) = 0;
public:
- bool start(const Variant::mapType &args) override;
+ bool start(Variant::mapType &args) override;
void end() override;
- bool data(const Variant &data) override;
+ bool data(Variant &data) override;
};
}
}
diff --git a/src/core/parser/stack/ImportIncludeHandler.cpp b/src/core/parser/stack/ImportIncludeHandler.cpp
index 94ee82d..797dd8d 100644
--- a/src/core/parser/stack/ImportIncludeHandler.cpp
+++ b/src/core/parser/stack/ImportIncludeHandler.cpp
@@ -18,48 +18,16 @@
#include "ImportIncludeHandler.hpp"
+#include <core/model/RootNode.hpp>
#include <core/parser/ParserScope.hpp>
+#include <core/parser/ParserContext.hpp>
namespace ousia {
-
-/* ImportIncludeHandler */
-
-void ImportIncludeHandler::start(Variant::mapType &args)
-{
- rel = args["rel"].asString();
- type = args["type"].asString();
- src = args["src"].asString();
- srcInArgs = !src.empty();
-}
-
-void ImportIncludeHandler::data(const std::string &data, int field)
-{
- 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);
-}
+namespace parser_stack {
/* ImportHandler */
-void ImportHandler::start(Variant::mapType &args)
-{
- 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 ImportHandler::end()
+void ImportHandler::doHandle(const Variant &fieldData, Variant::mapType &args)
{
// Fetch the last node and check whether an import is valid at this
// position
@@ -75,8 +43,9 @@ void ImportHandler::end()
// Perform the actual import, register the imported node within the leaf
// node
- Rooted<Node> imported =
- context().import(src, type, rel, leafRootNode->getReferenceTypes());
+ Rooted<Node> imported = context().import(
+ fieldData.asString(), args["type"].asString(), args["rel"].asString(),
+ leafRootNode->getReferenceTypes());
if (imported != nullptr) {
leafRootNode->reference(imported);
}
@@ -84,13 +53,10 @@ void ImportHandler::end()
/* IncludeHandler */
-void IncludeHandler::start(Variant::mapType &args)
+void IncludeHandler::doHandle(const Variant &fieldData, Variant::mapType &args)
{
- ImportIncludeHandler::start(args);
+ context().include(fieldData.asString(), args["type"].asString(),
+ args["rel"].asString(), {&RttiTypes::Node});
}
-
-void IncludeHandler::end()
-{
- context().include(src, type, rel, {&RttiTypes::Node});
}
}
diff --git a/src/core/parser/stack/ImportIncludeHandler.hpp b/src/core/parser/stack/ImportIncludeHandler.hpp
index f9abe55..8f3d3d0 100644
--- a/src/core/parser/stack/ImportIncludeHandler.hpp
+++ b/src/core/parser/stack/ImportIncludeHandler.hpp
@@ -29,9 +29,11 @@
#define _OUSIA_IMPORT_INCLUDE_HANDLER_HPP_
#include <core/common/Variant.hpp>
-#include <core/parser/ParserStack.hpp>
+
+#include "Handler.hpp"
namespace ousia {
+namespace parser_stack {
/**
* The ImportHandler is responsible for handling the "import" command. An import
@@ -46,7 +48,7 @@ public:
using StaticFieldHandler::StaticFieldHandler;
void doHandle(const Variant &fieldData,
- const Variant::mapType &args) override;
+ Variant::mapType &args) override;
/**
* Creates a new instance of the ImportHandler.
@@ -57,7 +59,7 @@ public:
*/
static Handler *create(const HandlerData &handlerData)
{
- return new ImportHandler{handlerData};
+ return new ImportHandler{handlerData, "src"};
}
};
@@ -72,7 +74,7 @@ public:
using StaticFieldHandler::StaticFieldHandler;
void doHandle(const Variant &fieldData,
- const Variant::mapType &args) override;
+ Variant::mapType &args) override;
/**
* Creates a new instance of the IncludeHandler.
@@ -83,8 +85,9 @@ public:
*/
static Handler *create(const HandlerData &handlerData)
{
- return new IncludeHandler{handlerData};
+ return new IncludeHandler{handlerData, "src"};
}
};
}
+}
#endif
diff --git a/src/core/parser/stack/Stack.cpp b/src/core/parser/stack/Stack.cpp
index d84a19c..47f7d2c 100644
--- a/src/core/parser/stack/Stack.cpp
+++ b/src/core/parser/stack/Stack.cpp
@@ -316,8 +316,6 @@ void Stack::command(const Variant &name, const Variant::mapType &args)
name);
}
- State const *lastTargetState = nullptr;
- Variant::mapType canonicalArgs;
while (true) {
// Try to find a target state for the given command, if none can be
// found and the current command does not have an open field, then try
@@ -342,14 +340,6 @@ void Stack::command(const Variant &name, const Variant::mapType &args)
// Fork the logger. We do not want any validation errors to skip
LoggerFork loggerFork = logger().fork();
- // Canonicalize the arguments (if this has not already been done), allow
- // additional arguments
- if (lastTargetState != targetState) {
- canonicalArgs = args;
- targetState->arguments.validateMap(canonicalArgs, loggerFork, true);
- lastTargetState = targetState;
- }
-
// Instantiate the handler and push it onto the stack
HandlerConstructor ctor = targetState->elementHandler
? targetState->elementHandler
@@ -369,6 +359,11 @@ void Stack::command(const Variant &name, const Variant::mapType &args)
bool validStack = handlersValid();
info.valid = false;
if (validStack) {
+ // Canonicalize the arguments (if this has not already been done),
+ // allow additional arguments
+ Variant::mapType canonicalArgs = args;
+ targetState->arguments.validateMap(canonicalArgs, loggerFork, true);
+
handler->setLogger(loggerFork);
try {
info.valid = handler->start(canonicalArgs);
@@ -430,7 +425,8 @@ void Stack::data(const Variant &data)
// Pass the data to the current Handler instance
bool valid = false;
try {
- valid = info.handler->data(data);
+ Variant dataCopy = data;
+ valid = info.handler->data(dataCopy);
}
catch (LoggableException ex) {
loggerFork.log(ex);
diff --git a/src/core/parser/stack/TypesystemHandler.cpp b/src/core/parser/stack/TypesystemHandler.cpp
index 2cc7dfb..34f64f9 100644
--- a/src/core/parser/stack/TypesystemHandler.cpp
+++ b/src/core/parser/stack/TypesystemHandler.cpp
@@ -20,28 +20,33 @@
#include <core/model/Typesystem.hpp>
#include <core/parser/ParserScope.hpp>
+#include <core/parser/ParserContext.hpp>
+
namespace ousia {
+namespace parser_stack {
/* TypesystemHandler */
-void TypesystemHandler::start(Variant::mapType &args)
+bool TypesystemHandler::start(Variant::mapType &args)
{
// Create the typesystem instance
Rooted<Typesystem> typesystem =
- project()->createTypesystem(args["name"].asString());
+ context().getProject()->createTypesystem(args["name"].asString());
typesystem->setLocation(location());
// Push the typesystem onto the scope, set the POST_HEAD flag to true
scope().push(typesystem);
scope().setFlag(ParserFlag::POST_HEAD, false);
+
+ return true;
}
void TypesystemHandler::end() { scope().pop(); }
/* TypesystemEnumHandler */
-void TypesystemEnumHandler::start(Variant::mapType &args)
+bool TypesystemEnumHandler::start(Variant::mapType &args)
{
scope().setFlag(ParserFlag::POST_HEAD, true);
@@ -52,33 +57,24 @@ void TypesystemEnumHandler::start(Variant::mapType &args)
enumType->setLocation(location());
scope().push(enumType);
+
+ return true;
}
void TypesystemEnumHandler::end() { scope().pop(); }
/* TypesystemEnumEntryHandler */
-void TypesystemEnumEntryHandler::start(Variant::mapType &args) {}
-
-void TypesystemEnumEntryHandler::end()
+void TypesystemEnumEntryHandler::doHandle(const Variant &fieldData,
+ Variant::mapType &args)
{
Rooted<EnumType> enumType = scope().selectOrThrow<EnumType>();
- enumType->addEntry(entry, logger());
-}
-
-void TypesystemEnumEntryHandler::data(const std::string &data, int field)
-{
- if (field != 0) {
- // TODO: This should be stored in the HandlerData
- logger().error("Enum entry only has one field.");
- return;
- }
- entry.append(data);
+ enumType->addEntry(fieldData.asString(), logger());
}
/* TypesystemStructHandler */
-void TypesystemStructHandler::start(Variant::mapType &args)
+bool TypesystemStructHandler::start(Variant::mapType &args)
{
scope().setFlag(ParserFlag::POST_HEAD, true);
@@ -103,13 +99,15 @@ void TypesystemStructHandler::start(Variant::mapType &args)
});
}
scope().push(structType);
+
+ return true;
}
void TypesystemStructHandler::end() { scope().pop(); }
/* TypesystemStructFieldHandler */
-void TypesystemStructFieldHandler::start(Variant::mapType &args)
+bool TypesystemStructFieldHandler::start(Variant::mapType &args)
{
// Read the argument values
const std::string &name = args["name"].asString();
@@ -142,13 +140,13 @@ void TypesystemStructFieldHandler::start(Variant::mapType &args)
}
});
}
-}
-void TypesystemStructFieldHandler::end() {}
+ return true;
+}
/* TypesystemConstantHandler */
-void TypesystemConstantHandler::start(Variant::mapType &args)
+bool TypesystemConstantHandler::start(Variant::mapType &args)
{
scope().setFlag(ParserFlag::POST_HEAD, true);
@@ -169,7 +167,9 @@ void TypesystemConstantHandler::start(Variant::mapType &args)
constant.cast<Constant>()->setType(type.cast<Type>(), logger);
}
});
-}
-void TypesystemConstantHandler::end() {}
+ return true;
}
+}
+}
+
diff --git a/src/core/parser/stack/TypesystemHandler.hpp b/src/core/parser/stack/TypesystemHandler.hpp
index 76a7bc9..55277a1 100644
--- a/src/core/parser/stack/TypesystemHandler.hpp
+++ b/src/core/parser/stack/TypesystemHandler.hpp
@@ -19,6 +19,9 @@
/**
* @file TypesystemHandler.hpp
*
+ * Contains the Handler classes used to parse Typesystem descriptions. The
+ * Handlers parse all the tags found below and including the "typesystem" tag.
+ *
* @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de)
*/
@@ -26,96 +29,154 @@
#define _OUSIA_TYPESYSTEM_HANDLER_HPP_
#include <core/common/Variant.hpp>
-#include <core/parser/ParserStack.hpp>
+
+#include "Handler.hpp"
namespace ousia {
+namespace parser_stack {
-class TypesystemHandler : public Handler {
+/**
+ * Handles the occurance of the "typesystem" tag. Creates a new Typesystem
+ * instance and places it on the ParserScope.
+ */
+class TypesystemHandler : public StaticHandler {
public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override;
+ using StaticHandler::StaticHandler;
+ bool start(Variant::mapType &args) override;
void end() override;
+ /**
+ * Creates a new instance of the TypesystemHandler.
+ *
+ * @param handlerData is the data that is passed to the constructor of the
+ * Handler base class and used there to e.g. access the ParserContext and
+ * the Callbacks instance.
+ */
static Handler *create(const HandlerData &handlerData)
{
return new TypesystemHandler{handlerData};
}
};
-class TypesystemEnumHandler : public Handler {
+/**
+ * Handles the occurance of the "enum" tag. Creates a new EnumType instance and
+ * places it on the ParserScope.
+ */
+class TypesystemEnumHandler : public StaticHandler {
public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override;
+ using StaticHandler::StaticHandler;
+ bool start(Variant::mapType &args) override;
void end() override;
+ /**
+ * Creates a new instance of the TypesystemEnumHandler.
+ *
+ * @param handlerData is the data that is passed to the constructor of the
+ * Handler base class and used there to e.g. access the ParserContext and
+ * the Callbacks instance.
+ */
static Handler *create(const HandlerData &handlerData)
{
return new TypesystemEnumHandler{handlerData};
}
};
-class TypesystemEnumEntryHandler : public Handler {
+/**
+ * Handles the occurance of the "entry" tag within an "enum" tag. Creates a new
+ * EnumType instance and places it on the ParserScope.
+ */
+class TypesystemEnumEntryHandler : public StaticFieldHandler {
public:
- using Handler::Handler;
-
- std::string entry;
-
- void start(Variant::mapType &args) override;
-
- void end() override;
-
- void data(const std::string &data, int field) override;
-
+ using StaticFieldHandler::StaticFieldHandler;
+
+ void doHandle(const Variant &fieldData,
+ Variant::mapType &args) override;
+
+ /**
+ * Creates a new instance of the TypesystemEnumEntryHandler.
+ *
+ * @param handlerData is the data that is passed to the constructor of the
+ * Handler base class and used there to e.g. access the ParserContext and
+ * the Callbacks instance.
+ */
static Handler *create(const HandlerData &handlerData)
{
- return new TypesystemEnumEntryHandler{handlerData};
+ return new TypesystemEnumEntryHandler{handlerData, "name"};
}
};
-class TypesystemStructHandler : public Handler {
+/**
+ * Handles the occurance of the "struct" tag within a typesystem description.
+ * Creates a new StructType instance and places it on the ParserScope.
+ */
+class TypesystemStructHandler : public StaticHandler {
public:
- using Handler::Handler;
-
- void start(Variant::mapType &args) override;
+ using StaticHandler::StaticHandler;
+ bool start(Variant::mapType &args) override;
void end() override;
+ /**
+ * Creates a new instance of the TypesystemStructHandler.
+ *
+ * @param handlerData is the data that is passed to the constructor of the
+ * Handler base class and used there to e.g. access the ParserContext and
+ * the Callbacks instance.
+ */
static Handler *create(const HandlerData &handlerData)
{
return new TypesystemStructHandler{handlerData};
}
};
-class TypesystemStructFieldHandler : public Handler {
+/**
+ * Handles the occurance of the "field" tag within a typesystem structure
+ * description. Places a new Attribute instance in the StructType instance
+ * that is currently at the top of the scope.
+ */
+class TypesystemStructFieldHandler : public StaticHandler {
public:
- using Handler::Handler;
+ using StaticHandler::StaticHandler;
- void start(Variant::mapType &args) override;
-
- void end() override;
+ bool start(Variant::mapType &args) override;
+ /**
+ * Creates a new instance of the TypesystemStructFieldHandler.
+ *
+ * @param handlerData is the data that is passed to the constructor of the
+ * Handler base class and used there to e.g. access the ParserContext and
+ * the Callbacks instance.
+ */
static Handler *create(const HandlerData &handlerData)
{
return new TypesystemStructFieldHandler{handlerData};
}
};
-class TypesystemConstantHandler : public Handler {
+/**
+ * Handles the occurance of the "constant" tag within a typesystem structure
+ * description. Places a new Constant instance in the current typesystem.
+ */
+class TypesystemConstantHandler : public StaticHandler {
public:
- using Handler::Handler;
+ using StaticHandler::StaticHandler;
- void start(Variant::mapType &args) override;
-
- void end() override;
+ bool start(Variant::mapType &args) override;
+ /**
+ * Creates a new instance of the TypesystemConstantHandler.
+ *
+ * @param handlerData is the data that is passed to the constructor of the
+ * Handler base class and used there to e.g. access the ParserContext and
+ * the Callbacks instance.
+ */
static Handler *create(const HandlerData &handlerData)
{
return new TypesystemConstantHandler{handlerData};
}
};
}
+}
#endif