tmp
This commit is contained in:
parent
93b02416de
commit
1f1dc001a1
8 changed files with 124 additions and 60 deletions
|
|
@ -18,7 +18,7 @@ namespace tp {
|
||||||
Type data;
|
Type data;
|
||||||
Node* next = nullptr;
|
Node* next = nullptr;
|
||||||
Node* prev = nullptr;
|
Node* prev = nullptr;
|
||||||
Node() = default;
|
Node() { data = Type(); }
|
||||||
explicit Node(TypeArg p_data) :
|
explicit Node(TypeArg p_data) :
|
||||||
data(p_data) {}
|
data(p_data) {}
|
||||||
Type& operator->() { return data; }
|
Type& operator->() { return data; }
|
||||||
|
|
|
||||||
1
Externals/lalr
vendored
Submodule
1
Externals/lalr
vendored
Submodule
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit ebf41832eb51205afd7aaf3e097d0a6197fefc26
|
||||||
|
|
@ -47,6 +47,7 @@ namespace tp {
|
||||||
class State {
|
class State {
|
||||||
friend FiniteStateAutomation;
|
friend FiniteStateAutomation;
|
||||||
|
|
||||||
|
public:
|
||||||
State() = default;
|
State() = default;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -61,7 +62,7 @@ namespace tp {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
List<State> mStates;
|
List<State> mStates;
|
||||||
const State* mStartState = nullptr;
|
State* mStartState = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FiniteStateAutomation() = default;
|
FiniteStateAutomation() = default;
|
||||||
|
|
@ -69,18 +70,18 @@ namespace tp {
|
||||||
State* addState(const tStateType& state, bool accepting) {
|
State* addState(const tStateType& state, bool accepting) {
|
||||||
auto node = mStates.newNode();
|
auto node = mStates.newNode();
|
||||||
node->data.mIsAccepting = accepting;
|
node->data.mIsAccepting = accepting;
|
||||||
node->data.mState = state;
|
node->data.mStateVal = state;
|
||||||
mStates.pushBack(node);
|
mStates.pushBack(node);
|
||||||
return &node->data;
|
return &node->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void addTransition(State* from, State* to, const tAlphabetType& symbol) {
|
void addTransition(State* from, State* to, const tAlphabetType& symbol) {
|
||||||
from->edges.pushBack(Transition(Transition::SYMBOL, to, symbol));
|
from->mTransitions.append(Transition(Transition::SYMBOL, to, symbol));
|
||||||
}
|
}
|
||||||
|
|
||||||
void addEpsilonTransition(State* from, State* to) { from->edges.pushBack(Transition(Transition::SYMBOL, to)); }
|
void addEpsilonTransition(State* from, State* to) { from->mTransitions.append(Transition(Transition::SYMBOL, to)); }
|
||||||
|
|
||||||
void addAnyTransition(State* from, State* to) { from->edges.pushBack(Transition(Transition::ANY, to)); }
|
void addAnyTransition(State* from, State* to) { from->mTransitions.append(Transition(Transition::ANY, to)); }
|
||||||
|
|
||||||
void setStartVertex(State* start) { mStartState = start; }
|
void setStartVertex(State* start) { mStartState = start; }
|
||||||
|
|
||||||
|
|
@ -96,7 +97,7 @@ namespace tp {
|
||||||
// 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 findClosureSet(const Buffer<State*>& from, Buffer<State*>& closureSet) const {
|
void findClosureSet(const Buffer<State*>& from, Buffer<State*>& closureSet) const {
|
||||||
Map<State*, bool> lookup;
|
Map<alni, bool> lookup;
|
||||||
List<State*> workingSet;
|
List<State*> workingSet;
|
||||||
|
|
||||||
for (auto item : from) {
|
for (auto item : from) {
|
||||||
|
|
@ -106,10 +107,11 @@ namespace tp {
|
||||||
while (workingSet.length()) {
|
while (workingSet.length()) {
|
||||||
auto first = workingSet.first()->data;
|
auto first = workingSet.first()->data;
|
||||||
closureSet.append(first);
|
closureSet.append(first);
|
||||||
|
lookup.put((alni) first, {});
|
||||||
|
|
||||||
for (auto edge : first->mTransitions) {
|
for (auto edge : first->mTransitions) {
|
||||||
if (!edge.data().isEpsilon()) continue;
|
if (!edge.data().isEpsilon()) continue;
|
||||||
if (lookup.presents(edge.data().mState)) continue;
|
if (lookup.presents((alni) edge.data().mState)) continue;
|
||||||
workingSet.pushBack(edge.data().mState);
|
workingSet.pushBack(edge.data().mState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,88 +121,118 @@ namespace tp {
|
||||||
|
|
||||||
// vertices that are reachable from initial set with symbol transition
|
// vertices that are reachable from initial set with symbol transition
|
||||||
void findMoveSet(const Buffer<State*>& from, Buffer<State*>& moveSet, tAlphabetType symbol) const {
|
void findMoveSet(const Buffer<State*>& from, Buffer<State*>& moveSet, tAlphabetType symbol) const {
|
||||||
Map<State*, bool> lookup;
|
Map<alni, bool> lookup;
|
||||||
|
|
||||||
for (auto vertex : from) {
|
for (auto vertex : from) {
|
||||||
for (auto edge : vertex.mTransitions) {
|
for (auto edge : vertex->mTransitions) {
|
||||||
if (edge.data().isepsilon()) continue;
|
if (edge.data().isEpsilon()) continue;
|
||||||
if (!edge.data().isTransition(symbol)) continue;
|
if (!edge.data().isTransition(symbol)) continue;
|
||||||
if (lookup.presents(edge.data().mState)) continue;
|
if (lookup.presents((alni) edge.data().mState)) continue;
|
||||||
moveSet.append(edge.data().mState);
|
moveSet.append(edge.data().mState);
|
||||||
lookup.put(edge.data().mState, {});
|
lookup.put((alni) edge.data().mState, {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename tAlphabetIterator>
|
template <typename tAlphabetIterator>
|
||||||
bool makeDeterministic(const tAlphabetIterator& allSymbols) {
|
bool makeDeterministic(const tAlphabetIterator& allSymbols) {
|
||||||
if (!isValid()) {
|
if (!isValid()) return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Group {
|
typedef Buffer<State*> Group;
|
||||||
Buffer<State*> states;
|
|
||||||
AvlTree<Group*, tAlphabetType> transitions;
|
struct GroupKey {
|
||||||
|
const Group* group;
|
||||||
|
static ualni hash(GroupKey key) { return 0; }
|
||||||
|
bool operator==(const GroupKey& key) const { return false; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GroupInfo {
|
||||||
|
Group* group = nullptr;
|
||||||
|
AvlTree<AvlNumericKey<alni>, tAlphabetType> transitions;
|
||||||
State* newState = nullptr;
|
State* newState = nullptr;
|
||||||
bool accepting = false;
|
bool accepting = false;
|
||||||
tStateType stateVal = tStateType();
|
tStateType stateVal = tStateType();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GroupKey {
|
Buffer<Group> groups = { {} };
|
||||||
const Group* group;
|
Map<GroupKey, GroupInfo, DefaultAllocator, GroupKey::hash> groupInfos;
|
||||||
};
|
|
||||||
|
|
||||||
Buffer<Group> newStates = { {} };
|
findClosureSet({ getStartState() }, groups.first());
|
||||||
|
groupInfos.put({ &groups.first() }, { &groups.first() });
|
||||||
|
|
||||||
// 1) find new states
|
// 1) find new states
|
||||||
Map<GroupKey, bool> lookup;
|
|
||||||
List<Group*> workingSet;
|
List<Group*> workingSet;
|
||||||
|
workingSet.pushBack(&groups.first());
|
||||||
|
|
||||||
findClosureSet({ getStartState() }, newStates.first().states);
|
|
||||||
|
|
||||||
workingSet.pushBack(&newStates.first());
|
|
||||||
while (workingSet.length()) {
|
while (workingSet.length()) {
|
||||||
auto group = workingSet.first();
|
Group* group = workingSet.first()->data;
|
||||||
|
GroupInfo* info = &groupInfos.get({ group });
|
||||||
|
|
||||||
for (auto symbol : allSymbols) {
|
for (auto symbol : allSymbols) {
|
||||||
|
|
||||||
// calculate new possible state
|
// calculate new possible state
|
||||||
|
Group potentialGroupTmp;
|
||||||
Group potentialGroup;
|
Group potentialGroup;
|
||||||
findMoveSet(group.states, potentialGroup.states, symbol);
|
|
||||||
if (!potentialGroup.states.size()) continue;
|
findMoveSet(*group, potentialGroupTmp, symbol);
|
||||||
|
findClosureSet(potentialGroupTmp, potentialGroup);
|
||||||
|
|
||||||
|
if (!potentialGroup.size()) continue;
|
||||||
|
|
||||||
// find existing or create group
|
// find existing or create group
|
||||||
Group* targetGroup = nullptr;
|
Group* targetGroup = nullptr;
|
||||||
auto iter = lookup.presents({ &potentialGroup });
|
auto iter = groupInfos.presents({ &potentialGroup });
|
||||||
if (iter) {
|
if (iter) {
|
||||||
targetGroup = lookup.getSlotVal(iter);
|
targetGroup = groupInfos.getSlotVal(iter).group;
|
||||||
} else {
|
} else {
|
||||||
targetGroup = newStates.append({});
|
targetGroup = &groups.append(potentialGroup);
|
||||||
lookup.put({ targetGroup }, {});
|
groupInfos.put({ targetGroup }, { targetGroup });
|
||||||
|
workingSet.pushBack(targetGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add transition
|
// assert transition is added
|
||||||
group.transitions.insert(targetGroup, symbol);
|
info->transitions.insert((alni) targetGroup, symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
workingSet.popFront();
|
workingSet.popFront();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2) find new states termination values
|
// 2) find new states termination values
|
||||||
// ...
|
for (auto group : groupInfos) {
|
||||||
|
GroupInfo* info = &group->val;
|
||||||
|
bool accepting = false;
|
||||||
|
for (auto item : *info->group) {
|
||||||
|
if (item->mIsAccepting) {
|
||||||
|
if (accepting) return false;
|
||||||
|
accepting = true;
|
||||||
|
info->accepting = true;
|
||||||
|
info->stateVal = item->mStateVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!accepting) {
|
||||||
|
info->accepting = false;
|
||||||
|
info->stateVal = info->group->first()->mStateVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 3) transfer
|
// 3) transfer
|
||||||
mStates.removeAll();
|
mStates.removeAll();
|
||||||
|
|
||||||
for (auto group : newStates) {
|
// create states
|
||||||
group.newState = addState();
|
for (auto group : groupInfos) {
|
||||||
|
group->val.newState = addState(group->val.stateVal, group->val.accepting);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto group : newStates) {
|
// create transitions
|
||||||
for (auto transition : group.transitions) {
|
for (auto group : groupInfos) {
|
||||||
addTransition(/* ... */);
|
auto functor = [&](AvlNumericKey<alni> targetGroupKey, tAlphabetType symbol) {
|
||||||
}
|
GroupInfo* targetGroup = &groupInfos.get({ (Group*) targetGroupKey.val });
|
||||||
|
addTransition(group->val.newState, targetGroup->newState, symbol);
|
||||||
|
};
|
||||||
|
group->val.transitions.forEach(functor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -21,8 +21,8 @@ namespace tp {
|
||||||
ualni mAdvanceIdx;
|
ualni mAdvanceIdx;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef NFA<Alphabet, Item> NFA;
|
typedef FiniteStateAutomation<Alphabet, Item> NFA;
|
||||||
typedef typename NFA::Vertex State;
|
typedef typename NFA::State State;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void compile(const Grammar& in, NFA& out) { nfa = &out; }
|
void compile(const Grammar& in, NFA& out) { nfa = &out; }
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,12 @@ 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> RegularGraph;
|
typedef FiniteStateAutomation<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> RegularNonDetGraph;
|
typedef FiniteStateAutomation<tAlphabetType, TokenType> RegularNonDetGraph;
|
||||||
|
|
||||||
// ContextFreeCompiler::Alphabet PushDownTable;
|
// ContextFreeCompiler::Alphabet PushDownTable;
|
||||||
typedef DFA<ContextFreeCompiler::Alphabet, ContextFreeCompiler::Item> ContextFreeDFA;
|
typedef FiniteStateAutomation<ContextFreeCompiler::Alphabet, ContextFreeCompiler::Item> ContextFreeDFA;
|
||||||
typedef ContextFreeCompiler::NFA ContextFreeNFA;
|
typedef ContextFreeCompiler::NFA ContextFreeNFA;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -27,8 +27,11 @@ 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>& dfa) {
|
void construct(const FiniteStateAutomation<tAlphabetType, tStateType>& dfa) {
|
||||||
mSymbolRange = { dfa.getRange().first(), dfa.getRange().last() };
|
// mSymbolRange = { dfa.getRange().first(), dfa.getRange().last() };
|
||||||
|
ASSERT(0);
|
||||||
|
|
||||||
|
/*
|
||||||
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);
|
||||||
|
|
@ -67,6 +70,8 @@ namespace tp {
|
||||||
}
|
}
|
||||||
vertexIdx++;
|
vertexIdx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isTrapped() { return mStates[mIter] == tFailedStateVal; }
|
bool isTrapped() { return mStates[mIter] == tFailedStateVal; }
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ 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> Graph;
|
typedef FiniteStateAutomation<tAlphabetType, tStateType> Graph;
|
||||||
typedef typename Graph::Vertex Vertex;
|
typedef typename Graph::State Vertex;
|
||||||
typedef RegularGrammar<tAlphabetType, tStateType> Grammar;
|
typedef RegularGrammar<tAlphabetType, tStateType> Grammar;
|
||||||
|
|
||||||
struct Node {
|
struct Node {
|
||||||
|
|
@ -69,8 +69,9 @@ namespace tp {
|
||||||
|
|
||||||
auto node = compileNode(astNode, nullptr, nullptr);
|
auto node = compileNode(astNode, nullptr, nullptr);
|
||||||
|
|
||||||
mGraph->setVertexState(node.right, state, true);
|
// mGraph->setVertexState(node.right, state, true);
|
||||||
mGraph->setStartVertex(node.left);
|
// mGraph->setStartVertex(node.left);
|
||||||
|
ASSERT(0);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
@ -173,21 +174,29 @@ namespace tp {
|
||||||
}
|
}
|
||||||
|
|
||||||
void transitionAny(Vertex* from, Vertex* to, bool consumes = false) {
|
void transitionAny(Vertex* from, Vertex* to, bool consumes = false) {
|
||||||
mGraph->addTransition(from, to, {}, consumes, true, false);
|
// mGraph->addTransition(from, to, {}, consumes, true, false);
|
||||||
|
ASSERT(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void transitionVal(Vertex* from, Vertex* to, tAlphabetType val) {
|
void transitionVal(Vertex* from, Vertex* to, tAlphabetType val) {
|
||||||
mGraph->addTransition(from, to, { val, val }, true, false, false);
|
// mGraph->addTransition(from, to, { val, val }, true, false, false);
|
||||||
|
ASSERT(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
ASSERT(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vertex* addVertex() { return mGraph->addVertex(tNoStateVal, false); }
|
Vertex* addVertex() {
|
||||||
|
// return mGraph->addVertex(tNoStateVal, false);
|
||||||
|
ASSERT(0);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Range<tAlphabetType> getAlphabetRange() const {
|
Range<tAlphabetType> getAlphabetRange() const {
|
||||||
|
/*
|
||||||
tAlphabetType start = 0, end = 0;
|
tAlphabetType start = 0, end = 0;
|
||||||
Range<tAlphabetType> all_range(
|
Range<tAlphabetType> all_range(
|
||||||
std::numeric_limits<tAlphabetType>::min(), std::numeric_limits<tAlphabetType>::max()
|
std::numeric_limits<tAlphabetType>::min(), std::numeric_limits<tAlphabetType>::max()
|
||||||
|
|
@ -204,14 +213,16 @@ namespace tp {
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Range<tAlphabetType>(start, end + 1);
|
return Range<tAlphabetType>(start, end + 1);
|
||||||
|
*/
|
||||||
|
ASSERT(0);
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAlphabet() {
|
void setAlphabet() {
|
||||||
auto range = getAlphabetRange();
|
auto range = getAlphabetRange();
|
||||||
for (auto iter : range) {
|
for (auto iter : range) {
|
||||||
mGraph->mAllSymbols.append(iter);
|
// mGraph->mAllSymbols.append(iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,20 @@
|
||||||
|
|
||||||
using namespace tp;
|
using namespace tp;
|
||||||
|
|
||||||
|
void testAutomation() {
|
||||||
|
|
||||||
|
FiniteStateAutomation<char, int> automata;
|
||||||
|
|
||||||
|
auto start = automata.addState(0, false);
|
||||||
|
auto end = automata.addState(1, true);
|
||||||
|
|
||||||
|
automata.addTransition(start, end, 'a');
|
||||||
|
|
||||||
|
automata.setStartVertex(start);
|
||||||
|
|
||||||
|
automata.makeDeterministic(Range<char>(10, 30));
|
||||||
|
}
|
||||||
|
|
||||||
void test() {
|
void test() {
|
||||||
auto parser = SimpleParser<int1>();
|
auto parser = SimpleParser<int1>();
|
||||||
auto ast = AST();
|
auto ast = AST();
|
||||||
|
|
@ -20,6 +34,7 @@ int main() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testAutomation();
|
||||||
test();
|
test();
|
||||||
|
|
||||||
testModule.deinitialize();
|
testModule.deinitialize();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue