From 29df0609ae08aecb2f9622cd109d383fa9387af0 Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Mon, 7 Jul 2014 21:35:17 +0200 Subject: [PATCH] base implementation of Unknown and Unrestricted G --- alib2/src/grammar/Grammar.cpp | 78 +++++++++++ alib2/src/grammar/Grammar.h | 47 +++++++ alib2/src/grammar/GrammarBase.cpp | 78 +++++++++++ alib2/src/grammar/GrammarBase.h | 79 +++++++++++ alib2/src/grammar/GrammarException.cpp | 23 ++++ alib2/src/grammar/GrammarException.h | 27 ++++ alib2/src/grammar/UnknownGrammar.cpp | 79 +++++++++++ alib2/src/grammar/UnknownGrammar.h | 60 ++++++++ alib2/src/grammar/UnknownRule.cpp | 129 ++++++++++++++++++ alib2/src/grammar/UnknownRule.h | 73 ++++++++++ .../Unrestricted/UnrestrictedGrammar.cpp | 73 ++++++++++ .../Unrestricted/UnrestrictedGrammar.h | 40 ++++++ ...rminalNonterminalAlphabetInitialSymbol.cpp | 108 +++++++++++++++ ...TerminalNonterminalAlphabetInitialSymbol.h | 106 ++++++++++++++ 14 files changed, 1000 insertions(+) create mode 100644 alib2/src/grammar/Grammar.cpp create mode 100644 alib2/src/grammar/Grammar.h create mode 100644 alib2/src/grammar/GrammarBase.cpp create mode 100644 alib2/src/grammar/GrammarBase.h create mode 100644 alib2/src/grammar/GrammarException.cpp create mode 100644 alib2/src/grammar/GrammarException.h create mode 100644 alib2/src/grammar/UnknownGrammar.cpp create mode 100644 alib2/src/grammar/UnknownGrammar.h create mode 100644 alib2/src/grammar/UnknownRule.cpp create mode 100644 alib2/src/grammar/UnknownRule.h create mode 100644 alib2/src/grammar/Unrestricted/UnrestrictedGrammar.cpp create mode 100644 alib2/src/grammar/Unrestricted/UnrestrictedGrammar.h create mode 100644 alib2/src/grammar/common/TerminalNonterminalAlphabetInitialSymbol.cpp create mode 100644 alib2/src/grammar/common/TerminalNonterminalAlphabetInitialSymbol.h diff --git a/alib2/src/grammar/Grammar.cpp b/alib2/src/grammar/Grammar.cpp new file mode 100644 index 0000000000..fc0fc1ad5a --- /dev/null +++ b/alib2/src/grammar/Grammar.cpp @@ -0,0 +1,78 @@ +/* + * Grammar.cpp + * + * Created on: Apr 16, 2013 + * Author: Martin Zak + */ + +#include "Grammar.h" + +namespace grammar { + +Grammar::Grammar(const GrammarBase& grammar) : grammar(grammar.clone()) { + +} + +Grammar::Grammar(GrammarBase&& grammar) : grammar(std::move(grammar).plunder()) { + +} + +Grammar::Grammar(const Grammar& other) : grammar(other.getGrammar().clone()) { + +} + +Grammar::Grammar(Grammar&& other) noexcept : grammar(std::move(other.getGrammar()).plunder()) { + other.grammar = NULL; +} + +Grammar& Grammar::operator=(const Grammar& other) { + if(this == &other) return *this; + + delete grammar; + grammar = other.getGrammar().clone(); + + return *this; +} + +Grammar& Grammar::operator=(Grammar&& other) noexcept { + std::swap(this->grammar, other.grammar); + return *this; +} + +Grammar::~Grammar() { + delete grammar; +} + +const GrammarBase& Grammar::getGrammar() const { + return *grammar; +} + +GrammarBase& Grammar::getGrammar() { + return *grammar; +} + +void Grammar::setGrammar(const GrammarBase& grammar) { + delete this->grammar; + this->grammar = grammar.clone(); +} + +void Grammar::setGrammar(GrammarBase&& grammar) { + delete this->grammar; + this->grammar = std::move(grammar).plunder(); +} + +bool Grammar::operator!=(const Grammar& other) const { + return !(*this == other); +} + +bool Grammar::operator==(const Grammar& other) const { + return this->getGrammar() == other.getGrammar(); +} + +std::ostream& operator<<(std::ostream& os, const Grammar& grammar) { + os << grammar.getGrammar(); + return os; +} + +} /* namespace grammar */ + diff --git a/alib2/src/grammar/Grammar.h b/alib2/src/grammar/Grammar.h new file mode 100644 index 0000000000..95ffefe2bd --- /dev/null +++ b/alib2/src/grammar/Grammar.h @@ -0,0 +1,47 @@ +/* + * Grammar.h + * + * Created on: Apr 10, 2013 + * Author: Martin Zak + */ + +#ifndef GRAMMAR_H_ +#define GRAMMAR_H_ + +#include "../std/visitor.hpp" +#include "GrammarBase.h" + +namespace grammar { + +/** + * Wrapper around automata. + */ +class Grammar { +protected: + GrammarBase* grammar; +public: + explicit Grammar(const GrammarBase& grammar); + explicit Grammar(GrammarBase&& grammar); + Grammar(const Grammar& other); + Grammar(Grammar&&) noexcept; + Grammar& operator=(const Grammar& other); + Grammar& operator=(Grammar&& other) noexcept; + virtual ~Grammar() noexcept; + + const GrammarBase& getGrammar() const; + GrammarBase& getGrammar(); + + void setGrammar(const GrammarBase& grammar); + void setGrammar(GrammarBase&& grammar); + + bool operator!=(const Grammar& other) const; + + bool operator==(const Grammar& other) const; + + friend std::ostream& operator<<(std::ostream& os, const Grammar& grammar); +}; + +} /* namespace grammar */ + +#endif /* GRAMMAR_H_ */ + diff --git a/alib2/src/grammar/GrammarBase.cpp b/alib2/src/grammar/GrammarBase.cpp new file mode 100644 index 0000000000..cda2451564 --- /dev/null +++ b/alib2/src/grammar/GrammarBase.cpp @@ -0,0 +1,78 @@ +/* + * GrammarBase.cpp + * + * Created on: Apr 16, 2013 + * Author: Jan Travnicek + */ + +#include "GrammarBase.h" + +namespace grammar { + +GrammarBase::~GrammarBase() { + +} + +bool GrammarBase::operator!=(const GrammarBase& other) const { + return !(*this == other); +} + +bool GrammarBase::operator==(const UnknownGrammar&) const { + return false; +} + +bool GrammarBase::operator==(const LeftLG&) const { + return false; +} + +bool GrammarBase::operator==(const LeftRG&) const { + return false; +} + +bool GrammarBase::operator==(const RightLG&) const{ + return false; +} + +bool GrammarBase::operator==(const RightRG&) const{ + return false; +} + +bool GrammarBase::operator==(const LG&) const { + return false; +} + +bool GrammarBase::operator==(const CFG&) const { + return false; +} + +bool GrammarBase::operator==(const EpsilonFreeCFG&) const { + return false; +} + +bool GrammarBase::operator==(const CNF&) const { + return false; +} + +bool GrammarBase::operator==(const GNF&) const { + return false; +} + +bool GrammarBase::operator==(const CSG&) const { + return false; +} + +bool GrammarBase::operator==(const NonContractingGrammar&) const { + return false; +} + +bool GrammarBase::operator==(const UnrestrictedGrammar&) const { + return false; +} + +std::ostream& operator<<(std::ostream& os, const GrammarBase& grammar) { + grammar >> os; + return os; +} + +} /* namespace grammar */ + diff --git a/alib2/src/grammar/GrammarBase.h b/alib2/src/grammar/GrammarBase.h new file mode 100644 index 0000000000..21bc658c6f --- /dev/null +++ b/alib2/src/grammar/GrammarBase.h @@ -0,0 +1,79 @@ +/* + * GrammarBase.h + * + * Created on: Apr 10, 2013 + * Author: Jan Travnicek + */ + +#ifndef GRAMMAR_BASE_H_ +#define GRAMMAR_BASE_H_ + +#include "../std/visitor.hpp" +#include <iostream> + +namespace grammar { + +class UnknownGrammar; +class LeftLG; +class LeftRG; +class RightLG; +class RightRG; +class LG; +class CFG; +class EpsilonFreeCFG; +class CNF; +class GNF; +class CSG; +class NonContractingGrammar; +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> { +public: + virtual GrammarBase* clone() const = 0; + + virtual GrammarBase* plunder() && = 0; + + virtual ~GrammarBase() noexcept; + + virtual bool operator!=(const GrammarBase& other) const; + + virtual bool operator==(const UnknownGrammar& other) const; + + virtual bool operator==(const LeftLG& other) const; + + virtual bool operator==(const LeftRG& other) const; + + virtual bool operator==(const RightLG& other) const; + + virtual bool operator==(const RightRG& other) const; + + virtual bool operator==(const LG& other) const; + + virtual bool operator==(const CFG& other) const; + + virtual bool operator==(const EpsilonFreeCFG& other) const; + + virtual bool operator==(const CNF& other) const; + + virtual bool operator==(const GNF& other) const; + + virtual bool operator==(const CSG& other) const; + + virtual bool operator==(const NonContractingGrammar& other) const; + + virtual bool operator==(const UnrestrictedGrammar& other) const; + + virtual bool operator==(const GrammarBase& other) const = 0; + + friend std::ostream& operator<<(std::ostream& os, const GrammarBase& grammar); + + virtual void operator>>(std::ostream&) const = 0; +}; + +} /* namespace grammar */ + +#endif /* GRAMMAR_BASE_H_ */ + diff --git a/alib2/src/grammar/GrammarException.cpp b/alib2/src/grammar/GrammarException.cpp new file mode 100644 index 0000000000..3f139de0de --- /dev/null +++ b/alib2/src/grammar/GrammarException.cpp @@ -0,0 +1,23 @@ +/* + * GrammarException.cpp + * + * Created on: Apr 1, 2013 + * Author: Martin Zak + */ + +#include "GrammarException.h" + +namespace grammar { + +GrammarException::GrammarException() { +} + +GrammarException::GrammarException(const std::string& cause) : + AlibException(cause) { +} + +GrammarException::~GrammarException() throw () { + +} + +} /* namespace grammar */ diff --git a/alib2/src/grammar/GrammarException.h b/alib2/src/grammar/GrammarException.h new file mode 100644 index 0000000000..6977f57a56 --- /dev/null +++ b/alib2/src/grammar/GrammarException.h @@ -0,0 +1,27 @@ +/* + * GrammarException.h + * + * Created on: Apr 1, 2013 + * Author: Martin Zak + */ + +#ifndef GRAMMAR_EXCEPTION_H_ +#define GRAMMAR_EXCEPTION_H_ + +#include "../exception/AlibException.h" + +namespace grammar { + +/** + * Exception thrown by an grammar, grammar parser or grammar printer. + */ +class GrammarException: public exception::AlibException { +public: + GrammarException(); + explicit GrammarException(const std::string& cause); + virtual ~GrammarException() throw (); +}; + +} /* namespace grammar */ + +#endif /* GRAMMAR_EXCEPTION_H_ */ diff --git a/alib2/src/grammar/UnknownGrammar.cpp b/alib2/src/grammar/UnknownGrammar.cpp new file mode 100644 index 0000000000..bf6d93da60 --- /dev/null +++ b/alib2/src/grammar/UnknownGrammar.cpp @@ -0,0 +1,79 @@ +/* + * UnknownGrammar.cpp + * + * Created on: Nov 2, 2013 + * Author: Martin Zak + */ + +#include "UnknownGrammar.h" +#include "GrammarException.h" + +namespace grammar { + +UnknownGrammar::UnknownGrammar() : initialSymbol(NULL) { + +} + +bool UnknownGrammar::addTerminalSymbol(const alphabet::Symbol& symbol) { + return terminalAlphabet.insert(symbol).second; +} + +bool UnknownGrammar::removeTerminalSymbol(const alphabet::Symbol& symbol) { + return terminalAlphabet.insert(symbol).second; +} + +const std::set<alphabet::Symbol>& UnknownGrammar::getTerminalAlphabet() const { + return terminalAlphabet; +} + +void UnknownGrammar::setTerminalAlphabet(std::set<alphabet::Symbol>& alphabet) { + terminalAlphabet = alphabet; +} + +bool UnknownGrammar::addNonterminalSymbol(const alphabet::Symbol& symbol) { + return nonterminalAlphabet.insert(symbol).second; +} + +bool UnknownGrammar::removeNonterminalSymbol(const alphabet::Symbol& symbol) { + return nonterminalAlphabet.insert(symbol).second; +} + +const std::set<alphabet::Symbol>& UnknownGrammar::getNonterminalAlphabet() const { + return nonterminalAlphabet; +} + +void UnknownGrammar::setNonterminalAlphabet(std::set<alphabet::Symbol>& alphabet) { + nonterminalAlphabet = alphabet; +} + +void UnknownGrammar::setInitialSymbol(const alphabet::Symbol& symbol) { + delete initialSymbol; + initialSymbol = new alphabet::Symbol(symbol); +} + +bool UnknownGrammar::hasInitialSymbol() const { + return initialSymbol != NULL; +} + +void UnknownGrammar::clearInitialSymbol() { + delete initialSymbol; + initialSymbol = NULL; +} + +const alphabet::Symbol& UnknownGrammar::getInitialSymbol() const { + return *initialSymbol; +} + +int UnknownGrammar::addRule(const UnknownRule& rule) { + return rules.insert(rule).second; +} + +int UnknownGrammar::removeRule(const UnknownRule& rule) { + return rules.erase(rule); +} + +const std::set<UnknownRule>& UnknownGrammar::getRules() const { + return rules; +} + +} /* namespace grammar */ diff --git a/alib2/src/grammar/UnknownGrammar.h b/alib2/src/grammar/UnknownGrammar.h new file mode 100644 index 0000000000..39efacd1d2 --- /dev/null +++ b/alib2/src/grammar/UnknownGrammar.h @@ -0,0 +1,60 @@ +/* + * UnknownGrammar.h + * + * Created on: Nov 3, 2013 + * Author: Jan Travnicek + */ + +#ifndef UNKNOWN_GRAMMAR_H_ +#define UNKNOWN_GRAMMAR_H_ + +#include "UnknownRule.h" +#include <set> + +namespace grammar { + +/** + * Class representing unknown grammar which was parsed from the XML. + */ +class UnknownGrammar { + std::set<alphabet::Symbol> terminalAlphabet; + std::set<alphabet::Symbol> nonterminalAlphabet; + std::set<UnknownRule> rules; + alphabet::Symbol* initialSymbol; +protected: + UnknownGrammar(); + + bool addTerminalSymbol(const alphabet::Symbol& symbol); + + bool removeTerminalSymbol(const alphabet::Symbol& symbol); + + const std::set<alphabet::Symbol>& getTerminalAlphabet() const; + + void setTerminalAlphabet(std::set<alphabet::Symbol>& alphabet); + + bool addNonterminalSymbol(const alphabet::Symbol& symbol); + + bool removeNonterminalSymbol(const alphabet::Symbol& symbol); + + const std::set<alphabet::Symbol>& getNonterminalAlphabet() const; + + void setNonterminalAlphabet(std::set<alphabet::Symbol>& alphabet); + + void setInitialSymbol(const alphabet::Symbol& symbol); + + bool hasInitialSymbol() const; + + void clearInitialSymbol(); + + const alphabet::Symbol& getInitialSymbol() const; + + int addRule(const UnknownRule& rule); + + int removeRule(const UnknownRule& rule); + + const std::set<UnknownRule>& getRules() const; + +}; + +} /* namespace grammar */ +#endif /* UNKNOWN_GRAMMAR_H_ */ diff --git a/alib2/src/grammar/UnknownRule.cpp b/alib2/src/grammar/UnknownRule.cpp new file mode 100644 index 0000000000..ac68c99fe1 --- /dev/null +++ b/alib2/src/grammar/UnknownRule.cpp @@ -0,0 +1,129 @@ +/* + * UnknownRule.cpp + * + * Created on: Nov 2, 2013 + * Author: Martin Zak + */ + +#include "UnknownRule.h" +#include <algorithm> + +namespace grammar { + +UnknownRule::UnknownRule() { +} + +UnknownRule::UnknownRule(const list<Symbol>& leftSide, const list<Symbol>& rightSide) : + leftSide(leftSide), rightSide(rightSide) { +} + +void grammar::UnknownRule::setLeftSide(const list<Symbol>& leftSide) { + this->leftSide = leftSide; +} + +void grammar::UnknownRule::setRightSide(const list<Symbol>& rightSide) { + this->rightSide = rightSide; +} + +const list<Symbol>& grammar::UnknownRule::getLeftSide() const { + return leftSide; +} + +const list<Symbol>& grammar::UnknownRule::getRightSide() const { + return rightSide; +} + +bool UnknownRule::containsSymbol(const Symbol& symbol) const { + if (find(leftSide.begin(), leftSide.end(), symbol) != leftSide.end()) { + return true; + } + + if (find(rightSide.begin(), rightSide.end(), symbol) != rightSide.end()) { + return true; + } + + return false; +} + +string UnknownRule::toString() const { + string output; + output += "["; + for(auto const& symbol : leftSide) { + output += " " + (std::string) symbol.getSymbol(); + } + output += " -> "; + for(auto const& symbol : rightSide) { + output += " " + (std::string) symbol.getSymbol(); + } + + output += "]"; + return output; +} + +bool UnknownRule::operator <(const UnknownRule& other) const { + if (leftSide.size() != other.leftSide.size()) { + return leftSide.size() < other.leftSide.size(); + } + + if (rightSide.size() != other.rightSide.size()) { + return rightSide.size() < other.rightSide.size(); + } + + list<Symbol>::const_iterator left = leftSide.begin(); + list<Symbol>::const_iterator otherLeft = other.leftSide.begin(); + while (left != leftSide.end()) { + if (*left != *otherLeft) { + return *left < *otherLeft; + } + left++; + otherLeft++; + } + + list<Symbol>::const_iterator right = rightSide.begin(); + list<Symbol>::const_iterator otherRight = other.rightSide.begin(); + while (right != rightSide.end()) { + if (*right != *otherRight) { + return *right < *otherRight; + } + right++; + otherRight++; + } + + return false; +} + +bool UnknownRule::operator ==(const UnknownRule& other) const { + return equal(leftSide.begin(), leftSide.end(), other.leftSide.begin()) + && equal(rightSide.begin(), rightSide.end(), other.rightSide.begin()); +} + +bool UnknownRule::operator !=(const UnknownRule& other) const { + return !equal(leftSide.begin(), leftSide.end(), other.leftSide.begin()) + || !equal(rightSide.begin(), rightSide.end(), other.rightSide.begin()); +} + +ostream& operator<<(ostream& out, const UnknownRule& rule) { + bool first; + out << " leftSide = ["; + + first = true; + for(list<Symbol>::const_iterator iter = rule.leftSide.begin(); iter != rule.leftSide.end(); iter++) { + if(!first) out << ", "; + first = false; + out << *iter; + } + + out << "] rightSide = ["; + + first = true; + for(list<Symbol>::const_iterator iter = rule.rightSide.begin(); iter != rule.rightSide.end(); iter++) { + if(!first) out << ", "; + first = false; + out << *iter; + } + out << "]"; + + return out; +} + +} /* namespace grammar */ diff --git a/alib2/src/grammar/UnknownRule.h b/alib2/src/grammar/UnknownRule.h new file mode 100644 index 0000000000..86c5185319 --- /dev/null +++ b/alib2/src/grammar/UnknownRule.h @@ -0,0 +1,73 @@ +/* + * UnknownRule.h + * + * Created on: Nov 2, 2013 + * Author: Martin Zak + */ + +#ifndef UNKNOWN_RULE_H_ +#define UNKNOWN_RULE_H_ + +#include <list> +#include "../alphabet/Symbol.h" + +namespace grammar { + +using namespace std; +using namespace alphabet; + +/** + * Represents rewrite rule (production) of a Grammar. + */ +class UnknownRule { +private: + list<Symbol> leftSide; + list<Symbol> rightSide; +public: + UnknownRule(); + UnknownRule(const list<Symbol>& leftSide, const list<Symbol>& rightSide); + + /** + * Sets left side of the rule. + * @param leftSide list of symbols to set + */ + void setLeftSide(const list<Symbol>& leftSide); + + /** + * Sets right side of the rule. + * @param rightSide list of symbols to set + */ + void setRightSide(const list<Symbol>& rightSide); + + /** + * @return list of symbols on the left side of the UnknownRule + */ + const list<Symbol>& getLeftSide() const; + + /** + * @return list of symbols on the right side of the UnknownRule + */ + const list<Symbol>& getRightSide() const; + + /** + * Checks that UnknownRule contains given symbol. + * @param symbol Symbol to find + * @return true when UnknownRule contains the symbol, false otherwise + */ + bool containsSymbol(const Symbol& symbol) const; + + /** + * Converts rule into human readable string. + * @return string in format [ leftSide -> rightSide ] + */ + string toString() const; + + bool operator <(const UnknownRule& other) const; + bool operator ==(const UnknownRule& other) const; + bool operator !=(const UnknownRule& other) const; + + friend ostream& operator<<(ostream&, const UnknownRule&); +}; + +} /* namespace grammar */ +#endif /* UNKNOWN_RULE_H_ */ diff --git a/alib2/src/grammar/Unrestricted/UnrestrictedGrammar.cpp b/alib2/src/grammar/Unrestricted/UnrestrictedGrammar.cpp new file mode 100644 index 0000000000..a68e7a1cd7 --- /dev/null +++ b/alib2/src/grammar/Unrestricted/UnrestrictedGrammar.cpp @@ -0,0 +1,73 @@ +/* + * UnrestrictedGrammar.cpp + * + * Created on: Nov 17, 2013 + * Author: martin + */ + +#include "UnrestrictedGrammar.h" +#include "../GrammarException.h" +#include <algorithm> + +namespace grammar { + +UnrestrictedGrammar::UnrestrictedGrammar(const alphabet::Symbol& initialSymbol) : TerminalNonterminalAlphabetInitialSymbol(initialSymbol) { + +} + +UnrestrictedGrammar::UnrestrictedGrammar(const std::set<alphabet::Symbol>& nonterminalAlphabet, const std::set<alphabet::Symbol>& terminalAlphabet, const alphabet::Symbol& initialSymbol) : TerminalNonterminalAlphabetInitialSymbol(initialSymbol) { + setNonterminalAlphabet(nonterminalAlphabet); + setTerminalAlphabet(terminalAlphabet); +} + +bool UnrestrictedGrammar::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 UnrestrictedGrammar::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 UnrestrictedGrammar::addRule(const std::vector<alphabet::Symbol>& leftHandSide, const std::vector<alphabet::Symbol>& rightHandSide) { + 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>>> UnrestrictedGrammar::getRules() const { + return rules; +} + +bool UnrestrictedGrammar::removeRule(const std::vector<alphabet::Symbol>& leftHandSide, const std::vector<alphabet::Symbol>& rightHandSide) { + return rules[leftHandSide].erase(rightHandSide); +} + +} /* namespace grammar */ diff --git a/alib2/src/grammar/Unrestricted/UnrestrictedGrammar.h b/alib2/src/grammar/Unrestricted/UnrestrictedGrammar.h new file mode 100644 index 0000000000..f49188ce01 --- /dev/null +++ b/alib2/src/grammar/Unrestricted/UnrestrictedGrammar.h @@ -0,0 +1,40 @@ +/* + * UnrestrictedGrammar.h + * + * Created on: Nov 17, 2013 + * Author: martin + */ + +#ifndef UNRESTRICTED_GRAMMAR_H_ +#define UNRESTRICTED_GRAMMAR_H_ + +#include "../common/TerminalNonterminalAlphabetInitialSymbol.h" +#include <map> + +namespace grammar { + +/** + * Unrestricted grammar. Type 0 in Chomsky hierarchy. Produces recursively enumerable language. + */ +class UnrestrictedGrammar: public TerminalNonterminalAlphabetInitialSymbol { + std::map<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>> rules; + +public: + UnrestrictedGrammar(const alphabet::Symbol& initialSymbol); + + UnrestrictedGrammar(const std::set<alphabet::Symbol>& nonTerminalSymbols, const std::set<alphabet::Symbol>& terminalSymbols, const alphabet::Symbol& initialSymbol); + + 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); +}; + +} /* namespace grammar */ + +#endif /* UNRESTRICTED_GRAMMAR_H_ */ diff --git a/alib2/src/grammar/common/TerminalNonterminalAlphabetInitialSymbol.cpp b/alib2/src/grammar/common/TerminalNonterminalAlphabetInitialSymbol.cpp new file mode 100644 index 0000000000..25a72e8f28 --- /dev/null +++ b/alib2/src/grammar/common/TerminalNonterminalAlphabetInitialSymbol.cpp @@ -0,0 +1,108 @@ +/* + * TerminalNonterminalAlphabetAlphabetInitialSymbol.cpp + * + * Created on: Nov 2, 2013 + * Author: Martin Zak + */ + +#include "TerminalNonterminalAlphabetInitialSymbol.h" +#include "../GrammarException.h" +#include "../../alphabet/LabeledSymbol.h" +#include "../../label/Label.h" +#include "../../label/NextLabel.h" +#include "../../alphabet/LabeledSymbol.h" +#include <limits.h> + +namespace grammar { + +TerminalNonterminalAlphabetInitialSymbol::TerminalNonterminalAlphabetInitialSymbol(const alphabet::Symbol& initialSymbol) : initialSymbol(initialSymbol) { + addTerminalSymbol(initialSymbol); +} + +bool TerminalNonterminalAlphabetInitialSymbol::addTerminalSymbol(const alphabet::Symbol& symbol) { + if(nonterminalAlphabet.find(symbol) != nonterminalAlphabet.end()){ + throw GrammarException("Symbol \"" + (std::string) symbol.getSymbol() + "\" is nonterminal symbol."); + } + + return terminalAlphabet.insert(symbol).second; +} + +const std::set<alphabet::Symbol>& TerminalNonterminalAlphabetInitialSymbol::getTerminalAlphabet() const { + return terminalAlphabet; +} + +void TerminalNonterminalAlphabetInitialSymbol::setTerminalAlphabet(const std::set<alphabet::Symbol>& alphabet) { + std::set<alphabet::Symbol> removed; + std::set_difference(terminalAlphabet.begin(), terminalAlphabet.end(), alphabet.begin(), alphabet.end(), std::inserter(removed, removed.end())); + + std::set<alphabet::Symbol> added; + std::set_difference(alphabet.begin(), alphabet.end(), terminalAlphabet.begin(), terminalAlphabet.end(), std::inserter(added, added.end())); + + for(const alphabet::Symbol& removedSymbol : removed) { + removeTerminalSymbol(removedSymbol); + } + + for(const alphabet::Symbol& addedSymbol : added) { + addTerminalSymbol(addedSymbol); + } +} + +bool TerminalNonterminalAlphabetInitialSymbol::addNonterminalSymbol(const alphabet::Symbol& symbol) { + if(terminalAlphabet.find(symbol) != terminalAlphabet.end()){ + throw GrammarException("Symbol \"" + (std::string) symbol.getSymbol() + "\" is terminal symbol."); + } + + return nonterminalAlphabet.insert(symbol).second; +} + +const std::set<alphabet::Symbol>& TerminalNonterminalAlphabetInitialSymbol::getNonterminalAlphabet() const { + return nonterminalAlphabet; +} + +void TerminalNonterminalAlphabetInitialSymbol::setNonterminalAlphabet(const std::set<alphabet::Symbol>& alphabet) { + std::set<alphabet::Symbol> removed; + std::set_difference(nonterminalAlphabet.begin(), nonterminalAlphabet.end(), alphabet.begin(), alphabet.end(), std::inserter(removed, removed.end())); + + std::set<alphabet::Symbol> added; + std::set_difference(alphabet.begin(), alphabet.end(), nonterminalAlphabet.begin(), nonterminalAlphabet.end(), std::inserter(added, added.end())); + + for(const alphabet::Symbol& removedSymbol : removed) { + removeNonterminalSymbol(removedSymbol); + } + + for(const alphabet::Symbol& addedSymbol : added) { + addNonterminalSymbol(addedSymbol); + } +} + +const alphabet::Symbol& TerminalNonterminalAlphabetInitialSymbol::getInitialSymbol() const{ + return initialSymbol; +} + +void TerminalNonterminalAlphabetInitialSymbol::setInitialSymbol(const alphabet::Symbol& symbol) { + if(nonterminalAlphabet.find(symbol) == nonterminalAlphabet.end()) { + throw GrammarException("Symbol \"" + (std::string) symbol.getSymbol() + "\" isn't nonterminal symbol."); + } + + initialSymbol = symbol; +} + +alphabet::Symbol TerminalNonterminalAlphabetInitialSymbol::createUniqueSymbol(const alphabet::Symbol& base, const std::set<alphabet::Symbol>& terminalAlphabet, const std::set<alphabet::Symbol>& nonterminalAlphabet) { + label::NextLabel nextLabelCreator; + + const alphabet::LabeledSymbol* baseSymbol = dynamic_cast<const alphabet::LabeledSymbol*>(&(base.getSymbol())); + if(baseSymbol == NULL) + throw GrammarException("Could not create unique symbol with nonlabeled base symbol " + (std::string) base.getSymbol() + "." ); + + int i = 0; + do { + label::Label nextLabel = nextLabelCreator.nextLabel(baseSymbol->getLabel()); + alphabet::Symbol attempt = alphabet::Symbol(alphabet::LabeledSymbol(nextLabel)); + if(terminalAlphabet.count(attempt) == 0 && nonterminalAlphabet.count(attempt) == 0) + return attempt; + } while(++i < INT_MAX); + + throw GrammarException("Could not create unique symbol with base symbol " + (std::string) base.getSymbol() + "." ); +} + +} /* namespace grammar */ diff --git a/alib2/src/grammar/common/TerminalNonterminalAlphabetInitialSymbol.h b/alib2/src/grammar/common/TerminalNonterminalAlphabetInitialSymbol.h new file mode 100644 index 0000000000..0f2372501e --- /dev/null +++ b/alib2/src/grammar/common/TerminalNonterminalAlphabetInitialSymbol.h @@ -0,0 +1,106 @@ +/* + * TerminalNonterminalAlphabetInitialSymbol.h + * + * Created on: Nov 2, 2013 + * Author: Martin Zak + */ + +#ifndef TERMINAL_NONTERMINAL_ALPHABET_INITIAL_SYMBOL_H_ +#define TERMINAL_NONTERMINAL_ALPHABET_INITIAL_SYMBOL_H_ + +#include <set> +#include <list> +#include <algorithm> + +#include "../../alphabet/Symbol.h" + +namespace grammar { + +/** + * Abstract class representing grammar. Implements methods for manipulation + * with terminal and nonterminal symbols. Only method, which is not implemented + * is grammar specific isValidRule. + */ +class TerminalNonterminalAlphabetInitialSymbol { +protected: + std::set<alphabet::Symbol> terminalAlphabet; + std::set<alphabet::Symbol> nonterminalAlphabet; + alphabet::Symbol initialSymbol; + +public: + TerminalNonterminalAlphabetInitialSymbol(const alphabet::Symbol& initialSymbol); + + /** + * Adds terminal symbol to the terminal alphabet. + * @param symbol Symbol to add + * @throws GrammarException when symbol is already a nonterminal symbol + */ + bool addTerminalSymbol(const alphabet::Symbol& symbol); + + /** + * Removes terminal symbol from the terminal alphabet. + * @param symbol Symbol to remove + * @throws GrammarException when symbol is used in rule + */ + virtual bool removeTerminalSymbol(const alphabet::Symbol& symbol) = 0; + + /** + * return set of terminal symbols + */ + const std::set<alphabet::Symbol>& getTerminalAlphabet() const; + + /** + * Sets the terminal alphabet + */ + void setTerminalAlphabet(const std::set<alphabet::Symbol>& alphabet); + + /** + * Adds nonterminal symbol to the alphabet of nonterminals. + * @param symbol Symbol to add + * @throws GrammarException when symbol is already a terminal + */ + bool addNonterminalSymbol(const alphabet::Symbol& symbol); + + /** + * Removes nonterminal symbol from the grammar. + * @param symbol Symbol to remove + * @throws GrammarException when symbol is used in rule + */ + virtual bool removeNonterminalSymbol(const alphabet::Symbol& symbol) = 0; + + /** + * @return set of nonterminal symbols + */ + const std::set<alphabet::Symbol>& getNonterminalAlphabet() const; + + /** + * Sets the terminal alphabet + */ + void setNonterminalAlphabet(const std::set<alphabet::Symbol>& alphabet); + + /** + * @return start symbol + */ + const alphabet::Symbol& getInitialSymbol() const; + + /** + * Sets the initial symbol. + * @param symbol nonterminal Symbol + * @throws GrammarException when symbol isn't a nonterminal symbol + */ + void setInitialSymbol(const alphabet::Symbol& symbol); + + /** + * Creates and adds unique state to grammar. If given state name is + * already used, appends apostrophe or integer suffix + * @param name name of the state + * @throws AutomatonException if symbol could not be created + * @return created symbol + */ + static alphabet::Symbol createUniqueSymbol(const alphabet::Symbol& base, const std::set<alphabet::Symbol>& Terminals, const std::set<alphabet::Symbol>& nonterminals); + +}; + +} /* namespace grammar */ + +#endif /* TERMINAL_NONTERMINAL_ALPHABET_INITIAL_SYMBOL_H_ */ -- GitLab