summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-01-16 00:43:18 +0100
committerAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-01-16 00:43:18 +0100
commitfae1b7a4eafbd9872d2447eab011bdf9aab97645 (patch)
treed064da98dff6061bdd74c2734e4f9c7f2f4f51dd /src
parentdbf59a218edd684f93f9cf74cdddd6bebefe15e7 (diff)
Working on XMLParser (still lot work in progress)
Diffstat (limited to 'src')
-rw-r--r--src/core/parser/ParserStack.cpp30
-rw-r--r--src/core/parser/ParserStack.hpp79
-rw-r--r--src/plugins/xml/XmlParser.cpp118
3 files changed, 169 insertions, 58 deletions
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> 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<Node> 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 &registry() {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> 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 <core/common/CharReader.hpp>
#include <core/common/Utils.hpp>
#include <core/parser/ParserStack.hpp>
+#include <core/model/Typesystem.hpp>
#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<model::Attribute> 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<model::StructType> 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<model::StructType>();
+ }
+
+ Rooted<model::Typesystem> typesystem =
+ scope().getLeaf().cast<model::Typesystem>();
}
- void data(const std::string &data, int field) override
+ void child(std::shared_ptr<Handler> handler)
{
- std::cout << this->name << ": data \"" << data << "\"" << std::endl;
+/* std::shared_ptr<StructFieldHandler> structFieldHandler =
+ dynamic_cast<StructFieldHandler>(handler);*/
+
+ // Try to resolve
}
- void child(std::shared_ptr<Handler> 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<model::Attribute> attribute;
+
+ void start(Variant::mapType &args) override
+ {
+/* this->name = args["name"].asString();
+ this->type = args["parent"].asString();*/
+ }
+
+ void end() override {}
+};
static const std::multimap<std::string, HandlerDescriptor> 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