From 312419936ed413925bc76ae50eac74b8909a71a0 Mon Sep 17 00:00:00 2001 From: IlyaShurupov Date: Tue, 6 Feb 2024 09:27:49 +0300 Subject: [PATCH] tmp --- Language/public/Automata.hpp | 75 +++++++++++-------------- Language/public/ContextFreeCompiler.hpp | 27 ++++++++- Language/public/Parser.hpp | 18 +++++- Language/public/RegularAutomata.hpp | 9 +-- Language/public/RegularCompiler.hpp | 66 ++++++++++++++++------ Utils/public/Utils.hpp | 4 +- 6 files changed, 128 insertions(+), 71 deletions(-) diff --git a/Language/public/Automata.hpp b/Language/public/Automata.hpp index 2ac7924..1b742a0 100644 --- a/Language/public/Automata.hpp +++ b/Language/public/Automata.hpp @@ -8,9 +8,8 @@ namespace tp { // Non-Deterministic Finite-State Automata - template + template class NFA { - static_assert(TypeTraits::isIntegral, "tAlphabetType must be enumerable."); public: struct Vertex; @@ -32,7 +31,8 @@ namespace tp { struct Vertex { List edges; - tStateType termination_state = tNoStateVal; + tStateType state{}; + bool isTermination = false; ualni debug_idx = 0; ualni flag = 0; }; @@ -40,12 +40,15 @@ namespace tp { public: List mVertices; Vertex* mStart = nullptr; + Buffer mAllSymbols; public: NFA() = default; - Vertex* addVertex() { + Vertex* addVertex(const tStateType& state, bool termination) { auto node = mVertices.newNode(); + node->data.isTermination = termination; + node->data.state = state; node->data.debug_idx = mVertices.length() + 1; mVertices.pushBack(node); return &node->data; @@ -66,7 +69,10 @@ namespace tp { [[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 { if (!mStart) { @@ -75,27 +81,6 @@ namespace tp { return true; } - Range getAlphabetRange() const { - tAlphabetType start = 0, end = 0; - Range all_range( - std::numeric_limits::min(), std::numeric_limits::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(start, end + 1); - } - // vertices that are reachable from initial set with no input consumption (E-transitions) // does not include initial set void closure(const List& set, List& closure, ualni unique_call_id) { @@ -133,10 +118,9 @@ namespace tp { }; // Deterministic Finite-State Automata - template + template class DFA { - static_assert(TypeTraits::isIntegral, "tAlphabetType must be enumerable."); - + public: struct Vertex { struct Edge { Vertex* vertex = nullptr; @@ -144,25 +128,26 @@ namespace tp { }; List edges; - tStateType termination_state = tNoStateVal; + tStateType state{}; + bool termination = false; bool marked = false; }; List mVertices; Vertex* mStart = nullptr; const Vertex* mIter = nullptr; - Range mAlphabetRange; + Buffer mAlphabetRange; bool mTrapState = false; - typedef typename NFA::Vertex NState; + typedef typename NFA::Vertex NState; public: - explicit DFA(NFA& nfa) { + explicit DFA(NFA& nfa) { if (!nfa.isValid()) { return; } - mAlphabetRange = nfa.getAlphabetRange(); + mAlphabetRange = nfa.mAllSymbols; struct DStateKey { const List* nStates; @@ -269,14 +254,19 @@ namespace tp { // create own vertices for (auto node : dStates) { - tStateType state = tNoStateVal; + const tStateType* state = nullptr; + ualni numFound = 0; for (auto iter : node->val->nStates) { - if (iter->termination_state != tNoStateVal) { - state = iter->termination_state; + if (iter->isTermination) { + state = &iter->state; 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 @@ -295,9 +285,9 @@ namespace tp { } collapseEquivalentVertices(); - mAlphabetRange = getAlphabetRange(); } + /* tStateType move(tAlphabetType symbol) { if (mTrapState || !mIter) { return tNoStateVal; @@ -318,10 +308,11 @@ namespace tp { mIter = mStart; mTrapState = false; } + */ [[nodiscard]] uhalni nVertices() const { return (uhalni) mVertices.length(); } - [[nodiscard]] Range getRange() const { return mAlphabetRange; } + [[nodiscard]] const Buffer& getRange() const { return mAlphabetRange; } public: [[nodiscard]] Range getAlphabetRange() const { @@ -363,9 +354,9 @@ namespace tp { // TODO } - Vertex* addVertex(tStateType state) { + Vertex* addVertex(const tStateType& state) { auto node = mVertices.addNodeBack(); - node->data.termination_state = state; + node->data.state = state; return &node->data; } diff --git a/Language/public/ContextFreeCompiler.hpp b/Language/public/ContextFreeCompiler.hpp index c67e3e1..29fb439 100644 --- a/Language/public/ContextFreeCompiler.hpp +++ b/Language/public/ContextFreeCompiler.hpp @@ -1,10 +1,33 @@ #pragma once +#include "Automata.hpp" #include "Grammar.hpp" namespace tp { - template - class RegularCompiler {}; + class ContextFreeCompiler { + typedef ContextFreeGrammar Grammar; + + public: + // Terminals or non terminals + struct Alphabet { + String mId; + bool mIsTerminal = false; + }; + + struct Item { + Grammar::Rule mRule; + ualni mAdvanceIdx; + }; + + typedef NFA NFA; + typedef typename NFA::Vertex State; + + public: + void compile(const Grammar& in, NFA& out) { nfa = &out; } + + private: + NFA* nfa = nullptr; + }; } diff --git a/Language/public/Parser.hpp b/Language/public/Parser.hpp index 24407fa..43870c8 100644 --- a/Language/public/Parser.hpp +++ b/Language/public/Parser.hpp @@ -3,6 +3,7 @@ #include "AST.hpp" #include "RegularCompiler.hpp" +#include "ContextFreeCompiler.hpp" namespace tp { @@ -10,9 +11,13 @@ namespace tp { class Parser { typedef TransitionMatrix RegularTable; - typedef DFA RegularGraph; + typedef DFA RegularGraph; typedef RegularCompiler RegularCompiler; - typedef NFA RegularNonDetGraph; + typedef NFA RegularNonDetGraph; + + // ContextFreeCompiler::Alphabet PushDownTable; + typedef DFA ContextFreeDFA; + typedef ContextFreeCompiler::NFA ContextFreeNFA; public: Parser() = default; @@ -28,6 +33,15 @@ namespace tp { RegularGraph dfa(nfa); 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) {} diff --git a/Language/public/RegularAutomata.hpp b/Language/public/RegularAutomata.hpp index dea3c21..08a895c 100644 --- a/Language/public/RegularAutomata.hpp +++ b/Language/public/RegularAutomata.hpp @@ -7,9 +7,6 @@ namespace tp { - template - class TransitionMatrix; - template class TransitionMatrix { @@ -30,8 +27,8 @@ namespace tp { auto getTransitions() const { return &mTransitions; } auto getStart() const { return mStart; } - void construct(const DFA& dfa) { - mSymbolRange = dfa.getRange(); + void construct(const DFA& dfa) { + mSymbolRange = { dfa.getRange().first(), dfa.getRange().last() }; auto range_len = ualni(mSymbolRange.mEnd - mSymbolRange.mBegin); auto sizeX = range_len ? range_len : 1; auto sizeY = (ualni) (dfa.nVertices() + 1); @@ -42,7 +39,7 @@ namespace tp { ualni idx = 0; for (auto vertex : dfa.mVertices) { - auto state = vertex.data().termination_state; + auto state = vertex.data().termination ? vertex.data().state : tNoStateVal; mStates[idx] = state; idx++; } diff --git a/Language/public/RegularCompiler.hpp b/Language/public/RegularCompiler.hpp index e99625f..479e9b6 100644 --- a/Language/public/RegularCompiler.hpp +++ b/Language/public/RegularCompiler.hpp @@ -9,7 +9,7 @@ namespace tp { template class RegularCompiler { - typedef NFA Graph; + typedef NFA Graph; typedef typename Graph::Vertex Vertex; typedef RegularGrammar Grammar; @@ -31,16 +31,17 @@ namespace tp { CompileError mError; - Node compile(Graph& graph, const tAlphabetType* regex, tStateType state) { + void compile(Graph& graph, const tAlphabetType* regex, tStateType state) { 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; - auto left = mGraph->addVertex(); - auto right = mGraph->addVertex(); + auto left = addVertex(); + auto right = addVertex(); halni idx = 0; for (auto rule : grammar.mRules) { @@ -49,7 +50,7 @@ namespace tp { if (!(node.left && node.right)) { mError.mRuleIndex = idx; - return {}; + return; } transitionAny(left, node.left); @@ -60,7 +61,7 @@ namespace tp { mGraph->setStartVertex(left); - return { left, right }; + setAlphabet(); } private: @@ -68,15 +69,15 @@ namespace tp { auto node = compileNode(astNode, nullptr, nullptr); - mGraph->setVertexState(node.right, state); + mGraph->setVertexState(node.right, state, true); mGraph->setStartVertex(node.left); return node; } Node compileVal(Grammar::ValueNode* val, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) { - auto left = aLeft ? aLeft : mGraph->addVertex(); - auto right = aRight ? aRight : mGraph->addVertex(); + auto left = aLeft ? aLeft : addVertex(); + auto right = aRight ? aRight : addVertex(); transitionVal(left, right, val->mVal); return { left, right }; } @@ -90,15 +91,15 @@ namespace tp { } Node compileAny(const Grammar::AnyNode*, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) { - auto left = aLeft ? aLeft : mGraph->addVertex(); - auto right = aRight ? aRight : mGraph->addVertex(); + auto left = aLeft ? aLeft : addVertex(); + auto right = aRight ? aRight : addVertex(); transitionAny(left, right, true); return { left, right }; } Node compileRepeat(const Grammar::RepetitionNode* repeat, Vertex* aLeft = nullptr, Vertex* aRight = nullptr) { if (repeat->mPlus) { - auto middle = mGraph->addVertex(); + auto middle = addVertex(); 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) { - auto left = aLeft ? aLeft : mGraph->addVertex(); - auto right = aRight ? aRight : mGraph->addVertex(); + auto left = aLeft ? aLeft : addVertex(); + auto right = aRight ? aRight : addVertex(); if (node->mRanges.size() == 1) { auto const& range = node->mRanges.first(); @@ -132,7 +133,7 @@ namespace tp { } for (auto range : node->mRanges) { - auto middle = mGraph->addVertex(); + auto middle = addVertex(); transitionRange(left, middle, { range.data().mBegin, range.data().mEnd }, node->mExclude); transitionAny(middle, right); } @@ -182,5 +183,36 @@ namespace tp { void transitionRange(Vertex* from, Vertex* to, Range range, bool exclude) { mGraph->addTransition(from, to, range, true, false, exclude); } + + Vertex* addVertex() { return mGraph->addVertex(tNoStateVal, false); } + + private: + Range getAlphabetRange() const { + tAlphabetType start = 0, end = 0; + Range all_range( + std::numeric_limits::min(), std::numeric_limits::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(start, end + 1); + } + + void setAlphabet() { + auto range = getAlphabetRange(); + for (auto iter : range) { + mGraph->mAllSymbols.append(iter); + } + } }; } diff --git a/Utils/public/Utils.hpp b/Utils/public/Utils.hpp index d883b67..8d22934 100644 --- a/Utils/public/Utils.hpp +++ b/Utils/public/Utils.hpp @@ -100,8 +100,8 @@ namespace tp { inline const Iterator& operator*() { return *this; } }; - tType mBegin = 0; - tType mEnd = 0; + tType mBegin{}; + tType mEnd{}; Range() = default;