/*
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 .
*/
#ifndef _OUSIA_PARSER_SCOPE_H_
#define _OUSIA_PARSER_SCOPE_H_
#include
#include
/**
* @file Scope.hpp
*
* Contains the Scope class used for resolving references based on the current
* parser state.
*
* @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de)
*/
namespace ousia {
namespace parser {
class Scope;
/**
* The ScopedScope class takes care of pushing a Node instance into the
* name resolution stack of a Scope instance and poping this node once the
* ScopedScope instance is deletes. This way you cannot forget to pop a Node
* from a Scope instance as this operation is performed automatically.
*/
class ScopedScope {
private:
/**
* Reference at the backing scope instance.
*/
Scope *scope;
public:
/**
* Creates a new ScopedScope instance.
*
* @param scope is the backing Scope instance.
* @param node is the Node instance that should be pushed onto the stack of
* the Scope instance.
*/
ScopedScope(Scope *scope, Handle node);
/**
* Pops the Node given in the constructor form the stack of the Scope
* instance.
*/
~ScopedScope();
/**
* Copying a ScopedScope is invalid.
*/
ScopedScope(const ScopedScope &) = delete;
/**
* Move constructor of the ScopedScope class.
*/
ScopedScope(ScopedScope &&);
/**
* Provides access at the underlying Scope instance.
*/
Scope *operator->() { return scope; }
/**
* Provides access at the underlying Scope instance.
*/
Scope &operator*() { return *scope; }
};
/**
* Provides an interface for document parsers to resolve references based on the
* current position in the created document tree. The Scope class itself is
* represented as a chain of Scope objects where each element has a reference to
* a Node object attached to it. The descend method can be used to add a new
* scope element to the chain.
*/
class Scope {
private:
std::deque> nodes;
public:
/**
* Constructor of the Scope class.
*
* @param rootNode is the top-most Node from which elements can be looked
* up.
*/
Scope(Handle rootNode) { nodes.push_back(rootNode); }
/**
* Pushes a new node onto the scope.
*
* @param node is the node that should be used for local lookup.
*/
void push(Handle node) { nodes.push_back(node); }
/**
* Removes the last pushed node from the scope.
*/
void pop() { nodes.pop_back(); }
/**
* Returns a ScopedScope instance, which automatically pushes the given node
* into the Scope stack and pops it once the ScopedScope is destroyed.
*/
ScopedScope descend(Handle node) { return ScopedScope{this, node}; }
/**
* Returns the top-most Node instance in the Scope hirarchy.
*
* @return a reference at the root node.
*/
Rooted getRoot() { return nodes.front(); }
/**
* Returns the bottom-most Node instance in the Scope hirarchy, e.g. the
* node that was pushed last onto the stack.
*
* @return a reference at the leaf node.
*/
Rooted getLeaf() { return nodes.back(); }
};
/* Class ScopedScope -- inline declaration of some methods */
inline ScopedScope::ScopedScope(Scope *scope, Handle node) : scope(scope)
{
scope->push(node);
}
inline ScopedScope::~ScopedScope()
{
if (scope) {
scope->pop();
}
}
inline ScopedScope::ScopedScope(ScopedScope &&s)
{
scope = s.scope;
s.scope = nullptr;
}
}
}
#endif /* _OUSIA_PARSER_SCOPE_H_ */