tmp
This commit is contained in:
parent
81a2247bf2
commit
4f88c45c9e
8 changed files with 120 additions and 117 deletions
|
|
@ -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; }
|
||||||
|
|
||||||
|
|
|
||||||
18
Language/public/ContextFreeAutomata.hpp
Normal file
18
Language/public/ContextFreeAutomata.hpp
Normal 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) {}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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(); }
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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<ualni> range, bool exclude) {
|
||||||
|
if (exclude) {
|
||||||
|
Range<ualni> first = { tMinSymbol, range.mBegin - 1 };
|
||||||
|
Range<ualni> second = { range.mEnd + 1, tMaxSymbol };
|
||||||
|
|
||||||
|
if (first.valid()) {
|
||||||
|
for (auto symbol : first) {
|
||||||
|
transitionVal(from, to, symbol);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void transitionRange(Vertex* from, Vertex* to, Range<tAlphabetType> range, bool exclude) {
|
if (second.valid()) {
|
||||||
// mGraph->addTransition(from, to, range, true, false, exclude);
|
for (auto symbol : second) {
|
||||||
ASSERT(0);
|
transitionVal(from, to, symbol);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vertex* addVertex() {
|
} else {
|
||||||
// return mGraph->addVertex(tNoStateVal, false);
|
for (auto symbol : range) {
|
||||||
ASSERT(0);
|
transitionVal(from, to, symbol);
|
||||||
return nullptr;
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
Vertex* addVertex() { return mGraph->addState(tStateType::InTransition, false); }
|
||||||
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);
|
|
||||||
*/
|
|
||||||
ASSERT(0);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
void setAlphabet() {
|
|
||||||
auto range = getAlphabetRange();
|
|
||||||
for (auto iter : range) {
|
|
||||||
// mGraph->mAllSymbols.append(iter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue