summaryrefslogtreecommitdiff
path: root/src/core/parser/stack/Stack.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/parser/stack/Stack.hpp')
-rw-r--r--src/core/parser/stack/Stack.hpp195
1 files changed, 146 insertions, 49 deletions
diff --git a/src/core/parser/stack/Stack.hpp b/src/core/parser/stack/Stack.hpp
index b106475..294f7ec 100644
--- a/src/core/parser/stack/Stack.hpp
+++ b/src/core/parser/stack/Stack.hpp
@@ -17,41 +17,126 @@
*/
/**
- * @file ParserStateStack.hpp
+ * @file Stack.hpp
*
* Helper classes for document or description parsers. Contains the
- * ParserStateStack class, which is an pushdown automaton responsible for
+ * Stack class, which is an pushdown automaton responsible for
* accepting commands in the correct order and calling specified handlers.
*
* @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de)
*/
-#ifndef _OUSIA_PARSER_STATE_STACK_HPP_
-#define _OUSIA_PARSER_STATE_STACK_HPP_
+#ifndef _OUSIA_PARSER_STACK_STACK_HPP_
+#define _OUSIA_PARSER_STACK_STACK_HPP_
#include <cstdint>
#include <map>
#include <memory>
#include <set>
-#include <stack>
#include <vector>
#include <core/common/Variant.hpp>
-#include <core/common/Logger.hpp>
-#include <core/common/Argument.hpp>
-
-#include "Parser.hpp"
-#include "ParserContext.hpp"
-#include "ParserState.hpp"
+#include <core/parser/Parser.hpp>
namespace ousia {
+// Forward declarations
+class ParserContext;
+
+namespace parser_stack {
+
+// Forward declarations
+class Handler;
+class State;
+
/**
- * The ParserStateStack class is a pushdown automaton responsible for turning a
- * command stream into a tree of Node instances.
+ * The HandlerInfo class is used internally by the stack to associate additional
+ * (mutable) data with a handler instance.
*/
-class ParserStateStack {
+class HandlerInfo {
+public:
+ /**
+ * Pointer pointing at the actual handler instance.
+ */
+ std::shared_ptr<Handler> handler;
+
+ /**
+ * Next field index to be passed to the "fieldStart" function of the Handler
+ * class.
+ */
+ size_t fieldIdx;
+
+ /**
+ * Set to true if the handler is valid (which is the case if the "start"
+ * method has returned true). If the handler is invalid, no more calls are
+ * directed at it until it can be removed from the stack.
+ */
+ bool valid : 1;
+
+ /**
+ * Set to true if the handler currently is in a filed.
+ */
+ bool inField : 1;
+
+ /**
+ * Set to true if the handler currently is in the default field.
+ */
+ bool inDefaultField : 1;
+
+ /**
+ * Set to true if the handler currently is in an implicitly started default
+ * field.
+ */
+ bool inImplicitDefaultField : 1;
+
+ /**
+ * Set to false if this field is only opened pro-forma and does not accept
+ * any data. Otherwise set to true.
+ */
+ bool inValidField : 1;
+
+ /**
+ * Set to true, if the default field was already started.
+ */
+ bool hasDefaultField : 1;
+
+ /**
+ * Default constructor of the HandlerInfo class.
+ */
+ HandlerInfo();
+
+ /**
+ * Constructor of the HandlerInfo class, taking a shared_ptr to the handler
+ * to which additional information should be attached.
+ */
+ HandlerInfo(std::shared_ptr<Handler> handler);
+
+ /**
+ * Destructor of the HandlerInfo class (to allow Handler to be forward
+ * declared).
+ */
+ ~HandlerInfo();
+
+ /**
+ * Updates the "field" flags according to a "fieldStart" event.
+ */
+ void fieldStart(bool isDefault, bool isImplicit, bool isValid);
+
+ /**
+ * Updates the "fields" flags according to a "fieldEnd" event.
+ */
+ void fieldEnd();
+};
+
+
+/**
+ * The Stack class is a pushdown automaton responsible for turning a command
+ * stream into a tree of Node instances. It does so by following a state
+ * transition graph and creating a set of Handler instances, which are placed
+ * on the stack.
+ */
+class Stack {
private:
/**
* Reference at the parser context.
@@ -62,12 +147,12 @@ private:
* Map containing all registered command names and the corresponding
* state descriptors.
*/
- const std::multimap<std::string, const ParserState *> &states;
+ const std::multimap<std::string, const State *> &states;
/**
* Internal stack used for managing the currently active Handler instances.
*/
- std::stack<std::shared_ptr<Handler>> stack;
+ std::vector<HandlerInfo> stack;
/**
* Used internally to get all expected command names for the current state.
@@ -83,44 +168,50 @@ private:
*
* @param name is the name of the requested command.
* @return nullptr if no target state was found, a pointer at the target
- *state
- * otherwise.
+ * state otherwise.
*/
- const ParserState *findTargetState(const std::string &name);
+ const State *findTargetState(const std::string &name);
+
+ /**
+ * Tries to reconstruct the parser state from the Scope instance of the
+ * ParserContext given in the constructor. This functionality is needed for
+ * including files,as the Parser of the included file needs to be brought to
+ * an equivalent state as the one in the including file.
+ */
+ void deduceState();
+
+ /**
+ * Returns true if all handlers on the stack are currently valid, or false
+ * if at least one handler is invalid.
+ *
+ * @return true if all handlers on the stack are valid.
+ */
+ bool handlersValid();
public:
/**
- * Creates a new instance of the ParserStateStack class.
+ * Creates a new instance of the Stack class.
*
* @param ctx is the parser context the parser stack is working on.
* @param states is a map containing the command names and pointers at the
- * corresponding ParserState instances.
+ * corresponding State instances.
*/
- ParserStateStack(
+ Stack(
ParserContext &ctx,
- const std::multimap<std::string, const ParserState *> &states);
+ const std::multimap<std::string, const State *> &states);
/**
- * Tries to reconstruct the parser state from the Scope instance of the
- * ParserContext given in the constructor. This functionality is needed for
- * including files,as the Parser of the included file needs to be brought to
- + an equivalent state as the one in the including file.
- *
- * @param scope is the ParserScope instance from which the ParserState
- * should be reconstructed.
- * @param logger is the logger instance to which error messages should be
- * written.
- * @return true if the operation was sucessful, false otherwise.
+ * Destructor of the Stack class.
*/
- bool deduceState();
+ ~Stack();
/**
- * Returns the state the ParserStateStack instance currently is in.
+ * Returns the state the Stack instance currently is in.
*
* @return the state of the currently active Handler instance or STATE_NONE
* if no handler is on the stack.
*/
- const ParserState &currentState();
+ const State &currentState();
/**
* Returns the command name that is currently being handled.
@@ -135,30 +226,35 @@ public:
*
* @param name is the name of the command (including the namespace
* separator ':') and its corresponding location. Must be a string variant.
- * @param args is a map variant containing the arguments that were passed to
- * the command.
+ * @param args is a map containing the arguments that were passed to the
+ * command.
*/
- void command(Variant name, Variant args);
+ void command(const Variant &name, const Variant::mapType &args);
/**
* Function that should be called whenever a new field starts. Fields of the
- * same command may not be separated by calls to
+ * same command may not be separated by calls to data or annotations. Doing
+ * so will result in a LoggableException.
+ *
+ * @param isDefault should be set to true if the started field explicitly
+ * is the default field.
*/
- void fieldStart();
+ void fieldStart(bool isDefault);
/**
- * Function that should be called whenever a field ends.
+ * Function that should be called whenever a field ends. Calling this
+ * function if there is no field to end will result in a LoggableException.
*/
void fieldEnd();
/**
* Function that shuold be called whenever character data is found in the
- * input stream.
+ * input stream. May only be called if the currently is a command on the
+ * stack.
*
- * @param data is a variant of any type containing the data that was parsed
- * as data.
+ * @param data is a string variant containing the data that has been found.
*/
- void data(Variant data);
+ void data(const Variant &data);
/**
* Function that should be called whenever an annotation starts.
@@ -167,7 +263,7 @@ public:
* @param args is a map variant containing the arguments that were passed
* to the annotation.
*/
- void annotationStart(Variant name, Variant args);
+ void annotationStart(const Variant &className, const Variant &args);
/**
* Function that should be called whenever an annotation ends.
@@ -175,7 +271,7 @@ public:
* @param name is the name of the annotation class that was ended.
* @param annotationName is the name of the annotation that was ended.
*/
- void annotationEnd(Variant name, Variant annotationName);
+ void annotationEnd(const Variant &className, const Variant &elementName);
/**
* Function that should be called whenever a previously registered token
@@ -186,6 +282,7 @@ public:
void token(Variant token);
};
}
+}
-#endif /* _OUSIA_PARSER_STATE_STACK_HPP_ */
+#endif /* _OUSIA_STACK_HPP_ */