Checking for non productive rules and loops in cfg

This commit is contained in:
IlushaShurupov 2023-08-12 09:09:46 +03:00 committed by Ilya Shurupov
parent 16115b483a
commit 0e4f4228de
3 changed files with 40 additions and 0 deletions

View file

@ -145,5 +145,18 @@ bool CfGrammar::compile() {
rules.removeNode(rules.find(*rule.data()));
}
}
for (auto nonTerminal : mNonTerminals) {
if (!nonTerminal->val.isProductive()) {
printf("Non-terminal '%s' is not productive\n", nonTerminal->val.rules.first()->data->id.read());
return false;
}
}
Map<String, ualni> processed;
if (mNonTerminals.get(startTerminal).isLooped(processed, startTerminal)) {
printf("Note that grammar is looped.\n");
}
return true;
}

View file

@ -1,3 +1,4 @@
#include "NewPlacement.hpp"
#include "Parser.hpp"
#include "Tokenizer.hpp"

View file

@ -24,6 +24,13 @@ namespace tp {
bool operator==(const Rule& in) const {
return (id == in.id) && (args == in.args);
}
[[nodiscard]] bool isProductive() const {
for (auto arg : args) {
if (arg->id == id) return false;
}
return true;
}
};
struct Sentence {
@ -42,9 +49,28 @@ namespace tp {
private:
struct NonTerminal {
List<Rule*> rules;
Map<String, NonTerminal*> references;
Map<String, NonTerminal*> referencing;
[[nodiscard]] bool isProductive() const {
for (auto rule : rules) {
if (rule->isProductive()) return true;
}
return false;
}
[[nodiscard]] bool isLooped(Map<String, ualni>& processed, const String& id) const {
for (auto ref : referencing) {
if (processed.presents(ref->key)) return true;
}
processed.put(id, {});
for (auto ref : referencing) {
if (ref->val->isLooped(processed, ref->key)) return true;
}
return false;
}
};
struct Terminal {};