From e01d6dfa9d658425559a7ca7d49a88e6f205548d Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Fri, 11 Jul 2014 19:05:17 +0200 Subject: [PATCH] Split ContextPreserving from Unrestricted Grammar --- alib2/src/grammar/GrammarBase.cpp | 4 + alib2/src/grammar/GrammarBase.h | 5 +- alib2/src/grammar/GrammarToXMLComposer.cpp | 9 ++ alib2/src/grammar/GrammarToXMLComposer.h | 3 + .../ContextPreservingUnrestrictedGrammar.cpp | 122 ++++++++++++++++++ .../ContextPreservingUnrestrictedGrammar.h | 51 ++++++++ .../Unrestricted/UnrestrictedGrammar.cpp | 19 +-- 7 files changed, 194 insertions(+), 19 deletions(-) create mode 100644 alib2/src/grammar/Unrestricted/ContextPreservingUnrestrictedGrammar.cpp create mode 100644 alib2/src/grammar/Unrestricted/ContextPreservingUnrestrictedGrammar.h diff --git a/alib2/src/grammar/GrammarBase.cpp b/alib2/src/grammar/GrammarBase.cpp index cda2451564..af929e3434 100644 --- a/alib2/src/grammar/GrammarBase.cpp +++ b/alib2/src/grammar/GrammarBase.cpp @@ -69,6 +69,10 @@ bool GrammarBase::operator==(const UnrestrictedGrammar&) const { return false; } +bool GrammarBase::operator==(const ContextPreservingUnrestrictedGrammar&) const { + return false; +} + std::ostream& operator<<(std::ostream& os, const GrammarBase& grammar) { grammar >> os; return os; diff --git a/alib2/src/grammar/GrammarBase.h b/alib2/src/grammar/GrammarBase.h index 21bc658c6f..4953e8b004 100644 --- a/alib2/src/grammar/GrammarBase.h +++ b/alib2/src/grammar/GrammarBase.h @@ -25,12 +25,13 @@ class CNF; class GNF; class CSG; class NonContractingGrammar; +class ContextPreservingUnrestrictedGrammar; class UnrestrictedGrammar; /** * Abstract base class for all automata. */ -class GrammarBase : public std::elementBase<UnknownGrammar, LeftLG, LeftRG, RightLG, RightRG, LG, CFG, EpsilonFreeCFG, CNF, GNF, CSG, NonContractingGrammar, UnrestrictedGrammar> { +class GrammarBase : public std::elementBase<UnknownGrammar, LeftLG, LeftRG, RightLG, RightRG, LG, CFG, EpsilonFreeCFG, CNF, GNF, CSG, NonContractingGrammar, ContextPreservingUnrestrictedGrammar, UnrestrictedGrammar> { public: virtual GrammarBase* clone() const = 0; @@ -65,6 +66,8 @@ public: virtual bool operator==(const NonContractingGrammar& other) const; virtual bool operator==(const UnrestrictedGrammar& other) const; + + virtual bool operator==(const ContextPreservingUnrestrictedGrammar& other) const; virtual bool operator==(const GrammarBase& other) const = 0; diff --git a/alib2/src/grammar/GrammarToXMLComposer.cpp b/alib2/src/grammar/GrammarToXMLComposer.cpp index 6bb874ad22..781b5a160f 100644 --- a/alib2/src/grammar/GrammarToXMLComposer.cpp +++ b/alib2/src/grammar/GrammarToXMLComposer.cpp @@ -96,6 +96,11 @@ std::list<sax::Token> GrammarToXMLComposer::compose(const NonContractingGrammar& return out; } +std::list<sax::Token> GrammarToXMLComposer::compose(const ContextPreservingUnrestrictedGrammar& grammar) const { + std::list<sax::Token> out; + return out; +} + std::list<sax::Token> GrammarToXMLComposer::compose(const UnrestrictedGrammar& grammar) const { std::list<sax::Token> out; out.push_back(sax::Token("UnrestrictedGrammar", sax::Token::TokenType::START_ELEMENT)); @@ -241,6 +246,10 @@ void GrammarToXMLComposer::Visit(void* data, const NonContractingGrammar& gramma *((std::list<sax::Token>*) data) = this->compose(grammar); } +void GrammarToXMLComposer::Visit(void* data, const ContextPreservingUnrestrictedGrammar& grammar) const { + *((std::list<sax::Token>*) data) = this->compose(grammar); +} + void GrammarToXMLComposer::Visit(void* data, const UnrestrictedGrammar& grammar) const { *((std::list<sax::Token>*) data) = this->compose(grammar); } diff --git a/alib2/src/grammar/GrammarToXMLComposer.h b/alib2/src/grammar/GrammarToXMLComposer.h index 53f76cb656..c0433201cc 100644 --- a/alib2/src/grammar/GrammarToXMLComposer.h +++ b/alib2/src/grammar/GrammarToXMLComposer.h @@ -23,6 +23,7 @@ class CNF; class GNF; class CSG; class NonContractingGrammar; +#include "Unrestricted/ContextPreservingUnrestrictedGrammar.h" #include "Unrestricted/UnrestrictedGrammar.h" #include "../sax/Token.h" @@ -45,6 +46,7 @@ class GrammarToXMLComposer : public GrammarBase::const_visitor_type { void Visit(void*, const GNF& grammar) const; void Visit(void*, const CSG& grammar) const; void Visit(void*, const NonContractingGrammar& grammar) const; + void Visit(void*, const ContextPreservingUnrestrictedGrammar& grammar) const; void Visit(void*, const UnrestrictedGrammar& grammar) const; void composeNonterminalAlphabet(std::list<sax::Token>& out, const std::set<alphabet::Symbol>& symbols) const; @@ -78,6 +80,7 @@ public: std::list<sax::Token> compose(const GNF& grammar) const; std::list<sax::Token> compose(const CSG& grammar) const; std::list<sax::Token> compose(const NonContractingGrammar& grammar) const; + std::list<sax::Token> compose(const ContextPreservingUnrestrictedGrammar& grammar) const; std::list<sax::Token> compose(const UnrestrictedGrammar& grammar) const; }; diff --git a/alib2/src/grammar/Unrestricted/ContextPreservingUnrestrictedGrammar.cpp b/alib2/src/grammar/Unrestricted/ContextPreservingUnrestrictedGrammar.cpp new file mode 100644 index 0000000000..ecd4d70852 --- /dev/null +++ b/alib2/src/grammar/Unrestricted/ContextPreservingUnrestrictedGrammar.cpp @@ -0,0 +1,122 @@ +/* + * ContextPreservingUnrestrictedGrammar.cpp + * + * Created on: Nov 17, 2013 + * Author: martin + */ + +#include "ContextPreservingUnrestrictedGrammar.h" +#include "../../std/map.hpp" +#include "../GrammarException.h" +#include <algorithm> + +#include "../../alphabet/Symbol.h" + +namespace grammar { + +ContextPreservingUnrestrictedGrammar::ContextPreservingUnrestrictedGrammar(const alphabet::Symbol& initialSymbol) : TerminalNonterminalAlphabetInitialSymbol(initialSymbol) { + +} + +ContextPreservingUnrestrictedGrammar::ContextPreservingUnrestrictedGrammar(const std::set<alphabet::Symbol>& nonterminalAlphabet, const std::set<alphabet::Symbol>& terminalAlphabet, const alphabet::Symbol& initialSymbol) : TerminalNonterminalAlphabetInitialSymbol(initialSymbol) { + setNonterminalAlphabet(nonterminalAlphabet); + setTerminalAlphabet(terminalAlphabet); +} + +GrammarBase* ContextPreservingUnrestrictedGrammar::clone() const { + return new ContextPreservingUnrestrictedGrammar(*this); +} + +GrammarBase* ContextPreservingUnrestrictedGrammar::plunder() && { + return new ContextPreservingUnrestrictedGrammar(std::move(*this)); +} + +bool ContextPreservingUnrestrictedGrammar::removeTerminalSymbol(const alphabet::Symbol& symbol) { + for(const std::pair<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>>& rule : rules) { + if(std::find(rule.first.begin(), rule.first.end(), symbol) != rule.first.end()) + throw GrammarException("Symbol \"" + (std::string) symbol.getSymbol() + "\" is used in rule."); + + for(const std::vector<alphabet::Symbol>& rhs : rule.second) + if(std::find(rhs.begin(), rhs.end(), symbol) != rhs.end()) + throw GrammarException("Symbol \"" + (std::string) symbol.getSymbol() + "\" is used in rule."); + } + + return terminalAlphabet.erase(symbol); +} + +bool ContextPreservingUnrestrictedGrammar::removeNonterminalSymbol(const alphabet::Symbol& symbol) { + for(const std::pair<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>>& rule : rules) { + if(std::find(rule.first.begin(), rule.first.end(), symbol) != rule.first.end()) + throw GrammarException("Symbol \"" + (std::string) symbol.getSymbol() + "\" is used in rule."); + + for(const std::vector<alphabet::Symbol>& rhs : rule.second) + if(std::find(rhs.begin(), rhs.end(), symbol) != rhs.end()) + throw GrammarException("Symbol \"" + (std::string) symbol.getSymbol() + "\" is used in rule."); + } + + if(initialSymbol == symbol) + throw GrammarException("Symbol \"" + (std::string) symbol.getSymbol() + "\" is initial symbol."); + + + return nonterminalAlphabet.erase(symbol); +} + +bool ContextPreservingUnrestrictedGrammar::addRule(const std::vector<alphabet::Symbol>& leftHandSide, const std::vector<alphabet::Symbol>& rightHandSide) { + int lSize = leftHandSide.size(); + int rSize = rightHandSide.size(); + + if(lSize > rSize + 1) + throw GrammarException("Invalid size of right hand side of a rule"); + + int lContext; + int rContext; + for(lContext = 0; lContext < lSize - 1 && leftHandSide[lContext] == rightHandSide[lContext]; lContext++); + for(rContext = 0; rContext < lSize - 1 && leftHandSide[lSize - rContext] == rightHandSide[rSize - rContext]; rContext++); + + if(lContext + rContext + 1 < lSize) { + throw GrammarException("Rule must rewrite only one symbol"); + } else + if(lContext + rContext + 1 == lSize) { + if(!nonterminalAlphabet.count(leftHandSide[lContext])) throw GrammarException("Rule must rewrite nonterminal symbol"); + } else + if(/* lContext + rContext + 1 > lSize */ std::all_of(leftHandSide.end() - rContext + 1, leftHandSide.begin() + lContext - 1, [&](const alphabet::Symbol symbol) {return !nonterminalAlphabet.count(symbol);})) + throw GrammarException("Rule must rewrite nonterminal symbol"); + + + for(const alphabet::Symbol& symbol : leftHandSide) + if(terminalAlphabet.find(symbol) == terminalAlphabet.end() && nonterminalAlphabet.find(symbol) == nonterminalAlphabet.end()) + throw GrammarException("Symbol \"" + (std::string) symbol.getSymbol() + "\" is not neither terminal nor nonterminal symbol"); + + for(const alphabet::Symbol& symbol : rightHandSide) + if(terminalAlphabet.find(symbol) == terminalAlphabet.end() && nonterminalAlphabet.find(symbol) == nonterminalAlphabet.end()) + throw GrammarException("Symbol \"" + (std::string) symbol.getSymbol() + "\" is not neither terminal nor nonterminal symbol"); + + return rules[leftHandSide].insert(rightHandSide).second; +} + +const std::map<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>> ContextPreservingUnrestrictedGrammar::getRules() const { + return rules; +} + +bool ContextPreservingUnrestrictedGrammar::removeRule(const std::vector<alphabet::Symbol>& leftHandSide, const std::vector<alphabet::Symbol>& rightHandSide) { + return rules[leftHandSide].erase(rightHandSide); +} + +bool ContextPreservingUnrestrictedGrammar::operator==(const GrammarBase& other) const { + return other == *this; +} + +bool ContextPreservingUnrestrictedGrammar::operator==(const ContextPreservingUnrestrictedGrammar& other) const { + return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules; +} + +void ContextPreservingUnrestrictedGrammar::operator>>(std::ostream& out) const { + out << "(ContextPreservingUnrestrictedGrammar" + << "nonterminalAlphabet = " << nonterminalAlphabet + << "terminalAlphabet = " << terminalAlphabet + << "initialSymbol = " << initialSymbol + << "rules = " << rules + << ")"; +} + +} /* namespace grammar */ diff --git a/alib2/src/grammar/Unrestricted/ContextPreservingUnrestrictedGrammar.h b/alib2/src/grammar/Unrestricted/ContextPreservingUnrestrictedGrammar.h new file mode 100644 index 0000000000..082cfcfef6 --- /dev/null +++ b/alib2/src/grammar/Unrestricted/ContextPreservingUnrestrictedGrammar.h @@ -0,0 +1,51 @@ +/* + * ContextPreservingUnrestrictedGrammar.h + * + * Created on: Nov 17, 2013 + * Author: martin + */ + +#ifndef CONTEXT_PRESERVING_UNRESTRICTED_GRAMMAR_H_ +#define CONTEXT_PRESERVING_UNRESTRICTED_GRAMMAR_H_ + +#include "../GrammarBase.h" +#include <map> +#include "../common/TerminalNonterminalAlphabetInitialSymbol.h" + +namespace grammar { + +/** + * UnrestrictedGrammar grammar. Type 0 in Chomsky hierarchy. Produces recursively enumerable language. + */ +class ContextPreservingUnrestrictedGrammar : public std::element<ContextPreservingUnrestrictedGrammar, GrammarBase>, public TerminalNonterminalAlphabetInitialSymbol { + std::map<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>> rules; + +public: + ContextPreservingUnrestrictedGrammar(const alphabet::Symbol& initialSymbol); + + ContextPreservingUnrestrictedGrammar(const std::set<alphabet::Symbol>& nonTerminalSymbols, const std::set<alphabet::Symbol>& terminalSymbols, const alphabet::Symbol& initialSymbol); + + virtual GrammarBase* clone() const; + + virtual GrammarBase* plunder() &&; + + bool addRule(const std::vector<alphabet::Symbol>& leftHandSide, const std::vector<alphabet::Symbol>& rightHandSide); + + const std::map<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>> getRules() const; + + bool removeRule(const std::vector<alphabet::Symbol>& leftHandSide, const std::vector<alphabet::Symbol>& rightHandSide); + + bool removeTerminalSymbol(const alphabet::Symbol& symbol); + + bool removeNonterminalSymbol(const alphabet::Symbol& symbol); + + virtual bool operator==(const GrammarBase& other) const; + + virtual bool operator==(const ContextPreservingUnrestrictedGrammar& other) const; + + virtual void operator>>(std::ostream& os) const; +}; + +} /* namespace grammar */ + +#endif /* CONTEXT_PRESERVING_UNRESTRICTED_GRAMMAR_H_ */ diff --git a/alib2/src/grammar/Unrestricted/UnrestrictedGrammar.cpp b/alib2/src/grammar/Unrestricted/UnrestrictedGrammar.cpp index ed842072fe..28f2e366fa 100644 --- a/alib2/src/grammar/Unrestricted/UnrestrictedGrammar.cpp +++ b/alib2/src/grammar/Unrestricted/UnrestrictedGrammar.cpp @@ -62,24 +62,7 @@ bool UnrestrictedGrammar::removeNonterminalSymbol(const alphabet::Symbol& symbol } bool UnrestrictedGrammar::addRule(const std::vector<alphabet::Symbol>& leftHandSide, const std::vector<alphabet::Symbol>& rightHandSide) { - int lSize = leftHandSide.size(); - int rSize = rightHandSide.size(); - - if(lSize > rSize + 1) - throw GrammarException("Invalid size of right hand side of a rule"); - - int lContext; - int rContext; - for(lContext = 0; lContext < lSize - 1 && leftHandSide[lContext] == rightHandSide[lContext]; lContext++); - for(rContext = 0; rContext < lSize - 1 && leftHandSide[lSize - rContext] == rightHandSide[rSize - rContext]; rContext++); - - if(lContext + rContext + 1 < lSize) { - throw GrammarException("Rule must rewrite only one symbol"); - } else - if(lContext + rContext + 1 == lSize) { - if(!nonterminalAlphabet.count(leftHandSide[lContext])) throw GrammarException("Rule must rewrite nonterminal symbol"); - } else - if(/* lContext + rContext + 1 > lSize */ std::all_of(leftHandSide.end() - rContext + 1, leftHandSide.begin() + lContext - 1, [&](const alphabet::Symbol symbol) {return !nonterminalAlphabet.count(symbol);})) + if(std::all_of(leftHandSide.begin(), leftHandSide.end(), [&](const alphabet::Symbol symbol) {return !nonterminalAlphabet.count(symbol);})) throw GrammarException("Rule must rewrite nonterminal symbol"); -- GitLab