Checking for non productive rules and loops in cfg
This commit is contained in:
parent
16115b483a
commit
0e4f4228de
3 changed files with 40 additions and 0 deletions
|
|
@ -145,5 +145,18 @@ bool CfGrammar::compile() {
|
||||||
rules.removeNode(rules.find(*rule.data()));
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "NewPlacement.hpp"
|
||||||
#include "Parser.hpp"
|
#include "Parser.hpp"
|
||||||
|
|
||||||
#include "Tokenizer.hpp"
|
#include "Tokenizer.hpp"
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,13 @@ namespace tp {
|
||||||
bool operator==(const Rule& in) const {
|
bool operator==(const Rule& in) const {
|
||||||
return (id == in.id) && (args == in.args);
|
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 {
|
struct Sentence {
|
||||||
|
|
@ -42,9 +49,28 @@ namespace tp {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct NonTerminal {
|
struct NonTerminal {
|
||||||
|
|
||||||
List<Rule*> rules;
|
List<Rule*> rules;
|
||||||
Map<String, NonTerminal*> references;
|
Map<String, NonTerminal*> references;
|
||||||
Map<String, NonTerminal*> referencing;
|
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 {};
|
struct Terminal {};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue