Generate sentences from cf grammar. Fix list initialization from copy constructor

This commit is contained in:
IlushaShurupov 2023-08-11 16:04:02 +03:00 committed by Ilya Shurupov
parent 92e772cde1
commit 259bf5a485
4 changed files with 84 additions and 4 deletions

View file

@ -72,7 +72,7 @@ namespace tp {
public: public:
List() = default; List() = default;
List(const List& in) { this->operator=(in); }
List(const InitialierList<Type>& list) { operator=(list); } List(const InitialierList<Type>& list) { operator=(list); }
[[nodiscard]] inline Node* first() const { return mFirst; } [[nodiscard]] inline Node* first() const { return mFirst; }
@ -146,7 +146,7 @@ namespace tp {
} }
[[nodiscard]] Node* findIdx(Index idx) const { [[nodiscard]] Node* findIdx(Index idx) const {
DEBUG_ASSERT(!mFirst || idx > mLength - 1) DEBUG_ASSERT(mFirst && idx < mLength && idx >= 0)
Node* found = mFirst; Node* found = mFirst;
for (int i = 0; i != idx; i++) { for (int i = 0; i != idx; i++) {
found = found->next; found = found->next;

View file

@ -23,7 +23,11 @@ void run(const String& source) {
printf("Grammar accepted.\n"); printf("Grammar accepted.\n");
printf("Example text formed from grammar : TODO\n"); List<CfGrammar::Sentence> sentences;
grammar.generateSentences(sentences);
printf("Example sentences formed from grammar: \n");
for (auto sentence : sentences) tp::CfGrammar::printSentence(sentence.data());
CfGrammar::deinitializeCfGrammarParser(state); CfGrammar::deinitializeCfGrammarParser(state);
} }

View file

@ -2,8 +2,73 @@
#include "NewPlacement.hpp" #include "NewPlacement.hpp"
#include "CfGrammar.hpp" #include "CfGrammar.hpp"
#include "Timing.hpp"
using namespace tp; using namespace tp;
void CfGrammar::generateSentences(List<Sentence>& out) {
constexpr ualni maxTime = 1000;
constexpr ualni maxSentences = 40;
constexpr ualni maxQueue = 20000;
List<Sentence> 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() { bool CfGrammar::compile() {
if (!rules.length()) { if (!rules.length()) {

View file

@ -18,6 +18,14 @@ namespace tp {
List<Arg> args; List<Arg> args;
}; };
struct Sentence {
struct Term {
String id;
bool terminal;
};
List<Term> terms;
};
List<Rule> rules; List<Rule> rules;
String startTerminal; String startTerminal;
@ -41,7 +49,10 @@ namespace tp {
bool parse(CfGrammarParserState* context, const String& source); bool parse(CfGrammarParserState* context, const String& source);
bool compile(); bool compile();
bool isAmbiguous(); void generateSentences(List<Sentence>& out);
static void printSentence(Sentence& in);
private:
void optimize(); void optimize();
}; };
} }