summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-02-15 00:07:58 +0100
committerAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2015-02-15 00:07:58 +0100
commitcc281d91def921b7bbf5d3d4a0fce53afc5a317b (patch)
tree3ea32f91e35df73d12ce6742436db87440347cb9
parent40e5867bdf347dede1f6b593b774334ca17fd09d (diff)
Renamed parser/generic to parser/stack and made filenames much shorter
-rw-r--r--src/core/parser/generic/ParserStateHandler.cpp104
-rw-r--r--src/core/parser/stack/Callbacks.cpp (renamed from src/core/parser/generic/ParserStateCallbacks.cpp)5
-rw-r--r--src/core/parser/stack/Callbacks.hpp (renamed from src/core/parser/generic/ParserStateCallbacks.hpp)27
-rw-r--r--src/core/parser/stack/Handler.cpp90
-rw-r--r--src/core/parser/stack/Handler.hpp (renamed from src/core/parser/generic/ParserStateHandler.hpp)195
-rw-r--r--src/core/parser/stack/Stack.cpp (renamed from src/core/parser/generic/ParserStateStack.cpp)51
-rw-r--r--src/core/parser/stack/Stack.hpp (renamed from src/core/parser/generic/ParserStateStack.hpp)0
-rw-r--r--src/core/parser/stack/State.cpp (renamed from src/core/parser/generic/ParserState.cpp)66
-rw-r--r--src/core/parser/stack/State.hpp (renamed from src/core/parser/generic/ParserState.hpp)151
-rw-r--r--test/core/parser/ParserStateTest.cpp77
-rw-r--r--test/core/parser/stack/StateTest.cpp79
11 files changed, 439 insertions, 406 deletions
diff --git a/src/core/parser/generic/ParserStateHandler.cpp b/src/core/parser/generic/ParserStateHandler.cpp
deleted file mode 100644
index 64e2bfa..0000000
--- a/src/core/parser/generic/ParserStateHandler.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- Ousía
- Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <core/parser/ParserContext.hpp>
-
-#include "ParserStateHandler.hpp"
-
-namespace ousia {
-
-/* Class ParserStatedata */
-
-ParserStatedata::ParserStatedata(ParserContext &ctx,
- ParserStateCallbacks &callbacks,
- std::string name, const ParserState &state,
- const ParserState &parentState,
- const SourceLocation location)
- : ctx(ctx),
- callbacks(callbacks),
- name(std::move(name)),
- state(state),
- parentState(parentState),
- location(location){};
-
-/* Class ParserStateHandler */
-
-ParserStateHandler::ParserStateHandler(const ParserStatedata &data) : data(data)
-{
-}
-
-ParserContext &ParserStateHandler::context() { return data.ctx; }
-
-const std::string &ParserStateHandler::name() { return data.name; }
-
-ParserScope &ParserStateHandler::scope() { return data.ctx.getScope(); }
-
-Manager &ParserStateHandler::manager() { return data.ctx.getManager(); }
-
-Logger &ParserStateHandler::logger() { return data.ctx.getLogger(); }
-
-Rooted<Project> ParserStateHandler::project() { return data.ctx.getProject(); }
-
-const ParserState &ParserStateHandler::state() { return data.state; }
-
-SourceLocation ParserStateHandler::location() { return data.location; }
-
-void ParserStateHandler::setWhitespaceMode(WhitespaceMode whitespaceMode)
-{
- data.callbacks.setWhitespaceMode(whitespaceMode);
-}
-
-void ParserStateHandler::setDataType(VariantType type)
-{
- data.callbacks.setDataType(type);
-}
-
-bool ParserStateHandler::supportsToken(const std::string &token)
-{
- return data.callbacks.supportsToken(token);
-}
-
-void ParserStateHandler::registerToken(const std::string &token)
-{
- data.callbacks.registerToken(token);
-}
-
-void ParserStateHandler::unregisterToken(const std::string &token)
-{
- data.callbacks.unregisterToken(token);
-}
-
-void ParserStateHandler::data(const std::string &data, int field)
-{
- if (Utils::hasNonWhitepaceChar(data)) {
- logger().error("Expected command but found character data.");
- }
-}
-
-/* Class DefaultParserStateHandler */
-
-void DefaultParserStateHandler::start(Variant::mapType &args) {}
-
-void DefaultParserStateHandler::end() {}
-
-ParserStateHandler *DefaultParserStateHandler::create(const data &data)
-{
- return new DefaultHandler{data};
-}
-}
-
diff --git a/src/core/parser/generic/ParserStateCallbacks.cpp b/src/core/parser/stack/Callbacks.cpp
index 50bac57..6ebc549 100644
--- a/src/core/parser/generic/ParserStateCallbacks.cpp
+++ b/src/core/parser/stack/Callbacks.cpp
@@ -16,11 +16,8 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <ParserStateCallbacks.hpp>
+#include "Callbacks.hpp"
namespace ousia {
-
-/* Class ParserStateCallbacks */
-
}
diff --git a/src/core/parser/generic/ParserStateCallbacks.hpp b/src/core/parser/stack/Callbacks.hpp
index 7ec5264..bb56e44 100644
--- a/src/core/parser/generic/ParserStateCallbacks.hpp
+++ b/src/core/parser/stack/Callbacks.hpp
@@ -17,10 +17,10 @@
*/
/**
- * @file ParserStateCallbacks.hpp
+ * @file Callbacks.hpp
*
* Contains an interface defining the callbacks that can be directed from a
- * ParserStateHandler to the ParserStateStack, and from the ParserStateStack to
+ * StateHandler to the StateStack, and from the StateStack to
* the actual parser.
*
* @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de)
@@ -34,17 +34,18 @@
#include <core/common/Whitespace.hpp>
namespace ousia {
+namespace parser_stack {
/**
* Interface defining a set of callback functions that act as a basis for the
- * ParserStateStackCallbacks and the ParserCallbacks.
+ * StateStackCallbacks and the ParserCallbacks.
*/
-class ParserStateCallbacks {
+class Callbacks {
public:
/**
* Virtual descructor.
*/
- virtual ~ParserStateCallbacks() {};
+ virtual ~Callbacks() {};
/**
* Sets the whitespace mode that specifies how string data should be
@@ -56,15 +57,6 @@ public:
virtual void setWhitespaceMode(WhitespaceMode whitespaceMode) = 0;
/**
- * Sets the type as which the variant data should be parsed.
- *
- * @param type is one of the VariantType constants, specifying with which
- * type the data that is passed to the ParserStateHandler in the "data"
- * function should be handled.
- */
- virtual void setDataType(VariantType type) = 0;
-
- /**
* Registers the given token as token that should be reported to the handler
* using the "token" function.
*
@@ -83,9 +75,9 @@ public:
/**
* Interface defining the callback functions that can be passed from a
- * ParserStateStack to the underlying parser.
+ * StateStack to the underlying parser.
*/
-class ParserCallbacks : public ParserStateCallbacks {
+class ParserCallbacks : public Callbacks {
/**
* Checks whether the given token is supported by the parser. The parser
* returns true, if the token is supported, false if this token cannot be
@@ -98,9 +90,10 @@ class ParserCallbacks : public ParserStateCallbacks {
* because e.g. it is a reserved token or it interferes with other tokens.
*/
virtual bool supportsToken(const std::string &token) = 0;
-}
+};
}
+}
#endif /* _OUSIA_PARSER_STATE_CALLBACKS_HPP_ */
diff --git a/src/core/parser/stack/Handler.cpp b/src/core/parser/stack/Handler.cpp
new file mode 100644
index 0000000..66af2a4
--- /dev/null
+++ b/src/core/parser/stack/Handler.cpp
@@ -0,0 +1,90 @@
+/*
+ Ousía
+ Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <core/parser/ParserContext.hpp>
+
+#include "Callbacks.hpp"
+#include "Handler.hpp"
+#include "State.hpp"
+
+namespace ousia {
+namespace parser_stack {
+
+/* Class HandlerData */
+
+HandlerData::HandlerData(ParserContext &ctx, Callbacks &callbacks,
+ std::string name, const State &state,
+ const SourceLocation &location)
+ : ctx(ctx),
+ callbacks(callbacks),
+ name(std::move(name)),
+ state(state),
+ location(location)
+{
+}
+
+/* Class Handler */
+
+Handler::Handler(const HandlerData &internalData) : internalData(internalData)
+{
+}
+
+Handler::~Handler() {}
+
+ParserContext &Handler::context() { return internalData.ctx; }
+
+const std::string &Handler::name() { return internalData.name; }
+
+ParserScope &Handler::scope() { return internalData.ctx.getScope(); }
+
+Manager &Handler::manager() { return internalData.ctx.getManager(); }
+
+Logger &Handler::logger() { return internalData.ctx.getLogger(); }
+
+const State &Handler::state() { return internalData.state; }
+
+SourceLocation Handler::location() { return internalData.location; }
+
+void Handler::setWhitespaceMode(WhitespaceMode whitespaceMode)
+{
+ internalData.callbacks.setWhitespaceMode(whitespaceMode);
+}
+
+void Handler::registerToken(const std::string &token)
+{
+ internalData.callbacks.registerToken(token);
+}
+
+void Handler::unregisterToken(const std::string &token)
+{
+ internalData.callbacks.unregisterToken(token);
+}
+
+/* Class DefaultHandler */
+
+/*void DefaultHandler::start(Variant::mapType &args) {}
+
+void DefaultHandler::end() {}
+
+Handler *DefaultHandler::create(const data &data)
+{
+ return new DefaultHandler{data};
+}*/
+}
+}
+
diff --git a/src/core/parser/generic/ParserStateHandler.hpp b/src/core/parser/stack/Handler.hpp
index f3c836e..0701343 100644
--- a/src/core/parser/generic/ParserStateHandler.hpp
+++ b/src/core/parser/stack/Handler.hpp
@@ -22,20 +22,27 @@
#include <memory>
#include <string>
-#include <core/utils/Location.hpp>
+#include <core/common/Location.hpp>
+#include <core/common/Variant.hpp>
namespace ousia {
// Forward declarations
class ParserContext;
-class ParserState;
-class ParserStateCallbacks;
+class Callbacks;
+class Logger;
+class Project;
+
+namespace parser_stack {
+
+// More forward declarations
+class State;
/**
- * Class collecting all the data that is being passed to a ParserStateHandler
+ * Class collecting all the data that is being passed to a Handler
* instance.
*/
-class ParserStateHandlerData {
+class HandlerData {
public:
/**
* Reference to the ParserContext instance that should be used to resolve
@@ -44,60 +51,52 @@ public:
ParserContext &ctx;
/**
- * Reference at an instance of the ParserStateCallbacks class, used for
+ * Reference at an instance of the Callbacks class, used for
* modifying the behaviour of the parser (like registering tokens, setting
* the data type or changing the whitespace handling mode).
*/
- ParserStateCallbacks &callbacks;
+ Callbacks &callbacks;
/**
* Contains the name of the command that is being handled.
*/
- const std::string name;
+ std::string name;
/**
* Contains the current state of the state machine.
*/
- const ParserState &state;
-
- /**
- * Contains the state of the state machine when the parent node was handled.
- */
- const ParserState &parentState;
+ const State &state;
/**
* Current source code location.
*/
- const SourceLocation location;
+ SourceLocation location;
/**
* Constructor of the HandlerData class.
*
* @param ctx is the parser context the handler should be executed in.
- * @param callbacks is an instance of ParserStateCallbacks used to notify
+ * @param callbacks is an instance of Callbacks used to notify
* the parser about certain state changes.
* @param name is the name of the string.
* @param state is the state this handler was called for.
- * @param parentState is the state of the parent command.
* @param location is the location at which the handler is created.
*/
- ParserStateHandlerData(ParserContext &ctx, ParserStateCallbacks &callbacks,
- std::string name, const ParserState &state,
- const ParserState &parentState,
- const SourceLocation &location);
+ HandlerData(ParserContext &ctx, Callbacks &callbacks, std::string name,
+ const State &state, const SourceLocation &location);
};
/**
- * 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.
+ * The Handler class provides a context for handling a generic stack element.
+ * It has to beoverridden and registered in the StateStack class to form
+ * handlers for concrete XML tags.
*/
-class ParserStateHandler {
+class Handler {
private:
/**
* Structure containing the internal handler data.
*/
- const ParserStateHandlerData data;
+ const HandlerData internalData;
protected:
/**
@@ -106,13 +105,7 @@ protected:
* @param data is a structure containing all data being passed to the
* handler.
*/
- ParserStateHandler(const ParserStateHandlerData &data){};
-
-public:
- /**
- * Virtual destructor.
- */
- virtual ~Handler(){};
+ Handler(const HandlerData &internalData);
/**
* Returns a reference at the ParserContext.
@@ -151,20 +144,11 @@ public:
Logger &logger();
/**
- * Returns a reference at the Project Node, representing the project into
- * which the file is currently being parsed.
- *
- * @return a referance at the Project Node.
- */
- Rooted<Project> project();
-
- /**
- * Reference at the ParserState descriptor for which this Handler was
- * created.
+ * Reference at the State descriptor for which this Handler was created.
*
- * @return a const reference at the constructing ParserState descriptor.
+ * @return a const reference at the constructing State descriptor.
*/
- const ParserState &state();
+ const State &state();
/**
* Returns the current location in the source file.
@@ -173,42 +157,25 @@ public:
*/
SourceLocation location();
+public:
/**
- * Calls the corresponding function in the ParserStateCallbacks instance.
- * Sets the whitespace mode that specifies how string data should be
- * processed.
- *
- * @param whitespaceMode specifies one of the three WhitespaceMode constants
- * PRESERVE, TRIM or COLLAPSE.
- */
- void setWhitespaceMode(WhitespaceMode whitespaceMode);
-
- /**
- * Calls the corresponding function in the ParserStateCallbacks instance.
- * Sets the type as which the variant data should be parsed.
- *
- * @param type is one of the VariantType constants, specifying with which
- * type the data that is passed to the ParserStateHandler in the "data"
- * function should be handled.
+ * Virtual destructor.
*/
- void setDataType(VariantType type);
+ virtual ~Handler();
/**
- * Calls the corresponding function in the ParserStateCallbacks instance.
- * Checks whether the given token is supported by the parser. The parser
- * returns true, if the token is supported, false if this token cannot be
- * registered. Note that parsers that do not support the registration of
- * tokens at all should always return "true".
+ * Calls the corresponding function in the Callbacks instance. Sets the
+ * whitespace mode that specifies how string data should be processed. The
+ * calls to this function are placed on a stack by the underlying Stack
+ * class.
*
- * @param token is the token that should be checked for support.
- * @return true if the token is generally supported (or the parser does not
- * support registering tokens at all), false if the token is not supported,
- * because e.g. it is a reserved token or it interferes with other tokens.
+ * @param whitespaceMode specifies one of the three WhitespaceMode constants
+ * PRESERVE, TRIM or COLLAPSE.
*/
- bool supportsToken(const std::string &token);
+ void setWhitespaceMode(WhitespaceMode whitespaceMode);
/**
- * Calls the corresponding function in the ParserStateCallbacks instance.
+ * Calls the corresponding function in the Callbacks instance.
* Registers the given token as token that should be reported to the handler
* using the "token" function.
*
@@ -217,7 +184,7 @@ public:
void registerToken(const std::string &token);
/**
- * Calls the corresponding function in the ParserStateCallbacks instance.
+ * Calls the corresponding function in the Callbacks instance.
* Unregisters the given token, it will no longer be reported to the handler
* using the "token" function.
*
@@ -230,25 +197,77 @@ public:
* instanciated.
*
* @param args is a map from strings to variants (argument name and value).
+ * @return true if the handler was successful in starting the element it
+ * represents, false otherwise.
*/
- virtual void start(Variant::mapType &args) = 0;
+ virtual bool start(Variant::mapType &args) = 0;
/**
- * Called whenever the command for which this handler is defined ends.
+ * Called before the command for which this handler is defined ends (is
+ * forever removed from the stack).
*/
virtual void end() = 0;
/**
- * Called whenever raw data (int the form of a string) is available for the
- * Handler instance. In the default handler an exception is raised if the
- * received data contains non-whitespace characters.
+ * Called when a new field starts, while the handler is active. This
+ * function should return true if the field is supported, false otherwise.
+ * No error should be logged if the field cannot be started, the caller will
+ * take care of that (since it is always valid to start a default field,
+ * even though the corresponding structure does not have a field, as long as
+ * no data is fed into the field).
+ *
+ * @param isDefaultField is set to true if the field that is being started
+ * is the default/tree field. The handler should set the value of this
+ * variable to true if the referenced field is indeed the default field.
+ * @param isImplicit is set to true if the field is implicitly being started
+ * by the stack (this field always implies isDefaultField being set to
+ * true).
+ * @param fieldIndex is the numerical index of the field.
+ */
+ virtual bool fieldStart(bool &isDefaultField, bool isImplicit,
+ size_t fieldIndex) = 0;
+
+ /**
+ * Called when a previously opened field ends, while the handler is active.
+ * Note that a "fieldStart" and "fieldEnd" are always called alternately.
+ */
+ virtual void fieldEnd() = 0;
+
+ /**
+ * Called whenever an annotation starts while this handler is active. The
+ * function should return true if starting the annotation was successful,
+ * false otherwise.
+ *
+ * @param className is a string variant containing the name of the
+ * annotation class and the location of the name in the source code.
+ * @param args is a map from strings to variants (argument name and value).
+ * @return true if the mentioned annotation could be started here, false
+ * if an error occurred.
+ */
+ virtual bool annotationStart(Variant className, Variant::mapType &args) = 0;
+
+ /**
+ * Called whenever an annotation ends while this handler is active. The
+ * function should return true if ending the annotation was successful,
+ * false otherwise.
*
- * @param data is a pointer at the character data that is available for the
+ * @param className is a string variant containing the name of the
+ * annotation class and the location of the class name in the source code.
+ * @param elementName is a string variant containing the name of the
+ * annotation class and the location of the element name in the source code.
+ * @return true if the mentioned annotation could be started here, false if
+ * an error occurred.
+ */
+ virtual bool annotationEnd(Variant className, Variant elementName) = 0;
+
+ /**
+ * Called whenever raw data (int the form of a string) is available for the
* Handler instance.
- * @param field is the field number (the interpretation of this value
- * depends on the format that is being parsed).
+ *
+ * @param data is a string variant containing the character data and its
+ * location.
*/
- virtual void data(const std::string &data, int field);
+ virtual void data(Variant data) = 0;
};
/**
@@ -263,18 +282,20 @@ using HandlerConstructor = Handler *(*)(const HandlerData &handlerData);
/**
* The DefaultHandler class is used in case no element handler is specified in
- * the ParserState descriptor.
+ * the State descriptor.
*/
-class DefaultParserStateHandler : public ParserStateHandler {
+/*class EmptyHandler : public Handler {
public:
- using ParserStateHandler::ParserStateHandler;
+ using Handler::Handler;
void start(Variant::mapType &args) override;
void end() override;
static Handler *create(const HandlerData &handlerData);
-};
+};*/
+
+}
}
#endif /* _OUSIA_PARSER_STATE_HANDLER_HPP_ */
diff --git a/src/core/parser/generic/ParserStateStack.cpp b/src/core/parser/stack/Stack.cpp
index 8c32f17..1d83a68 100644
--- a/src/core/parser/generic/ParserStateStack.cpp
+++ b/src/core/parser/stack/Stack.cpp
@@ -20,14 +20,14 @@
#include <core/common/Utils.hpp>
#include <core/common/Exceptions.hpp>
-#include <core/model/Project.hpp>
+#include <core/parser/ParserScope.hpp>
-#include "ParserScope.hpp"
-#include "ParserStateStack.hpp"
+#include "Stack.hpp"
namespace ousia {
+namespace parser_stack {
-/* Class ParserStateStack */
+/* Class StateStack */
/**
* Returns an Exception that should be thrown when a currently invalid command
@@ -50,25 +50,25 @@ static LoggableException InvalidCommand(const std::string &name,
}
}
-ParserStateStack::ParserStateStack(
+StateStack::StateStack(
ParserContext &ctx,
- const std::multimap<std::string, const ParserState *> &states)
+ const std::multimap<std::string, const State *> &states)
: ctx(ctx), states(states)
{
}
-bool ParserStateStack::deduceState()
+bool StateStack::deduceState()
{
// Assemble all states
- std::vector<const ParserState *> states;
+ std::vector<const State *> states;
for (const auto &e : this->states) {
states.push_back(e.second);
}
// Fetch the type signature of the scope and derive all possible states,
// abort if no unique parser state was found
- std::vector<const ParserState *> possibleStates =
- ParserStateDeductor(ctx.getScope().getStackTypeSignature(), states)
+ std::vector<const State *> possibleStates =
+ StateDeductor(ctx.getScope().getStackTypeSignature(), states)
.deduce();
if (possibleStates.size() != 1) {
ctx.getLogger().error(
@@ -77,16 +77,16 @@ bool ParserStateStack::deduceState()
}
// Switch to this state by creating a dummy handler
- const ParserState *state = possibleStates[0];
+ const State *state = possibleStates[0];
Handler *handler =
DefaultHandler::create({ctx, "", *state, *state, SourceLocation{}});
stack.emplace(handler);
return true;
}
-std::set<std::string> ParserStateStack::expectedCommands()
+std::set<std::string> StateStack::expectedCommands()
{
- const ParserState *currentState = &(this->currentState());
+ const State *currentState = &(this->currentState());
std::set<std::string> res;
for (const auto &v : states) {
if (v.second->parents.count(currentState)) {
@@ -96,23 +96,23 @@ std::set<std::string> ParserStateStack::expectedCommands()
return res;
}
-const ParserState &ParserStateStack::currentState()
+const State &StateStack::currentState()
{
- return stack.empty() ? ParserStates::None : stack.top()->state();
+ return stack.empty() ? States::None : stack.top()->state();
}
-std::string ParserStateStack::currentCommandName()
+std::string StateStack::currentCommandName()
{
return stack.empty() ? std::string{} : stack.top()->name();
}
-const ParserState *ParserStateStack::findTargetState(const std::string &name)
+const State *StateStack::findTargetState(const std::string &name)
{
- const ParserState *currentState = &(this->currentState());
+ const State *currentState = &(this->currentState());
auto range = states.equal_range(name);
for (auto it = range.first; it != range.second; it++) {
- const ParserStateSet &parents = it->second->parents;
- if (parents.count(currentState) || parents.count(&ParserStates::All)) {
+ const StateSet &parents = it->second->parents;
+ if (parents.count(currentState) || parents.count(&States::All)) {
return it->second;
}
}
@@ -120,10 +120,10 @@ const ParserState *ParserStateStack::findTargetState(const std::string &name)
return nullptr;
}
-void ParserStateStack::start(const std::string &name, Variant::mapType &args,
+void StateStack::start(const std::string &name, Variant::mapType &args,
const SourceLocation &location)
{
- ParserState const *targetState = findTargetState(name);
+ State const *targetState = findTargetState(name);
// TODO: Andreas, please improve this.
// if (!Utils::isIdentifier(name)) {
// throw LoggableException(std::string("Invalid identifier \"") + name +
@@ -151,14 +151,14 @@ void ParserStateStack::start(const std::string &name, Variant::mapType &args,
stack.emplace(handler);
}
-void ParserStateStack::start(std::string name, const Variant::mapType &args,
+void StateStack::start(std::string name, const Variant::mapType &args,
const SourceLocation &location)
{
Variant::mapType argsCopy(args);
start(name, argsCopy);
}
-void ParserStateStack::end()
+void StateStack::end()
{
// Check whether the current command could be ended
if (stack.empty()) {
@@ -173,7 +173,7 @@ void ParserStateStack::end()
inst->end();
}
-void ParserStateStack::data(const std::string &data, int field)
+void StateStack::data(const std::string &data, int field)
{
// Check whether there is any command the data can be sent to
if (stack.empty()) {
@@ -184,4 +184,5 @@ void ParserStateStack::data(const std::string &data, int field)
stack.top()->data(data, field);
}
}
+}
diff --git a/src/core/parser/generic/ParserStateStack.hpp b/src/core/parser/stack/Stack.hpp
index b106475..b106475 100644
--- a/src/core/parser/generic/ParserStateStack.hpp
+++ b/src/core/parser/stack/Stack.hpp
diff --git a/src/core/parser/generic/ParserState.cpp b/src/core/parser/stack/State.cpp
index f635d86..d72f533 100644
--- a/src/core/parser/generic/ParserState.cpp
+++ b/src/core/parser/stack/State.cpp
@@ -16,88 +16,97 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "ParserState.hpp"
+#include "State.hpp"
namespace ousia {
+namespace parser_stack {
-/* Class ParserState */
+/* Class State */
-ParserState::ParserState() : elementHandler(nullptr) {}
+State::State() : elementHandler(nullptr) {}
-ParserState::ParserState(ParserStateSet parents, Arguments arguments,
+State::State(StateSet parents, Arguments arguments,
RttiSet createdNodeTypes,
- HandlerConstructor elementHandler)
+ HandlerConstructor elementHandler,
+ bool supportsAnnotations)
: parents(parents),
arguments(arguments),
createdNodeTypes(createdNodeTypes),
- elementHandler(elementHandler)
+ elementHandler(elementHandler),
+ supportsAnnotations(supportsAnnotations)
{
}
-ParserState::ParserState(const ParserStateBuilder &builder)
- : ParserState(builder.build())
+State::State(const StateBuilder &builder)
+ : State(builder.build())
{
}
-/* Class ParserStateBuilder */
+/* Class StateBuilder */
-ParserStateBuilder &ParserStateBuilder::copy(const ParserState &state)
+StateBuilder &StateBuilder::copy(const State &state)
{
this->state = state;
return *this;
}
-ParserStateBuilder &ParserStateBuilder::parent(const ParserState *parent)
+StateBuilder &StateBuilder::parent(const State *parent)
{
- state.parents = ParserStateSet{parent};
+ state.parents = StateSet{parent};
return *this;
}
-ParserStateBuilder &ParserStateBuilder::parents(const ParserStateSet &parents)
+StateBuilder &StateBuilder::parents(const StateSet &parents)
{
state.parents = parents;
return *this;
}
-ParserStateBuilder &ParserStateBuilder::arguments(const Arguments &arguments)
+StateBuilder &StateBuilder::arguments(const Arguments &arguments)
{
state.arguments = arguments;
return *this;
}
-ParserStateBuilder &ParserStateBuilder::createdNodeType(const Rtti *type)
+StateBuilder &StateBuilder::createdNodeType(const Rtti *type)
{
state.createdNodeTypes = RttiSet{type};
return *this;
}
-ParserStateBuilder &ParserStateBuilder::createdNodeTypes(const RttiSet &types)
+StateBuilder &StateBuilder::createdNodeTypes(const RttiSet &types)
{
state.createdNodeTypes = types;
return *this;
}
-ParserStateBuilder &ParserStateBuilder::elementHandler(
+StateBuilder &StateBuilder::elementHandler(
HandlerConstructor elementHandler)
{
state.elementHandler = elementHandler;
return *this;
}
-const ParserState &ParserStateBuilder::build() const { return state; }
+StateBuilder &StateBuilder::supportsAnnotations(bool supportsAnnotations)
+{
+ state.supportsAnnotations = supportsAnnotations;
+ return *this;
+}
-/* Class ParserStateDeductor */
+const State &StateBuilder::build() const { return state; }
-ParserStateDeductor::ParserStateDeductor(
+/* Class StateDeductor */
+
+StateDeductor::StateDeductor(
std::vector<const Rtti *> signature,
- std::vector<const ParserState *> states)
+ std::vector<const State *> states)
: tbl(signature.size()),
signature(std::move(signature)),
states(std::move(states))
{
}
-bool ParserStateDeductor::isActive(size_t d, const ParserState *s)
+bool StateDeductor::isActive(size_t d, const State *s)
{
// Lookup the "active" state of (d, s), if it was not already set
// (e.second is true) we'll have to calculate it
@@ -123,7 +132,7 @@ bool ParserStateDeductor::isActive(size_t d, const ParserState *s)
// Check whether any of the parent nodes were active -- either for
// the previous element (if this one is generative) or for the
// current element (assuming this node was not generative)
- for (const ParserState *parent : s->parents) {
+ for (const State *parent : s->parents) {
if ((isGenerative && isActive(d - 1, parent)) ||
isActive(d, parent)) {
res = true;
@@ -136,9 +145,9 @@ bool ParserStateDeductor::isActive(size_t d, const ParserState *s)
return res;
}
-std::vector<const ParserState *> ParserStateDeductor::deduce()
+std::vector<const State *> StateDeductor::deduce()
{
- std::vector<const ParserState *> res;
+ std::vector<const State *> res;
if (!signature.empty()) {
const size_t D = signature.size();
for (auto s : states) {
@@ -153,9 +162,10 @@ std::vector<const ParserState *> ParserStateDeductor::deduce()
/* Constant initializations */
-namespace ParserStates {
-const ParserState All;
-const ParserState None;
+namespace States {
+const State All;
+const State None;
+}
}
}
diff --git a/src/core/parser/generic/ParserState.hpp b/src/core/parser/stack/State.hpp
index 6487fdd..ea326ec 100644
--- a/src/core/parser/generic/ParserState.hpp
+++ b/src/core/parser/stack/State.hpp
@@ -17,10 +17,10 @@
*/
/**
- * @file ParserState.hpp
+ * @file State.hpp
*
- * Defines the ParserState class used within the ParserStack pushdown
- * automaton and the ParserStateBuilder class for convenient construction of
+ * Defines the State class used within the ParserStack pushdown
+ * automaton and the StateBuilder class for convenient construction of
* such classes.
*
* @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de)
@@ -35,10 +35,11 @@
#include <core/common/Argument.hpp>
namespace ousia {
+namespace parser_stack {
// Forward declarations
-class ParserStateBuilder;
-class ParserState;
+class StateBuilder;
+class State;
class HandlerData;
class Handler;
using HandlerConstructor = Handler *(*)(const HandlerData &handlerData);
@@ -47,17 +48,17 @@ using HandlerConstructor = Handler *(*)(const HandlerData &handlerData);
* Set of pointers of parser states -- used for specifying a set of parent
* states.
*/
-using ParserStateSet = std::unordered_set<const ParserState *>;
+using StateSet = std::unordered_set<const State *>;
/**
- * Class used for the complete specification of a ParserState. Stores possible
+ * Class used for the complete specification of a State. Stores possible
* parent states, state handlers and arguments to be passed to that state.
*/
-struct ParserState {
+struct State {
/**
* Vector containing all possible parent states.
*/
- ParserStateSet parents;
+ StateSet parents;
/**
* Descriptor of the arguments that should be passed to the handler.
@@ -66,8 +67,8 @@ struct ParserState {
/**
* Set containing the types of the nodes that may be created in this
- * ParserState. This information is needed for Parsers to reconstruct the
- * current ParserState from a given ParserScope when a file is included.
+ * State. This information is needed for Parsers to reconstruct the
+ * current State from a given ParserScope when a file is included.
*/
RttiSet createdNodeTypes;
@@ -79,109 +80,119 @@ struct ParserState {
HandlerConstructor elementHandler;
/**
+ * Set to true if this handler does support annotations. This is almost
+ * always false (e.g. all description handlers), except for document
+ * element handlers.
+ */
+ bool supportsAnnotations;
+
+ /**
* Default constructor, initializes the handlers with nullptr.
*/
- ParserState();
+ State();
/**
- * Constructor taking values for all fields. Use the ParserStateBuilder
- * class for a more convenient construction of ParserState instances.
+ * Constructor taking values for all fields. Use the StateBuilder
+ * class for a more convenient construction of State instances.
*
* @param parents is a vector containing all possible parent states.
* @param arguments is a descriptor of arguments that should be passed to
* the handler.
* @param createdNodeTypes is a set containing the types of the nodes tha
- * may be created in this ParserState. This information is needed for
- * Parsers to reconstruct the current ParserState from a given ParserScope
+ * may be created in this State. This information is needed for
+ * Parsers to reconstruct the current State from a given ParserScope
* when a file is included.
* @param elementHandler is a pointer at a function which creates a new
* concrete Handler instance for the elements described by this state. May
* be nullptr in which case no handler instance is created.
+ * @param supportsAnnotations specifies whether annotations are supported
+ * here at all.
*/
- ParserState(ParserStateSet parents, Arguments arguments = Arguments{},
+ State(StateSet parents, Arguments arguments = Arguments{},
RttiSet createdNodeTypes = RttiSet{},
- HandlerConstructor elementHandler = nullptr);
+ HandlerConstructor elementHandler = nullptr,
+ bool supportsAnnotations = false);
/**
- * Creates this ParserState from the given ParserStateBuilder instance.
+ * Creates this State from the given StateBuilder instance.
*/
- ParserState(const ParserStateBuilder &builder);
+ State(const StateBuilder &builder);
};
/**
- * The ParserStateBuilder class is a class used for conveniently building new
- * ParserState instances.
+ * The StateBuilder class is a class used for conveniently building new
+ * State instances.
*/
-class ParserStateBuilder {
+class StateBuilder {
private:
/**
- * ParserState instance that is currently being built by the
- * ParserStateBuilder.
+ * State instance that is currently being built by the
+ * StateBuilder.
*/
- ParserState state;
+ State state;
public:
/**
- * Copies the ParserState instance and uses it as internal state. Overrides
- * all changes made by the ParserStateBuilder.
+ * Copies the State instance and uses it as internal state. Overrides
+ * all changes made by the StateBuilder.
*
* @param state is the state that should be copied.
- * @return a reference at this ParserStateBuilder instance for method
+ * @return a reference at this StateBuilder instance for method
* chaining.
*/
- ParserStateBuilder &copy(const ParserState &state);
+ StateBuilder &copy(const State &state);
/**
* Sets the possible parent states to the single given parent element.
*
- * @param parent is a pointer at the parent ParserState instance that should
+ * @param parent is a pointer at the parent State instance that should
* be the possible parent state.
- * @return a reference at this ParserStateBuilder instance for method
+ * @return a reference at this StateBuilder instance for method
* chaining.
*/
- ParserStateBuilder &parent(const ParserState *parent);
+ StateBuilder &parent(const State *parent);
/**
- * Sets the ParserState instances in the given ParserStateSet as the list of
+ * Sets the State instances in the given StateSet as the list of
* supported parent states.
*
- * @param parents is a set of pointers at ParserState instances that should
+ * @param parents is a set of pointers at State instances that should
* be the possible parent states.
- * @return a reference at this ParserStateBuilder instance for method
+ * @return a reference at this StateBuilder instance for method
* chaining.
*/
- ParserStateBuilder &parents(const ParserStateSet &parents);
+ StateBuilder &parents(const StateSet &parents);
/**
* Sets the arguments that should be passed to the parser state handler to
* those given as argument.
*
* @param arguments is the Arguments instance describing the Arguments that
- * should be parsed to a Handler for this ParserState.
- * @return a reference at this ParserStateBuilder instance for method
+ * should be parsed to a Handler for this State.
+ * @return a reference at this StateBuilder instance for method
* chaining.
*/
- ParserStateBuilder &arguments(const Arguments &arguments);
+ StateBuilder &arguments(const Arguments &arguments);
/**
* Sets the Node types this state may produce to the given Rtti descriptor.
*
* @param type is the Rtti descriptor of the Type that may be produced by
* this state.
- * @return a reference at this ParserStateBuilder instance for method
+ * @return a reference at this StateBuilder instance for method
* chaining.
*/
- ParserStateBuilder &createdNodeType(const Rtti *type);
+ StateBuilder &createdNodeType(const Rtti *type);
/**
* Sets the Node types this state may produce to the given Rtti descriptors.
*
* @param types is a set of Rtti descriptors of the Types that may be
* produced by this state.
- * @return a reference at this ParserStateBuilder instance for method
+ * @return a reference at this StateBuilder instance for method
* chaining.
*/
- ParserStateBuilder &createdNodeTypes(const RttiSet &types);
+ StateBuilder &createdNodeTypes(const RttiSet &types);
/**
* Sets the constructor for the element handler. The constructor creates a
@@ -191,31 +202,42 @@ public:
*
* @param elementHandler is the HandlerConstructor that should create a
* new Handler instance.
- * @return a reference at this ParserStateBuilder instance for method
+ * @return a reference at this StateBuilder instance for method
* chaining.
*/
- ParserStateBuilder &elementHandler(HandlerConstructor elementHandler);
+ StateBuilder &elementHandler(HandlerConstructor elementHandler);
/**
- * Returns a reference at the internal ParserState instance that was built
- * using the ParserStateBuilder.
+ * Sets the state of the "supportsAnnotations" flags (default value is
+ * false)
*
- * @return the built ParserState.
+ * @param supportsAnnotations should be set to true, if annotations are
+ * supported for the handlers associated with this document.
+ * @return a reference at this StateBuilder instance for method
+ * chaining.
*/
- const ParserState &build() const;
+ StateBuilder &supportsAnnotations(bool supportsAnnotations);
+
+ /**
+ * Returns a reference at the internal State instance that was built
+ * using the StateBuilder.
+ *
+ * @return the built State.
+ */
+ const State &build() const;
};
/**
- * Class used to deduce the ParserState a Parser is currently in based on the
+ * Class used to deduce the State a Parser is currently in based on the
* types of the Nodes that currently are on the ParserStack. Uses dynamic
* programming in order to solve this problem.
*/
-class ParserStateDeductor {
+class StateDeductor {
public:
/**
* Type containing the dynamic programming table.
*/
- using Table = std::vector<std::unordered_map<const ParserState *, bool>>;
+ using Table = std::vector<std::unordered_map<const State *, bool>>;
private:
/**
@@ -231,7 +253,7 @@ private:
/**
* List of states that should be checked for being active.
*/
- const std::vector<const ParserState *> states;
+ const std::vector<const State *> states;
/**
* Used internally to check whether the given parser stack s may have been
@@ -239,20 +261,20 @@ private:
*
* @param d is the signature element.
* @param s is the parser state.
- * @return true if the the given ParserState may have been active.
+ * @return true if the the given State may have been active.
*/
- bool isActive(size_t d, const ParserState *s);
+ bool isActive(size_t d, const State *s);
public:
/**
- * Constructor of the ParserStateDeductor class.
+ * Constructor of the StateDeductor class.
*
* @param signature a Node type signature describing the types of the nodes
* which currently reside on e.g. the ParserScope stack.
* @param states is a list of states that should be checked.
*/
- ParserStateDeductor(std::vector<const Rtti *> signature,
- std::vector<const ParserState *> states);
+ StateDeductor(std::vector<const Rtti *> signature,
+ std::vector<const State *> states);
/**
* Selects all active states from the given states. Only considers those
@@ -260,23 +282,24 @@ public:
*
* @return a list of states that may actually have been active.
*/
- std::vector<const ParserState *> deduce();
+ std::vector<const State *> deduce();
};
/**
- * The ParserStates namespace contains all the global state constants used
+ * The States namespace contains all the global state constants used
* in the ParserStack class.
*/
-namespace ParserStates {
+namespace States {
/**
* State representing all states.
*/
-extern const ParserState All;
+extern const State All;
/**
* State representing the initial state.
*/
-extern const ParserState None;
+extern const State None;
+}
}
}
diff --git a/test/core/parser/ParserStateTest.cpp b/test/core/parser/ParserStateTest.cpp
deleted file mode 100644
index 91d8dcd..0000000
--- a/test/core/parser/ParserStateTest.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- Ousía
- Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <gtest/gtest.h>
-
-#include <core/common/Rtti.hpp>
-#include <core/parser/ParserState.hpp>
-
-namespace ousia {
-
-static const Rtti t1;
-static const Rtti t2;
-static const Rtti t3;
-static const Rtti t4;
-static const Rtti t5;
-
-static const ParserState s1 = ParserStateBuilder().createdNodeType(&t1);
-static const ParserState s2a =
- ParserStateBuilder().parent(&s1).createdNodeType(&t2);
-static const ParserState s2b =
- ParserStateBuilder().parent(&s1).createdNodeType(&t2);
-static const ParserState s3 =
- ParserStateBuilder().parents({&s2a, &s1}).createdNodeType(&t3);
-static const ParserState s4 =
- ParserStateBuilder().parent(&s3).createdNodeType(&t4);
-static const ParserState s5 =
- ParserStateBuilder().parent(&s2b).createdNodeType(&t5);
-
-TEST(ParserStateDeductor, deduce)
-{
- using Result = std::vector<const ParserState *>;
- using Signature = std::vector<const Rtti *>;
- std::vector<const ParserState *> states{&s1, &s2a, &s2b, &s3, &s4, &s5};
-
- // Should not crash on empty signature
- ASSERT_EQ(Result{}, ParserStateDeductor(Signature{}, states).deduce());
-
- // Try repeating signature elements
- ASSERT_EQ(Result({&s1}),
- ParserStateDeductor(Signature({&t1}), states).deduce());
- ASSERT_EQ(Result({&s1}),
- ParserStateDeductor(Signature({&t1, &t1}), states).deduce());
- ASSERT_EQ(Result({&s1}),
- ParserStateDeductor(Signature({&t1, &t1, &t1}), states).deduce());
-
- // Go to another state
- ASSERT_EQ(Result({&s2a, &s2b}),
- ParserStateDeductor(Signature({&t1, &t1, &t2}), states).deduce());
- ASSERT_EQ(Result({&s4}),
- ParserStateDeductor(Signature({&t1, &t3, &t4}), states).deduce());
-
- // Skip one state
- ASSERT_EQ(Result({&s4}),
- ParserStateDeductor(Signature({&t2, &t4}), states).deduce());
-
- // Impossible signature
- ASSERT_EQ(Result({}),
- ParserStateDeductor(Signature({&t4, &t5}), states).deduce());
-
-}
-}
-
diff --git a/test/core/parser/stack/StateTest.cpp b/test/core/parser/stack/StateTest.cpp
new file mode 100644
index 0000000..e503d30
--- /dev/null
+++ b/test/core/parser/stack/StateTest.cpp
@@ -0,0 +1,79 @@
+/*
+ Ousía
+ Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <gtest/gtest.h>
+
+#include <core/common/Rtti.hpp>
+#include <core/parser/stack/State.hpp>
+
+namespace ousia {
+namespace parser_stack {
+
+static const Rtti t1;
+static const Rtti t2;
+static const Rtti t3;
+static const Rtti t4;
+static const Rtti t5;
+
+static const State s1 = StateBuilder().createdNodeType(&t1);
+static const State s2a =
+ StateBuilder().parent(&s1).createdNodeType(&t2);
+static const State s2b =
+ StateBuilder().parent(&s1).createdNodeType(&t2);
+static const State s3 =
+ StateBuilder().parents({&s2a, &s1}).createdNodeType(&t3);
+static const State s4 =
+ StateBuilder().parent(&s3).createdNodeType(&t4);
+static const State s5 =
+ StateBuilder().parent(&s2b).createdNodeType(&t5);
+
+TEST(StateDeductor, deduce)
+{
+ using Result = std::vector<const State *>;
+ using Signature = std::vector<const Rtti *>;
+ std::vector<const State *> states{&s1, &s2a, &s2b, &s3, &s4, &s5};
+
+ // Should not crash on empty signature
+ ASSERT_EQ(Result{}, StateDeductor(Signature{}, states).deduce());
+
+ // Try repeating signature elements
+ ASSERT_EQ(Result({&s1}),
+ StateDeductor(Signature({&t1}), states).deduce());
+ ASSERT_EQ(Result({&s1}),
+ StateDeductor(Signature({&t1, &t1}), states).deduce());
+ ASSERT_EQ(Result({&s1}),
+ StateDeductor(Signature({&t1, &t1, &t1}), states).deduce());
+
+ // Go to another state
+ ASSERT_EQ(Result({&s2a, &s2b}),
+ StateDeductor(Signature({&t1, &t1, &t2}), states).deduce());
+ ASSERT_EQ(Result({&s4}),
+ StateDeductor(Signature({&t1, &t3, &t4}), states).deduce());
+
+ // Skip one state
+ ASSERT_EQ(Result({&s4}),
+ StateDeductor(Signature({&t2, &t4}), states).deduce());
+
+ // Impossible signature
+ ASSERT_EQ(Result({}),
+ StateDeductor(Signature({&t4, &t5}), states).deduce());
+
+}
+}
+}
+