This commit is contained in:
IlyaShurupov 2024-02-07 19:20:29 +03:00 committed by Ilusha
parent 81a2247bf2
commit 4f88c45c9e
8 changed files with 120 additions and 117 deletions

View file

@ -92,7 +92,7 @@ namespace tp {
void addAnyTransition(State* from, State* to) { from->mTransitions.append(Transition(Transition::ANY, to)); } void addAnyTransition(State* from, State* to) { from->mTransitions.append(Transition(Transition::ANY, to)); }
void setStartVertex(State* start) { mStartState = start; } void setStartState(State* start) { mStartState = start; }
[[nodiscard]] State* getStartState() const { return mStartState; } [[nodiscard]] State* getStartState() const { return mStartState; }

View file

@ -0,0 +1,18 @@
#pragma once
#include "Strings.hpp"
#include "Automata.hpp"
#include "Buffer2D.hpp"
namespace tp {
template <typename tAlphabetType, typename tStateType>
class ContextFreeAutomata {
public:
ContextFreeAutomata() = default;
void construct(const FiniteStateAutomation<tAlphabetType, tStateType>& automata) {}
};
}

View file

@ -18,7 +18,7 @@ namespace tp {
struct Item { struct Item {
Grammar::Rule mRule; Grammar::Rule mRule;
ualni mAdvanceIdx; ualni mAdvanceIdx = 0;
}; };
typedef FiniteStateAutomation<Alphabet, Item> NFA; typedef FiniteStateAutomation<Alphabet, Item> NFA;

View file

@ -193,6 +193,7 @@ namespace tp {
explicit ClassNode(const Buffer<Range<tAlphabetType>>& ranges, bool exclude = false) : explicit ClassNode(const Buffer<Range<tAlphabetType>>& ranges, bool exclude = false) :
Node(Node::CLASS) { Node(Node::CLASS) {
mExclude = exclude; mExclude = exclude;
mRanges = ranges;
} }
~ClassNode() override { mRanges.removeAll(); } ~ClassNode() override { mRanges.removeAll(); }

View file

@ -2,45 +2,49 @@
#pragma once #pragma once
#include "AST.hpp" #include "AST.hpp"
#include "RegularCompiler.hpp" #include "RegularCompiler.hpp"
#include "RegularAutomata.hpp"
#include "ContextFreeCompiler.hpp" #include "ContextFreeCompiler.hpp"
#include "ContextFreeAutomata.hpp"
namespace tp { namespace tp {
template <typename tAlphabetType, typename TokenType> template <typename tAlphabetType, typename TokenType, ualni MinSymbol, ualni MaxSymbol>
class Parser { class Parser {
typedef RegularAutomata<tAlphabetType, TokenType, TokenType::InTransition, TokenType::Failed> RegularTable; typedef RegularGrammar<tAlphabetType, TokenType> RegularGrammar;
typedef RegularCompiler<tAlphabetType, TokenType, MinSymbol, MaxSymbol> RegularCompiler;
typedef FiniteStateAutomation<tAlphabetType, TokenType> RegularGraph; typedef FiniteStateAutomation<tAlphabetType, TokenType> RegularGraph;
typedef RegularCompiler<tAlphabetType, TokenType, TokenType::InTransition, TokenType::Failed> RegularCompiler; typedef RegularAutomata<tAlphabetType, TokenType, TokenType::InTransition, TokenType::Failed> RegularAutomata;
typedef FiniteStateAutomation<tAlphabetType, TokenType> RegularNonDetGraph;
// ContextFreeCompiler::Alphabet PushDownTable; // ContextFreeGrammar;
typedef FiniteStateAutomation<ContextFreeCompiler::Alphabet, ContextFreeCompiler::Item> ContextFreeDFA; // ContextFreeCompiler;
typedef ContextFreeCompiler::NFA ContextFreeNFA; typedef FiniteStateAutomation<ContextFreeCompiler::Alphabet, ContextFreeCompiler::Item> ContextFreeGraph;
typedef ContextFreeAutomata<ContextFreeCompiler::Alphabet, ContextFreeCompiler::Item> ContextFreeAutomata;
public: public:
Parser() = default; Parser() = default;
public: public:
void compileTables(const ContextFreeGrammar& cfGrammar, const RegularGrammar<tAlphabetType, TokenType>& reGrammar) { void compileTables(const ContextFreeGrammar& cfGrammar, const RegularGrammar& reGrammar) {
// Compile Regular Grammar // Compile Regular Grammar
{ {
RegularNonDetGraph nfa; RegularGraph graph;
RegularCompiler compiler; RegularCompiler compiler;
compiler.compile(nfa, reGrammar); compiler.compile(graph, reGrammar);
graph.makeDeterministic();
RegularGraph dfa(nfa); mRegularAutomata.construct(graph);
mRegularTable.construct(dfa);
} }
// compile context free grammar // compile context free grammar
{ {
ContextFreeNFA nfa; ContextFreeGraph graph;
ContextFreeCompiler compiler; ContextFreeCompiler compiler;
compiler.compile(cfGrammar, nfa); compiler.compile(cfGrammar, graph);
graph.makeDeterministic();
ContextFreeDFA dfa(nfa); mContextFreeAutomata.construct(graph);
} }
} }
@ -48,6 +52,7 @@ namespace tp {
public: public:
// save load compiled tables // save load compiled tables
RegularTable mRegularTable; RegularAutomata mRegularAutomata;
ContextFreeAutomata mContextFreeAutomata;
}; };
} }

View file

@ -27,50 +27,6 @@ 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 FiniteStateAutomation<tAlphabetType, tStateType>& automata) {
mSymbolRange = { tAlphabetType(automata.getAlphabetRange().mBegin),
tAlphabetType(automata.getAlphabetRange().mEnd) };
auto range_len = ualni(mSymbolRange.mEnd - mSymbolRange.mBegin);
auto sizeX = range_len ? range_len : 1;
auto sizeY = (ualni) (automata.numStates() + 1);
mTransitions.reserve({ sizeX, sizeY });
mTransitions.assign(automata.numStates());
mStates.reserve(sizeY);
ualni idx = 0;
for (auto state : *automata.getStates()) {
auto stateVal = state->isAccepting() ? state->getStateVal() : tNoStateVal;
mStates[idx] = stateVal;
idx++;
}
mStates[automata.numStates()] = tFailedStateVal;
idx = 0;
for (auto state : *automata.getStates()) {
if (&state.data() == automata.getStartState()) {
mStart = mIter = mIterPrev = idx;
}
idx++;
}
ualni stateIdx = 0;
for (auto state : *automata.getStates()) {
for (auto transition : *state->getTransitions()) {
ualni stateIdx2 = 0;
for (auto state2 : *automata.getStates()) {
if (transition->getState() == &state2.data()) break;
stateIdx2++;
}
auto const code = transition->getSymbol();
mTransitions.set({ (ualni) (code - mSymbolRange.mBegin), (ualni) stateIdx }, stateIdx2);
}
stateIdx++;
}
}
bool isTrapped() { return mStates[mIter] == tFailedStateVal; } bool isTrapped() { return mStates[mIter] == tFailedStateVal; }
tStateType move(tAlphabetType symbol) { tStateType move(tAlphabetType symbol) {
@ -112,5 +68,49 @@ namespace tp {
mIter = mStart; mIter = mStart;
mIterPrev = mStart; mIterPrev = mStart;
} }
void construct(const FiniteStateAutomation<tAlphabetType, tStateType>& automata) {
const auto range = automata.getAlphabetRange();
mSymbolRange = { tAlphabetType(range.mBegin), tAlphabetType(range.mEnd) };
auto range_len = ualni(mSymbolRange.mEnd - mSymbolRange.mBegin);
auto sizeX = range_len ? range_len : 1;
auto sizeY = (ualni) (automata.numStates() + 1);
mTransitions.reserve({ sizeX, sizeY });
mTransitions.assign(automata.numStates());
mStates.reserve(sizeY);
ualni idx = 0;
for (auto state : *automata.getStates()) {
auto stateVal = state->isAccepting() ? state->getStateVal() : tNoStateVal;
mStates[idx] = stateVal;
idx++;
}
mStates[automata.numStates()] = tFailedStateVal;
idx = 0;
for (auto state : *automata.getStates()) {
if (&state.data() == automata.getStartState()) {
mStart = mIter = mIterPrev = idx;
}
idx++;
}
ualni stateIdx = 0;
for (auto state : *automata.getStates()) {
for (auto transition : *state->getTransitions()) {
ualni stateIdx2 = 0;
for (auto state2 : *automata.getStates()) {
if (transition->getState() == &state2.data()) break;
stateIdx2++;
}
auto const code = transition->getSymbol();
mTransitions.set({ (ualni) (code - mSymbolRange.mBegin), (ualni) stateIdx }, stateIdx2);
}
stateIdx++;
}
}
}; };
} }

