From 6fcfa075f8afeb6726606b0a9e7dd387ae022818 Mon Sep 17 00:00:00 2001 From: IlushaShurupov Date: Fri, 11 Aug 2023 16:04:02 +0300 Subject: [PATCH] Generate sentences from cf grammar. Fix list initialization from copy constructor --- Containers/public/List.hpp | 4 +-- Parser/applications/Cfg.cpp | 6 +++- Parser/private/CfGrammar.cpp | 65 ++++++++++++++++++++++++++++++++++++ Parser/public/CfGrammar.hpp | 13 +++++++- 4 files changed, 84 insertions(+), 4 deletions(-) diff --git a/Containers/public/List.hpp b/Containers/public/List.hpp index 85a49bf..e80b50c 100644 --- a/Containers/public/List.hpp +++ b/Containers/public/List.hpp @@ -72,7 +72,7 @@ namespace tp { public: List() = default; - + List(const List& in) { this->operator=(in); } List(const InitialierList& list) { operator=(list); } [[nodiscard]] inline Node* first() const { return mFirst; } @@ -146,7 +146,7 @@ namespace tp { } [[nodiscard]] Node* findIdx(Index idx) const { - DEBUG_ASSERT(!mFirst || idx > mLength - 1) + DEBUG_ASSERT(mFirst && idx < mLength && idx >= 0) Node* found = mFirst; for (int i = 0; i != idx; i++) { found = found->next; diff --git a/Parser/applications/Cfg.cpp b/Parser/applications/Cfg.cpp index 6b22bb5..23ad5ac 100644 --- a/Parser/applications/Cfg.cpp +++ b/Parser/applications/Cfg.cpp @@ -23,7 +23,11 @@ void run(const String& source) { printf("Grammar accepted.\n"); - printf("Example text formed from grammar : TODO\n"); + List sentences; + grammar.generateSentences(sentences); + + printf("Example sentences formed from grammar: \n"); + for (auto sentence : sentences) tp::CfGrammar::printSentence(sentence.data()); CfGrammar::deinitializeCfGrammarParser(state); } diff --git a/Parser/private/CfGrammar.cpp b/Parser/private/CfGrammar.cpp index a265f51..5901eca 100644 --- a/Parser/private/CfGrammar.cpp +++ b/Parser/private/CfGrammar.cpp @@ -2,8 +2,73 @@ #include "NewPlacement.hpp" #include "CfGrammar.hpp" +#include "Timing.hpp" + using namespace tp; +void CfGrammar::generateSentences(List& out) { + constexpr ualni maxTime = 1000; + constexpr ualni maxSentences = 40; + constexpr ualni maxQueue = 20000; + + List queue; + Timer timer(maxTime); + + // add start production + Sentence start; + start.terms.pushBack( { startTerminal, false } ); + queue.pushBack(start); + + PASS: + + auto const sentential = &queue.first()->data; + bool isSentence = true; + ualni termIdx = 0; + for (auto term : sentential->terms) { + if (term->terminal) { + termIdx++; + continue; + } + + auto nonTerminal = &mNonTerminals.get(term->id); + for (auto production : nonTerminal->rules) { + queue.pushBack(*sentential); + auto copy = &queue.last()->data; + + auto appendTerm = copy->terms.findIdx(termIdx); + auto deleteTerm = appendTerm; + for (auto arg : production->args) { + auto newTerm = copy->terms.newNode({ arg->id, arg->isTerminal }); + copy->terms.attach(newTerm, appendTerm); + appendTerm = newTerm; + } + copy->terms.removeNode(deleteTerm); + } + + isSentence = false; + termIdx++; + } + if (isSentence) out.pushBack(*sentential); + queue.popFront(); + + + bool stop = false; + stop |= !queue.length(); + stop |= timer.isTimeout(); + stop |= queue.length() > maxQueue; + stop |= out.length() > maxSentences; + + if (!stop) goto PASS; +} + +void CfGrammar::printSentence(Sentence& in) { + printf("Sentence:"); + for (auto term : in.terms) { + printf(" %s", term->id.read()); + } + printf("\n"); +} + bool CfGrammar::compile() { if (!rules.length()) { diff --git a/Parser/public/CfGrammar.hpp b/Parser/public/CfGrammar.hpp index 8e4a4f7..f8b650e 100644 --- a/Parser/public/CfGrammar.hpp +++ b/Parser/public/CfGrammar.hpp @@ -18,6 +18,14 @@ namespace tp { List args; }; + struct Sentence { + struct Term { + String id; + bool terminal; + }; + List terms; + }; + List rules; String startTerminal; @@ -41,7 +49,10 @@ namespace tp { bool parse(CfGrammarParserState* context, const String& source); bool compile(); - bool isAmbiguous(); + void generateSentences(List& out); + static void printSentence(Sentence& in); + + private: void optimize(); }; } \ No newline at end of file