Generate sentences from cf grammar. Fix list initialization from copy constructor
This commit is contained in:
parent
d888aeb2b4
commit
6fcfa075f8
4 changed files with 84 additions and 4 deletions
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()) {
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue