From 38957e678b91907b2321e88e0c8b827660a0d21b Mon Sep 17 00:00:00 2001 From: IlyaShurupov Date: Thu, 2 Nov 2023 15:55:55 +0300 Subject: [PATCH] TODO : Make RE Grammar template independent. Difine Unified grammar format. --- Language/private/Grammar.cpp | 49 ++++++++++++++++++++++++ Language/private/SimpleParser.cpp | 11 +----- Language/public/Grammar.hpp | 63 ++++++++++++++++++++++++++++++- TODO | 3 ++ 4 files changed, 115 insertions(+), 11 deletions(-) diff --git a/Language/private/Grammar.cpp b/Language/private/Grammar.cpp index 0dac427..799d917 100644 --- a/Language/private/Grammar.cpp +++ b/Language/private/Grammar.cpp @@ -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& 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& 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& args) { addRule(Rule(id, args)); } + +void ContextFreeGrammar::setStart(const String& startRule) { mStartTerminal = startRule; } \ No newline at end of file diff --git a/Language/private/SimpleParser.cpp b/Language/private/SimpleParser.cpp index 1c8b16f..81f6ae9 100644 --- a/Language/private/SimpleParser.cpp +++ b/Language/private/SimpleParser.cpp @@ -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 diff --git a/Language/public/Grammar.hpp b/Language/public/Grammar.hpp index 5f7984f..c1f5fa1 100644 --- a/Language/public/Grammar.hpp +++ b/Language/public/Grammar.hpp @@ -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& args); + + public: + bool operator==(const Rule& in) const; + [[nodiscard]] bool isProductive() const; + + private: + String mId; + Buffer mArgs; + }; + + private: + // cache data + struct NonTerminal { + Buffer rules; + Map references; + Map referencing; + + public: + [[nodiscard]] bool isProductive() const; + [[nodiscard]] bool isLooped(Map& processed, const String& id) const; + }; + + public: + ContextFreeGrammar() = default; + + public: + void addRule(const Rule& rule); + void addRule(const String& id, const InitialierList& args); + void setStart(const String& startRule); + + private: + Map mNonTerminals; + Buffer mRules; + String mStartTerminal; + bool mIsLooped = false; + }; template class RegularGrammar { diff --git a/TODO b/TODO index 458a572..29512ba 100644 --- a/TODO +++ b/TODO @@ -3,6 +3,9 @@ All: make more general structure for feature renders Language: + Grammar: + Store all RE Grammar API nodes in one buffer + rename Language module to FormalLanguage Merge parser and tokenizer module into grammar module