View file

@ -2,11 +2,11 @@
#pragma once #pragma once
#include "Grammar.hpp" #include "Grammar.hpp"
#include "RegularAutomata.hpp" #include "Automata.hpp"
namespace tp { namespace tp {
template <typename tAlphabetType, typename tStateType, tStateType tNoStateVal, tStateType tFailedStateVal> template <typename tAlphabetType, typename tStateType, ualni tMinSymbol, ualni tMaxSymbol>
class RegularCompiler { class RegularCompiler {
typedef FiniteStateAutomation<tAlphabetType, tStateType> Graph; typedef FiniteStateAutomation<tAlphabetType, tStateType> Graph;
@ -34,7 +34,6 @@ namespace tp {
void compile(Graph& graph, const tAlphabetType* regex, tStateType state) { void compile(Graph& graph, const tAlphabetType* regex, tStateType state) {
mGraph = &graph; mGraph = &graph;
compileUtil(regex, state); compileUtil(regex, state);
setAlphabet();
} }
void compile(Graph& aGraph, const Grammar& grammar) { void compile(Graph& aGraph, const Grammar& grammar) {
@ -59,9 +58,7 @@ namespace tp {
idx++; idx++;
} }
mGraph->setStartVertex(left); mGraph->setStartState(left);
setAlphabet();
} }
private: private:
@ -69,9 +66,10 @@ namespace tp {
auto node = compileNode(astNode, nullptr, nullptr); auto node = compileNode(astNode, nullptr, nullptr);
// mGraph->setVertexState(node.right, state, true); node.right->setValue(state);
// mGraph->setStartVertex(node.left); node.right->setAcceptance(true);
ASSERT(0);
mGraph->setStartState(node.left);
return node; return node;
} }
@ -129,13 +127,13 @@ namespace tp {
if (node->mRanges.size() == 1) { if (node->mRanges.size() == 1) {
auto const& range = node->mRanges.first(); auto const& range = node->mRanges.first();
transitionRange(left, right, { range.mBegin, range.mEnd }, node->mExclude); transitionRange(left, right, { ualni(range.mBegin), ualni(range.mEnd) }, node->mExclude);
return { left, right }; return { left, right };
} }
for (auto range : node->mRanges) { for (auto range : node->mRanges) {
auto middle = addVertex(); auto middle = addVertex();
transitionRange(left, middle, { range.data().mBegin, range.data().mEnd }, node->mExclude); transitionRange(left, middle, { ualni(range->mBegin), ualni(range->mEnd) }, node->mExclude);
transitionAny(middle, right); transitionAny(middle, right);
} }
return { left, right }; return { left, right };
@ -174,56 +172,37 @@ 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); for (auto symbol : Range<ualni>(tMinSymbol, tMaxSymbol)) {
ASSERT(0); transitionVal(from, to, symbol);
}
} }
void transitionVal(Vertex* from, Vertex* to, tAlphabetType val) { void transitionVal(Vertex* from, Vertex* to, tAlphabetType val) { mGraph->addTransition(from, to, val); }
// 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<ualni> range, bool exclude) {
// mGraph->addTransition(from, to, range, true, false, exclude); if (exclude) {
ASSERT(0); Range<ualni> first = { tMinSymbol, range.mBegin - 1 };
} Range<ualni> second = { range.mEnd + 1, tMaxSymbol };
Vertex* addVertex() { if (first.valid()) {
// return mGraph->addVertex(tNoStateVal, false); for (auto symbol : first) {
ASSERT(0); transitionVal(from, to, symbol);
return nullptr; }
} }
private: if (second.valid()) {
Range<tAlphabetType> getAlphabetRange() const { for (auto symbol : second) {
/* transitionVal(from, to, symbol);
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) { } else {
for (auto edge : vertex.data().edges) { for (auto symbol : range) {
if (!edge.data().mConsumesSymbol) continue; transitionVal(from, to, symbol);
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);
*/
ASSERT(0);
return {};
} }
void setAlphabet() { Vertex* addVertex() { return mGraph->addState(tStateType::InTransition, false); }
auto range = getAlphabetRange();
for (auto iter : range) {
// mGraph->mAllSymbols.append(iter);
}
}
}; };
} }

View file

@ -12,7 +12,7 @@ void testAutomation() {
automata.addTransition(start, end, 'a'); automata.addTransition(start, end, 'a');
automata.setStartVertex(start); automata.setStartState(start);
automata.makeDeterministic(); automata.makeDeterministic();
} }