summaryrefslogtreecommitdiff
path: root/src/core/parser/ParserStack.cpp
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-02-01 21:30:15 +0100
committerAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-02-01 21:30:15 +0100
commit28fc6ac92cf8b058da22c54c939fc225779ac26d (patch)
tree6caf90848f577109fd2e89ff07af88f93d39d0c1 /src/core/parser/ParserStack.cpp
parentba5439849b72ac341344d55f2bf05ccf11e37410 (diff)
Improved ParserStack state description
Diffstat (limited to 'src/core/parser/ParserStack.cpp')
-rw-r--r--src/core/parser/ParserStack.cpp114
1 files changed, 55 insertions, 59 deletions
diff --git a/src/core/parser/ParserStack.cpp b/src/core/parser/ParserStack.cpp
index 02b142a..51a7a13 100644
--- a/src/core/parser/ParserStack.cpp
+++ b/src/core/parser/ParserStack.cpp
@@ -28,6 +28,10 @@ namespace ousia {
/* A default handler */
+/**
+ * The DefaultHandler class is used in case no element handler is specified in
+ * the ParserState descriptor.
+ */
class DefaultHandler : public Handler {
public:
using Handler::Handler;
@@ -35,12 +39,12 @@ public:
void start(Variant::mapType &args) override {}
void end() override {}
-};
-static Handler *createDefaultHandler(const HandlerData &handlerData)
-{
- return new DefaultHandler{handlerData};
-}
+ static Handler *create(const HandlerData &handlerData)
+ {
+ return new DefaultHandler{handlerData};
+ }
+};
/* Class Handler */
@@ -54,40 +58,13 @@ void Handler::data(const std::string &data, int field)
}
}
-void Handler::child(std::shared_ptr<Handler> handler)
-{
- // Do nothing here
-}
-
-/* Class HandlerDescriptor */
-
-HandlerInstance HandlerDescriptor::create(const ParserContext &ctx,
- std::string name, State parentState,
- bool isChild, Variant::mapType &args,
- const SourceLocation &location) const
-{
- Handler *h;
- HandlerData data{ctx, name, targetState, parentState, isChild, location};
- if (ctor) {
- h = ctor(data);
- } else {
- h = createDefaultHandler(data);
- }
-
- // Canonicalize the arguments
- arguments.validateMap(args, ctx.getLogger(), true);
-
- h->start(args);
- return HandlerInstance(h, this);
-}
-
/* Class ParserStack */
/**
* Returns an Exception that should be thrown when a currently invalid command
* is thrown.
*/
-static LoggableException invalidCommand(const std::string &name,
+static LoggableException InvalidCommand(const std::string &name,
const std::set<std::string> &expected)
{
if (expected.empty()) {
@@ -104,47 +81,72 @@ static LoggableException invalidCommand(const std::string &name,
}
}
-std::set<std::string> ParserStack::expectedCommands(State state)
+ParserStack::ParserStack(
+ ParserContext &ctx,
+ const std::multimap<std::string, const ParserState *> &states)
+ : ctx(ctx), states(states)
+{
+}
+
+std::set<std::string> ParserStack::expectedCommands(const ParserState &state)
{
std::set<std::string> res;
- for (const auto &v : handlers) {
- if (v.second.parentStates.count(state)) {
+ for (const auto &v : states) {
+ if (v.second->parents.count(&state)) {
res.insert(v.first);
}
}
return res;
}
+const ParserState &ParserStack::currentState()
+{
+ return stack.empty() ? ParserStates::None : stack.top()->state();
+}
+
+std::string ParserStack::currentCommandName()
+{
+ return stack.empty() ? std::string{} : stack.top()->name();
+}
+
void ParserStack::start(std::string name, Variant::mapType &args,
const SourceLocation &location)
{
// Fetch the current handler and the current state
- const HandlerInstance *h = stack.empty() ? nullptr : &stack.top();
- const State curState = currentState();
- bool isChild = false;
+ ParserState const *currentState = &(this->currentState());
// Fetch the correct Handler descriptor for this
- const HandlerDescriptor *descr = nullptr;
- auto range = handlers.equal_range(name);
+ ParserState const *targetState = nullptr;
+ HandlerConstructor ctor = nullptr;
+ auto range = states.equal_range(name);
for (auto it = range.first; it != range.second; it++) {
- const std::set<State> &parentStates = it->second.parentStates;
- if (parentStates.count(curState) || parentStates.count(STATE_ALL)) {
- descr = &(it->second);
+ const ParserStateSet &parents = it->second->parents;
+ if (parents.count(currentState) || parents.count(&ParserStates::All)) {
+ targetState = it->second;
+ ctor = targetState->elementHandler ? targetState->elementHandler
+ : DefaultHandler::create;
break;
}
}
- if (!descr && currentArbitraryChildren()) {
- isChild = true;
- descr = h->descr;
+
+ // Try to use the child handler if one was given
+ if (!targetState && currentState->childHandler) {
+ targetState = currentState;
+ ctor = targetState->childHandler;
}
// No descriptor found, throw an exception.
- if (!descr) {
- throw invalidCommand(name, expectedCommands(curState));
+ if (!targetState || !ctor) {
+ throw InvalidCommand(name, expectedCommands(*currentState));
}
+ // Canonicalize the arguments, allow additional arguments
+ targetState->arguments.validateMap(args, ctx.getLogger(), true);
+
// Instantiate the handler and call its start function
- stack.emplace(descr->create(ctx, name, curState, isChild, args, location));
+ Handler *handler = ctor({ctx, name, *targetState, *currentState, location});
+ handler->start(args);
+ stack.emplace(handler);
}
void ParserStack::start(std::string name, const Variant::mapType &args,
@@ -162,17 +164,11 @@ void ParserStack::end()
}
// Remove the current HandlerInstance from the stack
- HandlerInstance inst{stack.top()};
+ std::shared_ptr<Handler> inst{stack.top()};
stack.pop();
// Call the end function of the last Handler
- inst.handler->end();
-
- // Call the "child" function of the parent Handler in the stack
- // (if one exists).
- if (!stack.empty()) {
- stack.top().handler->child(inst.handler);
- }
+ inst->end();
}
void ParserStack::data(const std::string &data, int field)
@@ -183,7 +179,7 @@ void ParserStack::data(const std::string &data, int field)
}
// Pass the data to the current Handler instance
- stack.top().handler->data(data, field);
+ stack.top()->data(data, field);
}
}