diff options
author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-02-03 02:27:55 +0100 |
---|---|---|
committer | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-02-03 02:27:55 +0100 |
commit | c9cb8e1a0cda97511742211c8abab89b35493560 (patch) | |
tree | a32de722f69b2be77b6edd24b5f7e81175741999 /src/core/parser/ParserState.cpp | |
parent | 66e9838c47b58810cb0bb6c67c32fb119eb50797 (diff) |
Implemented ParserStateDeductor which is used to deduce the current ParserState given the Type signature extracted from a ParserScope.
Diffstat (limited to 'src/core/parser/ParserState.cpp')
-rw-r--r-- | src/core/parser/ParserState.cpp | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/core/parser/ParserState.cpp b/src/core/parser/ParserState.cpp index b0b02d2..9d3aa7e 100644 --- a/src/core/parser/ParserState.cpp +++ b/src/core/parser/ParserState.cpp @@ -25,10 +25,12 @@ namespace ousia { ParserState::ParserState() : elementHandler(nullptr), childHandler(nullptr) {} ParserState::ParserState(ParserStateSet parents, Arguments arguments, + RttiSet createdNodeTypes, HandlerConstructor elementHandler, HandlerConstructor childHandler) : parents(parents), arguments(arguments), + createdNodeTypes(createdNodeTypes), elementHandler(elementHandler), childHandler(childHandler) { @@ -65,6 +67,18 @@ ParserStateBuilder &ParserStateBuilder::arguments(const Arguments &arguments) return *this; } +ParserStateBuilder &ParserStateBuilder::createdNodeType(const Rtti *type) +{ + state.createdNodeTypes = RttiSet{type}; + return *this; +} + +ParserStateBuilder &ParserStateBuilder::createdNodeTypes(const RttiSet &types) +{ + state.createdNodeTypes = types; + return *this; +} + ParserStateBuilder &ParserStateBuilder::elementHandler( HandlerConstructor elementHandler) { @@ -81,6 +95,71 @@ ParserStateBuilder &ParserStateBuilder::childHandler( const ParserState &ParserStateBuilder::build() const { return state; } +/* Class ParserStateDeductor */ + +ParserStateDeductor::ParserStateDeductor( + std::vector<const Rtti *> signature, + std::vector<const ParserState *> states) + : tbl(signature.size()), + signature(std::move(signature)), + states(std::move(states)) +{ +} + +bool ParserStateDeductor::isActive(size_t d, const ParserState *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 ParserState *parent : s->parents) { + if ((isGenerative && isActive(d - 1, parent)) || + isActive(d, parent)) { + res = true; + break; + } + } + } + } + + return res; +} + +std::vector<const ParserState *> ParserStateDeductor::deduce() +{ + std::vector<const ParserState *> 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 ParserStates { |