tmp
This commit is contained in:
parent
d2bb8cdd6a
commit
312419936e
6 changed files with 128 additions and 71 deletions
|
|
@ -8,9 +8,8 @@
|
||||||
namespace tp {
|
namespace tp {
|
||||||
|
|
||||||
// Non-Deterministic Finite-State Automata
|
// Non-Deterministic Finite-State Automata
|
||||||
template <typename tAlphabetType, typename tStateType, tStateType tNoStateVal, tStateType tFailedStateVal>
|
template <typename tAlphabetType, typename tStateType>
|
||||||
class NFA {
|
class NFA {
|
||||||
static_assert(TypeTraits<tAlphabetType>::isIntegral, "tAlphabetType must be enumerable.");
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
struct Vertex;
|
struct Vertex;
|
||||||
|
|
@ -32,7 +31,8 @@ namespace tp {
|
||||||
|
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
List<Edge> edges;
|
List<Edge> edges;
|
||||||
tStateType termination_state = tNoStateVal;
|
tStateType state{};
|
||||||
|
bool isTermination = false;
|
||||||
ualni debug_idx = 0;
|
ualni debug_idx = 0;
|
||||||
ualni flag = 0;
|
ualni flag = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -40,12 +40,15 @@ namespace tp {
|
||||||
public:
|
public:
|
||||||
List<Vertex> mVertices;
|
List<Vertex> mVertices;
|
||||||
Vertex* mStart = nullptr;
|
Vertex* mStart = nullptr;
|
||||||
|
Buffer<tAlphabetType> mAllSymbols;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NFA() = default;
|
NFA() = default;
|
||||||
|
|
||||||
Vertex* addVertex() {
|
Vertex* addVertex(const tStateType& state, bool termination) {
|
||||||
auto node = mVertices.newNode();
|
auto node = mVertices.newNode();
|
||||||
|
node->data.isTermination = termination;
|
||||||
|
node->data.state = state;
|
||||||
node->data.debug_idx = mVertices.length() + 1;
|
node->data.debug_idx = mVertices.length() + 1;
|
||||||
mVertices.pushBack(node);
|
mVertices.pushBack(node);
|
||||||
return &node->data;
|
return &node->data;
|
||||||
|
|
@ -66,7 +69,10 @@ namespace tp {
|
||||||
|
|
||||||
[[nodiscard]] Vertex* getStartVertex() const { return mStart; }
|
[[nodiscard]] Vertex* getStartVertex() const { return mStart; }
|
||||||
|
|
||||||
void setVertexState(Vertex* vertex, tStateType state) { vertex->termination_state = state; }
|
void setVertexState(Vertex* vertex, const tStateType& state, bool terminated) {
|
||||||
|
vertex->state = state;
|
||||||
|
vertex->isTermination = terminated;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool isValid() const {
|
[[nodiscard]] bool isValid() const {
|
||||||
if (!mStart) {
|
if (!mStart) {
|
||||||
|
|
@ -75,27 +81,6 @@ namespace tp {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Range<tAlphabetType> getAlphabetRange() const {
|
|
||||||
tAlphabetType start = 0, end = 0;
|
|
||||||
Range<tAlphabetType> all_range(
|
|
||||||
std::numeric_limits<tAlphabetType>::min(), std::numeric_limits<tAlphabetType>::max()
|
|
||||||
);
|
|
||||||
bool first = true;
|
|
||||||
|
|
||||||
for (auto vertex : mVertices) {
|
|
||||||
for (auto edge : vertex.data().edges) {
|
|
||||||
if (!edge.data().mConsumesSymbol) continue;
|
|
||||||
auto const& tran_range = edge.data().mAcceptingRange;
|
|
||||||
if (edge.data().mAcceptsAll || edge.data().mExclude) return all_range;
|
|
||||||
if (tran_range.mBegin < start || first) start = tran_range.mBegin;
|
|
||||||
if (tran_range.mEnd > end || first) end = tran_range.mEnd;
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Range<tAlphabetType>(start, end + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// vertices that are reachable from initial set with no input consumption (E-transitions)
|
// vertices that are reachable from initial set with no input consumption (E-transitions)
|
||||||
// does not include initial set
|
// does not include initial set
|
||||||
void closure(const List<Vertex*>& set, List<Vertex*>& closure, ualni unique_call_id) {
|
void closure(const List<Vertex*>& set, List<Vertex*>& closure, ualni unique_call_id) {
|
||||||
|
|
@ -133,10 +118,9 @@ namespace tp {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Deterministic Finite-State Automata
|
// Deterministic Finite-State Automata
|
||||||
template <typename tAlphabetType, typename tStateType, tStateType tNoStateVal, tStateType tFailedStateVal>
|
template <typename tAlphabetType, typename tStateType>
|
||||||
class DFA {
|
class DFA {
|
||||||
static_assert(TypeTraits<tAlphabetType>::isIntegral, "tAlphabetType must be enumerable.");
|
public:
|
||||||
|
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
struct Edge {
|
struct Edge {
|
||||||
Vertex* vertex = nullptr;
|
Vertex* vertex = nullptr;
|
||||||
|
|
@ -144,25 +128,26 @@ namespace tp {
|
||||||
};
|
};
|
||||||
|
|
||||||
List<Edge> edges;
|
List<Edge> edges;
|
||||||
tStateType termination_state = tNoStateVal;
|
tStateType state{};
|
||||||
|
bool termination = false;
|
||||||
bool marked = false;
|
bool marked = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
List<Vertex> mVertices;
|
List<Vertex> mVertices;
|
||||||
Vertex* mStart = nullptr;
|
Vertex* mStart = nullptr;
|
||||||
const Vertex* mIter = nullptr;
|
const Vertex* mIter = nullptr;
|
||||||
Range<tAlphabetType> mAlphabetRange;
|
Buffer<tAlphabetType> mAlphabetRange;
|
||||||
bool mTrapState = false;
|
bool mTrapState = false;
|
||||||
|
|
||||||
typedef typename NFA<tAlphabetType, tStateType, tNoStateVal, tFailedStateVal>::Vertex NState;
|
typedef typename NFA<tAlphabetType, tStateType>::Vertex NState;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit DFA(NFA<tAlphabetType, tStateType, tNoStateVal, tFailedStateVal>& nfa) {
|
explicit DFA(NFA<tAlphabetType, tStateType>& nfa) {
|
||||||
if (!nfa.isValid()) {
|
if (!nfa.isValid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mAlphabetRange = nfa.getAlphabetRange();
|
mAlphabetRange = nfa.mAllSymbols;
|
||||||
|
|
||||||
struct DStateKey {
|
struct DStateKey {
|
||||||
const List<NState*>* nStates;
|
const List<NState*>* nStates;
|
||||||
|
|
@ -269,14 +254,19 @@ namespace tp {
|
||||||
|
|
||||||
// create own vertices
|
// create own vertices
|
||||||
for (auto node : dStates) {
|
for (auto node : dStates) {
|
||||||
tStateType state = tNoStateVal;
|
const tStateType* state = nullptr;
|
||||||
|
ualni numFound = 0;
|
||||||
for (auto iter : node->val->nStates) {
|
for (auto iter : node->val->nStates) {
|
||||||
if (iter->termination_state != tNoStateVal) {
|
if (iter->isTermination) {
|
||||||
state = iter->termination_state;
|
state = &iter->state;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node->val->dVertex = addVertex(state);
|
if (numFound != 1) {
|
||||||
|
printf("Error constructing dfa - invalid number of termination states in final node.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
node->val->dVertex = addVertex(*state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// connect all vertices
|
// connect all vertices
|
||||||
|
|
@ -295,9 +285,9 @@ namespace tp {
|
||||||
}
|
}
|
||||||
|
|
||||||
collapseEquivalentVertices();
|
collapseEquivalentVertices();
|
||||||
mAlphabetRange = getAlphabetRange();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
tStateType move(tAlphabetType symbol) {
|
tStateType move(tAlphabetType symbol) {
|
||||||
if (mTrapState || !mIter) {
|
if (mTrapState || !mIter) {
|
||||||
return tNoStateVal;
|
return tNoStateVal;
|
||||||
|
|
@ -318,10 +308,11 @@ namespace tp {
|
||||||
mIter = mStart;
|
mIter = mStart;
|
||||||
mTrapState = false;
|
mTrapState = false;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
[[nodiscard]] uhalni nVertices() const { return (uhalni) mVertices.length(); }
|
[[nodiscard]] uhalni nVertices() const { return (uhalni) mVertices.length(); }
|
||||||
|
|
||||||
[[nodiscard]] Range<tAlphabetType> getRange() const { return mAlphabetRange; }
|
[[nodiscard]] const Buffer<tAlphabetType>& getRange() const { return mAlphabetRange; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
[[nodiscard]] Range<tAlphabetType> getAlphabetRange() const {
|
[[nodiscard]] Range<tAlphabetType> getAlphabetRange() const {
|
||||||
|
|
@ -363,9 +354,9 @@ namespace tp {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
Vertex* addVertex(tStateType state) {
|
Vertex* addVertex(const tStateType& state) {
|
||||||
auto node = mVertices.addNodeBack();
|
auto node = mVertices.addNodeBack();
|
||||||
node->data.termination_state = state;
|
node->data.state = state;
|
||||||
return &node->data;
|
return &node->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,33 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Automata.hpp"
|
||||||
#include "Grammar.hpp"
|
#include "Grammar.hpp"
|
||||||
|
|
||||||
namespace tp {
|
namespace tp {
|
||||||
|
|
||||||
template <typename tAlphabetType, typename tStateType, tStateType tNoStateVal, tStateType tFailedStateVal>
|
class ContextFreeCompiler {
|
||||||
class RegularCompiler {};
|
typedef ContextFreeGrammar Grammar;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Terminals or non terminals
|
||||||
|
struct Alphabet {
|
||||||
|
String mId;
|
||||||
|
bool mIsTerminal = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Item {
|
||||||
|
Grammar::Rule mRule;
|
||||||
|
ualni mAdvanceIdx;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef NFA<Alphabet, Item> NFA;
|
||||||
|
typedef typename NFA::Vertex State;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void compile(const Grammar& in, NFA& out) { nfa = &out; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
NFA* nfa = nullptr;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "AST.hpp"
|
#include "AST.hpp"
|
||||||
#include "RegularCompiler.hpp"
|
#include "RegularCompiler.hpp"
|
||||||
|
#include "ContextFreeCompiler.hpp"
|
||||||
|
|
||||||
namespace tp {
|
namespace tp {
|
||||||
|
|
||||||
|
|
@ -10,9 +11,13 @@ namespace tp {
|
||||||
class Parser {
|
class Parser {
|
||||||
|
|
||||||
typedef TransitionMatrix<tAlphabetType, TokenType, TokenType::InTransition, TokenType::Failed> RegularTable;
|
typedef TransitionMatrix<tAlphabetType, TokenType, TokenType::InTransition, TokenType::Failed> RegularTable;
|
||||||
typedef DFA<tAlphabetType, TokenType, TokenType::InTransition, TokenType::Failed> RegularGraph;
|
typedef DFA<tAlphabetType, TokenType> RegularGraph;
|
||||||
typedef RegularCompiler<tAlphabetType, TokenType, TokenType::InTransition, TokenType::Failed> RegularCompiler;
|
typedef RegularCompiler<tAlphabetType, TokenType, TokenType::InTransition, TokenType::Failed> RegularCompiler;
|
||||||
typedef NFA<tAlphabetType, TokenType, TokenType::InTransition, TokenType::Failed> RegularNonDetGraph;
|
typedef NFA<tAlphabetType, TokenType> RegularNonDetGraph;
|
||||||
|
|
||||||
|
// ContextFreeCompiler::Alphabet PushDownTable;
|
||||||
|
typedef DFA<ContextFreeCompiler::Alphabet, ContextFreeCompiler::Item> ContextFreeDFA;
|
||||||
|
typedef ContextFreeCompiler::NFA ContextFreeNFA;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Parser() = default;
|
Parser() = default;
|
||||||
|
|
@ -28,6 +33,15 @@ namespace tp {
|
||||||
RegularGraph dfa(nfa);
|
RegularGraph dfa(nfa);
|
||||||
mRegularTable.construct(dfa);
|
mRegularTable.construct(dfa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compile context free grammar
|
||||||
|
{
|
||||||
|
ContextFreeNFA nfa;
|
||||||
|
ContextFreeCompiler compiler;
|
||||||
|
compiler.compile(cfGrammar, nfa);
|
||||||
|
|
||||||
|
ContextFreeDFA dfa(nfa);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse(const tAlphabetType* sentence, ualni sentenceLength, AST& out) {}
|
void parse(const tAlphabetType* sentence, ualni sentenceLength, AST& out) {}
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,6 @@
|
||||||
|
|
||||||
namespace tp {
|
namespace tp {
|
||||||
|
|
||||||
template <typename tAlphabetType, typename tStateType, tStateType tNoStateVal, tStateType tFailedStateVal>
|
|
||||||
class TransitionMatrix;
|
|
||||||
|
|
||||||
template <typename tAlphabetType, typename tStateType, tStateType tNoStateVal, tStateType tFailedStateVal>
|
template <typename tAlphabetType, typename tStateType, tStateType tNoStateVal, tStateType tFailedStateVal>
|
||||||
class TransitionMatrix {
|
class TransitionMatrix {
|
||||||
|
|
||||||
|
|
@ -30,8 +27,8 @@ namespace tp {
|
||||||
auto getTransitions() const { return &mTransitions; }
|
auto getTransitions() const { return &mTransitions; }
|
||||||
auto getStart() const { return mStart; }
|
auto getStart() const { return mStart; }
|
||||||
|
|
||||||
void construct(const DFA<tAlphabetType, tStateType, tNoStateVal, tFailedStateVal>& dfa) {
|
void construct(const DFA<tAlphabetType, tStateType>& dfa) {
|
||||||
mSymbolRange = dfa.getRange();
|
mSymbolRange = { dfa.getRange().first(), dfa.getRange().last() };
|
||||||
auto range_len = ualni(mSymbolRange.mEnd - mSymbolRange.mBegin);
|
auto range_len = ualni(mSymbolRange.mEnd - mSymbolRange.mBegin);
|
||||||
auto sizeX = range_len ? range_len : 1;
|
auto sizeX = range_len ? range_len : 1;
|
||||||
auto sizeY = (ualni) (dfa.nVertices() + 1);
|
auto sizeY = (ualni) (dfa.nVertices() + 1);
|
||||||
|
|
@ -42,7 +39,7 @@ namespace tp {
|
||||||
|
|
||||||
ualni idx = 0;
|
ualni idx = 0;
|
||||||
for (auto vertex : dfa.mVertices) {
|
for (auto vertex : dfa.mVertices) {
|
||||||
auto state = vertex.data().termination_state;
|
auto state = vertex.data().termination ? vertex.data().state : tNoStateVal;
|
||||||
mStates[idx] = state;
|
mStates[idx] = state;
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ namespace tp {
|
||||||
template <typename tAlphabetType, typename tStateType, tStateType tNoStateVal, tStateType tFailedStateVal>
|
template <typename tAlphabetType, typename tStateType, tStateType tNoStateVal, tStateType tFailedStateVal>
|
||||||
class RegularCompiler {
|
class RegularCompiler {
|
||||||
|
|
||||||
typedef NFA<tAlphabetType, tStateType, tNoStateVal, tFailedStateVal> Graph;
|
typedef NFA<tAlphabetType, tStateType> Graph;
|
||||||
typedef typename Graph::Vertex Vertex;
|
typedef typename Graph::Vertex Vertex;
|
||||||
typedef RegularGrammar<tAlphabetType, tStateType> Grammar;
|
typedef RegularGrammar<tAlphabetType, tStateType> Grammar;
|
||||||
|
|
||||||
|
|
@ -31,16 +31,17 @@ namespace tp {
|
||||||
|
|
||||||
CompileError mError;
|
CompileError mError;
|
||||||
|
|
||||||
Node compile(Graph& graph, const tAlphabetType* regex, tStateType state) {
|
void compile(Graph& graph, const tAlphabetType* regex, tStateType state) {
|
||||||
mGraph = &graph;
|
mGraph = &graph;
|
||||||
return compileUtil(regex, state);
|
compileUtil(regex, state);
|
||||||
|
setAlphabet();
|
||||||
}
|
}
|
||||||
|
|
||||||
Node compile(Graph& aGraph, const Grammar& grammar) {
|
void compile(Graph& aGraph, const Grammar& grammar) {
|
||||||
mGraph = &aGraph;
|
mGraph = &aGraph;
|
||||||
|
|
||||||
auto left = mGraph->addVertex();
|
auto left = addVertex();
|
||||||
auto right = mGraph->addVertex();
|
auto right = addVertex();
|
||||||
|
|
||||||
halni idx = 0;
|
halni idx = 0;
|
||||||
for (auto rule : grammar.mRules) {
|
for (auto rule : grammar.mRules) {
|
||||||
|
|
@ -49,7 +50,7 @@ namespace tp {
|
||||||
|
|
||||||
if (!(node.left && node.right)) {
|
if (!(node.left && node.right)) {
|
||||||
mError.mRuleIndex = idx;
|
mError.mRuleIndex = idx;
|
||||||
return {};
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
transitionAny(left, node.left);
|
transitionAny(left, node.left);
|
||||||
|
|
@ -60,7 +61,7 @@ namespace tp {
|
||||||
|
|
||||||
mGraph->setStartVertex(left);
|
mGraph->setStartVertex(left);
|
||||||
|
|
||||||
return { left, right };
|
setAlphabet();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -68,15 +69,15 @@ namespace tp {
|
||||||
|
|
||||||
auto node = compileNode(astNode, nullptr, nullptr);
|
auto node = compileNode(astNode, nullptr, nullptr);
|
||||||
|
|
||||||
mGraph->setVertexState(node.right, state);
|
mGraph->setVertexState(node.right, state, true);
|
||||||
mGraph->setStartVertex(node.left);
|
mGraph->setStartVertex(node.left);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node compileVal(Grammar::ValueNode* val, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
|
Node compileVal(Grammar::ValueNode* val, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
|
||||||
auto left = aLeft ? aLeft : mGraph->addVertex();
|
auto left = aLeft ? aLeft : addVertex();
|
||||||
auto right = aRight ? aRight : mGraph->addVertex();
|
auto right = aRight ? aRight : addVertex();
|
||||||
transitionVal(left, right, val->mVal);
|
transitionVal(left, right, val->mVal);
|
||||||
return { left, right };
|
return { left, right };
|
||||||
}
|
}
|
||||||
|
|
@ -90,15 +91,15 @@ namespace tp {
|
||||||
}
|
}
|
||||||
|
|
||||||
Node compileAny(const Grammar::AnyNode*, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
|
Node compileAny(const Grammar::AnyNode*, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
|
||||||
auto left = aLeft ? aLeft : mGraph->addVertex();
|
auto left = aLeft ? aLeft : addVertex();
|
||||||
auto right = aRight ? aRight : mGraph->addVertex();
|
auto right = aRight ? aRight : addVertex();
|
||||||
transitionAny(left, right, true);
|
transitionAny(left, right, true);
|
||||||
return { left, right };
|
return { left, right };
|
||||||
}
|
}
|
||||||
|
|
||||||
Node compileRepeat(const Grammar::RepetitionNode* repeat, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
|
Node compileRepeat(const Grammar::RepetitionNode* repeat, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
|
||||||
if (repeat->mPlus) {
|
if (repeat->mPlus) {
|
||||||
auto middle = mGraph->addVertex();
|
auto middle = addVertex();
|
||||||
|
|
||||||
auto left_node = compileNode(repeat->mNode, aLeft, middle);
|
auto left_node = compileNode(repeat->mNode, aLeft, middle);
|
||||||
|
|
||||||
|
|
@ -122,8 +123,8 @@ namespace tp {
|
||||||
}
|
}
|
||||||
|
|
||||||
Node compileClass(const Grammar::ClassNode* node, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
|
Node compileClass(const Grammar::ClassNode* node, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) {
|
||||||
auto left = aLeft ? aLeft : mGraph->addVertex();
|
auto left = aLeft ? aLeft : addVertex();
|
||||||
auto right = aRight ? aRight : mGraph->addVertex();
|
auto right = aRight ? aRight : addVertex();
|
||||||
|
|
||||||
if (node->mRanges.size() == 1) {
|
if (node->mRanges.size() == 1) {
|
||||||
auto const& range = node->mRanges.first();
|
auto const& range = node->mRanges.first();
|
||||||
|
|
@ -132,7 +133,7 @@ namespace tp {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto range : node->mRanges) {
|
for (auto range : node->mRanges) {
|
||||||
auto middle = mGraph->addVertex();
|
auto middle = addVertex();
|
||||||
transitionRange(left, middle, { range.data().mBegin, range.data().mEnd }, node->mExclude);
|
transitionRange(left, middle, { range.data().mBegin, range.data().mEnd }, node->mExclude);
|
||||||
transitionAny(middle, right);
|
transitionAny(middle, right);
|
||||||
}
|
}
|
||||||
|
|
@ -182,5 +183,36 @@ namespace tp {
|
||||||
void transitionRange(Vertex* from, Vertex* to, Range<tAlphabetType> range, bool exclude) {
|
void transitionRange(Vertex* from, Vertex* to, Range<tAlphabetType> range, bool exclude) {
|
||||||
mGraph->addTransition(from, to, range, true, false, exclude);
|
mGraph->addTransition(from, to, range, true, false, exclude);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vertex* addVertex() { return mGraph->addVertex(tNoStateVal, false); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Range<tAlphabetType> getAlphabetRange() const {
|
||||||
|
tAlphabetType start = 0, end = 0;
|
||||||
|
Range<tAlphabetType> all_range(
|
||||||
|
std::numeric_limits<tAlphabetType>::min(), std::numeric_limits<tAlphabetType>::max()
|
||||||
|
);
|
||||||
|
bool first = true;
|
||||||
|
|
||||||
|
for (auto vertex : mGraph->mVertices) {
|
||||||
|
for (auto edge : vertex.data().edges) {
|
||||||
|
if (!edge.data().mConsumesSymbol) continue;
|
||||||
|
auto const& tran_range = edge.data().mAcceptingRange;
|
||||||
|
if (edge.data().mAcceptsAll || edge.data().mExclude) return all_range;
|
||||||
|
if (tran_range.mBegin < start || first) start = tran_range.mBegin;
|
||||||
|
if (tran_range.mEnd > end || first) end = tran_range.mEnd;
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Range<tAlphabetType>(start, end + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAlphabet() {
|
||||||
|
auto range = getAlphabetRange();
|
||||||
|
for (auto iter : range) {
|
||||||
|
mGraph->mAllSymbols.append(iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,8 +100,8 @@ namespace tp {
|
||||||
inline const Iterator& operator*() { return *this; }
|
inline const Iterator& operator*() { return *this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
tType mBegin = 0;
|
tType mBegin{};
|
||||||
tType mEnd = 0;
|
tType mEnd{};
|
||||||
|
|
||||||
Range() = default;
|
Range() = default;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue