diff options
author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-01-27 15:38:38 +0100 |
---|---|---|
committer | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-01-27 15:38:38 +0100 |
commit | 06eaf84b383affedbea5c0dffe0dc5e808d3b7b0 (patch) | |
tree | 101a6cd2abe0028d492240e008ca5e45e515d822 /src/core/parser | |
parent | 3334e1ba2417fb726f52963270f1367fac45265c (diff) |
Added fork, join, checkUnwound and getTopLevelNodes functionality to ParserScope and using it in the Manager
Diffstat (limited to 'src/core/parser')
-rw-r--r-- | src/core/parser/ParserScope.cpp | 86 | ||||
-rw-r--r-- | src/core/parser/ParserScope.hpp | 88 |
2 files changed, 150 insertions, 24 deletions
diff --git a/src/core/parser/ParserScope.cpp b/src/core/parser/ParserScope.cpp index d2f5800..df123df 100644 --- a/src/core/parser/ParserScope.cpp +++ b/src/core/parser/ParserScope.cpp @@ -16,6 +16,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include <core/common/Exceptions.hpp> #include <core/common/Utils.hpp> #include "ParserScope.hpp" @@ -24,6 +25,12 @@ namespace ousia { /* Class ParserScopeBase */ +ParserScopeBase::ParserScopeBase() {} + +ParserScopeBase::ParserScopeBase(const NodeVector<Node> &nodes) : nodes(nodes) +{ +} + Rooted<Node> ParserScopeBase::resolve(const std::vector<std::string> &path, const Rtti &type, Logger &logger) { @@ -40,7 +47,8 @@ Rooted<Node> ParserScopeBase::resolve(const std::vector<std::string> &path, if (res.size() > 1) { logger.error(std::string("The reference \"") + Utils::join(path, ".") + ("\" is ambigous!")); - logger.note("Referenced objects are:", SourceLocation{}, MessageMode::NO_CONTEXT); + logger.note("Referenced objects are:", SourceLocation{}, + MessageMode::NO_CONTEXT); for (const ResolutionResult &r : res) { logger.note(Utils::join(r.path(), "."), *(r.node)); } @@ -82,18 +90,73 @@ bool DeferredResolution::resolve(Logger &logger) /* Class ParserScope */ -void ParserScope::push(Handle<Node> node) { nodes.push_back(node); } +ParserScope::ParserScope(const NodeVector<Node> &nodes) + : ParserScopeBase(nodes), topLevelDepth(nodes.size()) +{ +} + +bool ParserScope::checkUnwound(Logger &logger) const +{ + if (nodes.size() != topLevelDepth) { + logger.error("Not all open elements have been closed!", + SourceLocation{}, MessageMode::NO_CONTEXT); + logger.note("Still open elements are: ", SourceLocation{}, + MessageMode::NO_CONTEXT); + for (size_t i = topLevelDepth + 1; i < nodes.size(); i++) { + logger.note(std::string("Element of interal type ") + + nodes[i]->type().name + + std::string(" defined here:"), + nodes[i]->getLocation()); + } + return false; + } + return true; +} + +ParserScope ParserScope::fork() { return ParserScope{nodes}; } + +bool ParserScope::join(const ParserScope &fork, Logger &logger) +{ + // Make sure the fork has been unwound + if (!fork.checkUnwound(logger)) { + return false; + } + + // Insert the deferred resolutions of the fork into our own deferred + // resolution list + deferred.insert(deferred.end(), fork.deferred.begin(), fork.deferred.end()); + return true; +} + +ParserScope::ParserScope() : topLevelDepth(0) {} + +void ParserScope::push(Handle<Node> node) +{ + if (nodes.size() == topLevelDepth) { + topLevelNodes.push_back(node); + } + nodes.push_back(node); +} + +void ParserScope::pop() +{ + if (nodes.size() == topLevelDepth) { + throw LoggableException{"No element here to end!"}; + } + nodes.pop_back(); +} -void ParserScope::pop() { nodes.pop_back(); } +NodeVector<Node> ParserScope::getTopLevelNodes() const { return topLevelNodes; } Rooted<Node> ParserScope::getRoot() const { return nodes.front(); } -Rooted<Node> ParserScope::getLeaf() { return nodes.back(); } +Rooted<Node> ParserScope::getLeaf() const { return nodes.back(); } -bool ParserScope::resolve(const std::vector<std::string> &path, const Rtti &type, - Logger &logger, ResolutionImposterCallback imposterCallback, - ResolutionResultCallback resultCallback, - const SourceLocation &location) +bool ParserScope::resolve(const std::vector<std::string> &path, + const Rtti &type, Logger &logger, + ResolutionImposterCallback imposterCallback, + ResolutionResultCallback resultCallback, + const SourceLocation &location) { if (!resolve(path, type, logger, resultCallback, location)) { resultCallback(imposterCallback(), logger); @@ -102,9 +165,10 @@ bool ParserScope::resolve(const std::vector<std::string> &path, const Rtti &type return true; } -bool ParserScope::resolve(const std::vector<std::string> &path, const Rtti &type, - Logger &logger, ResolutionResultCallback resultCallback, - const SourceLocation &location) +bool ParserScope::resolve(const std::vector<std::string> &path, + const Rtti &type, Logger &logger, + ResolutionResultCallback resultCallback, + const SourceLocation &location) { Rooted<Node> res = ParserScopeBase::resolve(path, type, logger); if (res != nullptr) { diff --git a/src/core/parser/ParserScope.hpp b/src/core/parser/ParserScope.hpp index c1369dd..191d08b 100644 --- a/src/core/parser/ParserScope.hpp +++ b/src/core/parser/ParserScope.hpp @@ -31,7 +31,8 @@ /** * @file ParserScope.hpp * - * Contains the ParserScope class used for resolving references based on the current + * Contains the ParserScope class used for resolving references based on the + *current * parser state. * * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de) @@ -72,16 +73,17 @@ public: /** * Default constructor, creates an empty ParserScope instance. */ - ParserScopeBase() {} + ParserScopeBase(); /** - * Creates a new instance of the ParserScopeBase class, copying the the given + * Creates a new instance of the ParserScopeBase class, copying the the + *given * nodes as initial start value of the node stack. This could for example * be initialized with the path of a node. * * @param nodes is a node vector containing the current node stack. */ - ParserScopeBase(const NodeVector<Node> &nodes) : nodes(nodes) {} + ParserScopeBase(const NodeVector<Node> &nodes); /** * Tries to resolve a node for the given type and path for all nodes that @@ -94,8 +96,8 @@ public: * @return a reference at a resolved node or nullptr if no node could be * found. */ - Rooted<Node> resolve(const std::vector<std::string> &path, - const Rtti &type, Logger &logger); + Rooted<Node> resolve(const std::vector<std::string> &path, const Rtti &type, + Logger &logger); }; /** @@ -147,8 +149,7 @@ public: * @param location is the location at which the resolution was triggered. */ DeferredResolution(const NodeVector<Node> &nodes, - const std::vector<std::string> &path, - const Rtti &type, + const std::vector<std::string> &path, const Rtti &type, ResolutionResultCallback resultCallback, const SourceLocation &location = SourceLocation{}); @@ -177,12 +178,63 @@ private: */ std::list<DeferredResolution> deferred; + /** + * Depth of the "nodes" list when the ParserScope was created. + */ + size_t topLevelDepth; + + /** + * List of a all nodes that have been pushed onto the scope at the top level + * depth. + */ + NodeVector<Node> topLevelNodes; + + /** + * Private constructor used to create a ParserScope fork. + */ + ParserScope(const NodeVector<Node> &nodes); + public: /** - * Default constructor of the ParserScope class, creates an empty ParserScope with no - * element on the internal stack. + * Default constructor of the ParserScope class, creates an empty + * ParserScope with no element on the internal stack. + */ + ParserScope(); + + /** + * Makes sure all elements on the scope have been unwound. Loggs an error + * message if this is not the case and returns false. + * + * @param logger is the Logger instance to which information in case of + * failure should be written. + * @return true if the stack is unwound, false otherwise. */ - ParserScope() {} + bool checkUnwound(Logger &logger) const; + + /** + * Returns a new ParserScope instance with a copy of the current node stack + * but empty deferred resolutions list and empty topLevelNodes. + * + * @return a forked ParserScope instance, which starts with a copy of the + * node stack. + */ + ParserScope fork(); + + /** + * Joins a previously forked ParserScope instance with this ParserScope. + * Copies all pending deferred resolutions from this ParserScope instance. + * Joining only works if the node stack of the given ParserScope has the + * same depth as the node stack of this ParserScope instance (has been + * unwound). This is assured by calling the "checkUnwound" function of + * the fork. + * + * @param fork is the ParserScope fork that should be joined with this + * ParserScope instance. + * @param logger is the Logger instance to which information in case of + * failure should be written. + * @return true if the operation was successful, false otherwise. + */ + bool join(const ParserScope &fork, Logger &logger); /** * Pushes a new node onto the scope. @@ -197,6 +249,15 @@ public: void pop(); /** + * Returns the top-level nodes. These are the nodes that are pushed onto the + * scope instance while the node stack has the depth it had during the + * creation of this ParserScope instance. + * + * @return a node vector containing the top-level nodes. + */ + NodeVector<Node> getTopLevelNodes() const; + + /** * Returns the top-most Node instance in the ParserScope hirarchy. * * @return a reference at the root node. @@ -204,12 +265,13 @@ public: Rooted<Node> getRoot() const; /** - * Returns the bottom-most Node instance in the ParserScope hirarchy, e.g. the + * Returns the bottom-most Node instance in the ParserScope hirarchy, e.g. + *the * node that was pushed last onto the stack. * * @return a reference at the leaf node. */ - Rooted<Node> getLeaf(); + Rooted<Node> getLeaf() const; /** * Tries to resolve a node for the given type and path for all nodes |