CF Grammar improvements
This commit is contained in:
parent
8feeb3d1c1
commit
a938bf9bb1
10 changed files with 262 additions and 20 deletions
62
Parser/private/CfGrammar.cpp
Normal file
62
Parser/private/CfGrammar.cpp
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
|
||||
#include "NewPlacement.hpp"
|
||||
#include "CfGrammar.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
bool CfGrammar::compile() {
|
||||
|
||||
if (!rules.length()) {
|
||||
printf("Grammar must have at leas one rule\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (startTerminal == String()) {
|
||||
printf("Using first rule's non-terminal as grammar's root. Define explicitly - 'Start : id'\n");
|
||||
startTerminal = rules.first()->data.id;
|
||||
}
|
||||
|
||||
// find all rules
|
||||
for (auto rule : rules) {
|
||||
|
||||
if (!rule->args.length()) {
|
||||
printf("Rule must have at leas one terminal or non-terminal. See rule '%s'\n", rule->id.read());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mNonTerminals.presents(rule->id)) {
|
||||
mNonTerminals.put(rule->id, {});
|
||||
}
|
||||
auto nonTerminal = &mNonTerminals.get(rule->id);
|
||||
|
||||
nonTerminal->rules.pushBack(&rule.data());
|
||||
}
|
||||
|
||||
for (auto nonTerminal : mNonTerminals) {
|
||||
for (auto rule : nonTerminal->val.rules) {
|
||||
for (auto arg : rule->args) {
|
||||
|
||||
if (arg->isTerminal) {
|
||||
mTerminals.put(rule->id, {});
|
||||
} else {
|
||||
auto idx = mNonTerminals.presents(arg->id);
|
||||
if (!idx) {
|
||||
printf("Referenced non-terminal '%s' is not defined\n", arg->id.read());
|
||||
return false;
|
||||
}
|
||||
auto reference = &mNonTerminals.getSlotVal(idx);
|
||||
reference->references.put(nonTerminal->key, &nonTerminal->val);
|
||||
nonTerminal->val.referencing.put(arg->id, reference);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto nonTerminal : mNonTerminals) {
|
||||
if (!nonTerminal->val.references.size() && nonTerminal->key != startTerminal) {
|
||||
printf("Non-terminal '%s' is defined but not used\n", nonTerminal->key.read());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue