/*
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 .
*/
#include "State.hpp"
namespace ousia {
namespace parser_stack {
/* Class State */
State::State() : elementHandler(nullptr) {}
State::State(StateSet parents, Arguments arguments,
RttiSet createdNodeTypes,
HandlerConstructor elementHandler,
bool supportsAnnotations)
: parents(parents),
arguments(arguments),
createdNodeTypes(createdNodeTypes),
elementHandler(elementHandler),
supportsAnnotations(supportsAnnotations)
{
}
State::State(const StateBuilder &builder)
: State(builder.build())
{
}
/* Class StateBuilder */
StateBuilder &StateBuilder::copy(const State &state)
{
this->state = state;
return *this;
}
StateBuilder &StateBuilder::parent(const State *parent)
{
state.parents = StateSet{parent};
return *this;
}
StateBuilder &StateBuilder::parents(const StateSet &parents)
{
state.parents = parents;
return *this;
}
StateBuilder &StateBuilder::arguments(const Arguments &arguments)
{
state.arguments = arguments;
return *this;
}
StateBuilder &StateBuilder::createdNodeType(const Rtti *type)
{
state.createdNodeTypes = RttiSet{type};
return *this;
}
StateBuilder &StateBuilder::createdNodeTypes(const RttiSet &types)
{
state.createdNodeTypes = types;
return *this;
}
StateBuilder &StateBuilder::elementHandler(
HandlerConstructor elementHandler)
{
state.elementHandler = elementHandler;
return *this;
}
StateBuilder &StateBuilder::supportsAnnotations(bool supportsAnnotations)
{
state.supportsAnnotations = supportsAnnotations;
return *this;
}
const State &StateBuilder::build() const { return state; }
/* Class StateDeductor */
StateDeductor::StateDeductor(
std::vector signature,
std::vector states)
: tbl(signature.size()),
signature(std::move(signature)),
states(std::move(states))
{
}
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
auto e = tbl[d].emplace(s, false);
bool &res = e.first->second;
if (!e.second) {
return res;
}
// Check whether this node is generative (may have produced the Node
// described by the current Signature element)
bool isGenerative = signature[d]->isOneOf(s->createdNodeTypes);
if (isGenerative && d == 0) {
// End of recursion -- the last signature element is reached and the
// node was generative
res = true;
} else {
// Try repetition of this node
if (isGenerative && isActive(d - 1, s)) {
res = true;
} else {
// 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 State *parent : s->parents) {
if ((isGenerative && isActive(d - 1, parent)) ||
isActive(d, parent)) {
res = true;
break;
}
}
}
}
return res;
}
std::vector StateDeductor::deduce()
{
std::vector res;
if (!signature.empty()) {
const size_t D = signature.size();
for (auto s : states) {
if (signature[D - 1]->isOneOf(s->createdNodeTypes) &&
isActive(D - 1, s)) {
res.push_back(s);
}
}
}
return res;
}
/* Constant initializations */
namespace States {
const State All;
const State None;
}
}
}