TODO : Make RE Grammar template independent. Difine Unified grammar format.

This commit is contained in:
IlyaShurupov 2023-11-02 15:55:55 +03:00 committed by Ilya Shurupov
parent 53b690dad9
commit 419ebb43d1
4 changed files with 115 additions and 11 deletions

View file

@ -1,4 +1,53 @@
#include "Grammar.hpp"
#include "NewPlacement.hpp"
using namespace tp;
ContextFreeGrammar::Arg::Arg(const String& id, bool terminal, bool epsilon) {
mId = id;
mIsTerminal = terminal;
mIsEpsilon = epsilon;
}
const String& ContextFreeGrammar::Arg::getId() const { return mId; }
bool ContextFreeGrammar::Arg::operator==(const Arg& in) const { return (mId == in.mId) && (mIsEpsilon == in.mIsEpsilon) && (mIsTerminal == in.mIsTerminal); }
ContextFreeGrammar::Rule::Rule(const String& id, const InitialierList<Arg>& args) {
mId = id;
mArgs = args;
}
bool ContextFreeGrammar::Rule::operator==(const Rule& in) const { return (mId == in.mId) && (mArgs == in.mArgs); }
bool ContextFreeGrammar::Rule::isProductive() const {
for (auto arg : mArgs) {
if (arg->getId() == mId) return false;
}
return true;
}
bool ContextFreeGrammar::NonTerminal::isProductive() const {
for (auto rule : rules) {
if (rule->isProductive()) return true;
}
return false;
}
bool ContextFreeGrammar::NonTerminal::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;
}
void ContextFreeGrammar::addRule(const Rule& rule) { mRules.append(rule); }
void ContextFreeGrammar::addRule(const String& id, const InitialierList<Arg>& args) { addRule(Rule(id, args)); }
void ContextFreeGrammar::setStart(const String& startRule) { mStartTerminal = startRule; }

View file

@ -12,15 +12,8 @@ SimpleParser::SimpleParser() {
ContextFreeGrammar contextFreeGrammar;
{
// use existing CF grammar interface
auto term = contextFreeGrammar.createTerminal();
auto nonTerm = contextFreeGrammar.createNonTerminal();
auto nonTerm2 = contextFreeGrammar.createNonTerminal();
contextFreeGrammar.addRule(nonTerm, { term, nonTerm2 });
contextFreeGrammar.addRule();
contextFreeGrammar.setStart(nonTerm);
contextFreeGrammar.addRule("a", { ContextFreeGrammar::Arg("") });
contextFreeGrammar.setStart("a");
}
// Define Regular grammar

View file

@ -3,11 +3,70 @@
#include "Buffer.hpp"
#include "LanguageCommon.hpp"
#include "Utils.hpp"
#include "Map.hpp"
#include "Strings.hpp"
namespace tp {
class ContextFreeGrammar {};
class ContextFreeGrammar {
public:
struct Arg {
friend class Rule;
public:
Arg() = default;
explicit Arg(const String& id, bool terminal = true, bool epsilon = false);
public:
bool operator==(const Arg& in) const;
[[nodiscard]] const String& getId() const;
private:
String mId;
bool mIsTerminal = false;
bool mIsEpsilon = false;
};
class Rule {
public:
Rule() = default;
Rule(const String& id, const InitialierList<Arg>& args);
public:
bool operator==(const Rule& in) const;
[[nodiscard]] bool isProductive() const;
private:
String mId;
Buffer<Arg> mArgs;
};
private:
// cache data
struct NonTerminal {
Buffer<Rule*> rules;
Map<String, NonTerminal*> references;
Map<String, NonTerminal*> referencing;
public:
[[nodiscard]] bool isProductive() const;
[[nodiscard]] bool isLooped(Map<String, ualni>& processed, const String& id) const;
};
public:
ContextFreeGrammar() = default;
public:
void addRule(const Rule& rule);
void addRule(const String& id, const InitialierList<Arg>& args);
void setStart(const String& startRule);
private:
Map<String, NonTerminal> mNonTerminals;
Buffer<Rule> mRules;
String mStartTerminal;
bool mIsLooped = false;
};
template <typename tAlphabetType, typename tTokType>
class RegularGrammar {