Skip to content
Snippets Groups Projects
Commit f47e73a5 authored by Jan Trávníček's avatar Jan Trávníček
Browse files

CFG and EpsilonFreeCFG

parent ad369989
No related branches found
No related tags found
No related merge requests found
/*
* CFG.cpp
*
* Created on: Nov 17, 2013
* Author: Jan Travnicek
*/
#include "CFG.h"
#include "../../std/map.hpp"
#include "../GrammarException.h"
#include <algorithm>
#include "../../alphabet/Symbol.h"
namespace grammar {
CFG::CFG(const alphabet::Symbol& initialSymbol) : TerminalNonterminalAlphabetInitialSymbol(initialSymbol), generatesEpsilon(false) {
}
CFG::CFG(const std::set<alphabet::Symbol>& nonterminalAlphabet, const std::set<alphabet::Symbol>& terminalAlphabet, const alphabet::Symbol& initialSymbol) : TerminalNonterminalAlphabetInitialSymbol(initialSymbol), generatesEpsilon(false) {
setNonterminalAlphabet(nonterminalAlphabet);
setTerminalAlphabet(terminalAlphabet);
}
GrammarBase* CFG::clone() const {
return new CFG(*this);
}
GrammarBase* CFG::plunder() && {
return new CFG(std::move(*this));
}
bool CFG::removeTerminalSymbol(const alphabet::Symbol& symbol) {
for(const std::pair<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>>& rule : rules) {
if(rule.first == symbol)
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 CFG::removeNonterminalSymbol(const alphabet::Symbol& symbol) {
for(const std::pair<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>>& rule : rules) {
if(rule.first == symbol)
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 CFG::addRule(const alphabet::Symbol& leftHandSide, const std::vector<alphabet::Symbol>& rightHandSide) {
if(!nonterminalAlphabet.count(leftHandSide))
throw GrammarException("Rule must rewrite 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<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>> CFG::getRules() const {
return rules;
}
bool CFG::removeRule(const alphabet::Symbol& leftHandSide, const std::vector<alphabet::Symbol>& rightHandSide) {
return rules[leftHandSide].erase(rightHandSide);
}
bool CFG::operator==(const GrammarBase& other) const {
return other == *this;
}
bool CFG::operator==(const CFG& other) const {
return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules;
}
void CFG::operator>>(std::ostream& out) const {
out << "(CFG"
<< "nonterminalAlphabet = " << nonterminalAlphabet
<< "terminalAlphabet = " << terminalAlphabet
<< "initialSymbol = " << initialSymbol
<< "rules = " << rules
<< ")";
}
} /* namespace grammar */
/*
* CFG.h
*
* Created on: Nov 17, 2013
* Author: Jan Travnicek
*/
#ifndef CFG_H_
#define CFG_H_
#include "../GrammarBase.h"
#include <map>
#include "../common/TerminalNonterminalAlphabetInitialSymbol.h"
namespace grammar {
/**
* Context free grammar. Type 2 in Chomsky hierarchy. Produces context free language.
*/
class CFG : public std::element<CFG, GrammarBase>, public TerminalNonterminalAlphabetInitialSymbol {
std::map<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>> rules;
bool generatesEpsilon;
public:
CFG(const alphabet::Symbol& initialSymbol);
CFG(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 alphabet::Symbol& leftHandSide, const std::vector<alphabet::Symbol>& rightHandSide);
const std::map<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>> getRules() const;
bool removeRule(const 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 CFG& other) const;
virtual void operator>>(std::ostream& os) const;
};
} /* namespace grammar */
#endif /* CFG_H_ */
/*
* EpsilonFreeCFG.cpp
*
* Created on: Nov 17, 2013
* Author: Jan Travnicek
*/
#include "EpsilonFreeCFG.h"
#include "../../std/map.hpp"
#include "../GrammarException.h"
#include <algorithm>
#include "../../alphabet/Symbol.h"
namespace grammar {
EpsilonFreeCFG::EpsilonFreeCFG(const alphabet::Symbol& initialSymbol) : TerminalNonterminalAlphabetInitialSymbol(initialSymbol), generatesEpsilon(false) {
}
EpsilonFreeCFG::EpsilonFreeCFG(const std::set<alphabet::Symbol>& nonterminalAlphabet, const std::set<alphabet::Symbol>& terminalAlphabet, const alphabet::Symbol& initialSymbol) : TerminalNonterminalAlphabetInitialSymbol(initialSymbol), generatesEpsilon(false) {
setNonterminalAlphabet(nonterminalAlphabet);
setTerminalAlphabet(terminalAlphabet);
}
GrammarBase* EpsilonFreeCFG::clone() const {
return new EpsilonFreeCFG(*this);
}
GrammarBase* EpsilonFreeCFG::plunder() && {
return new EpsilonFreeCFG(std::move(*this));
}
bool EpsilonFreeCFG::removeTerminalSymbol(const alphabet::Symbol& symbol) {
for(const std::pair<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>>& rule : rules) {
if(rule.first == symbol)
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 EpsilonFreeCFG::removeNonterminalSymbol(const alphabet::Symbol& symbol) {
for(const std::pair<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>>& rule : rules) {
if(rule.first == symbol)
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 EpsilonFreeCFG::addRule(const alphabet::Symbol& leftHandSide, const std::vector<alphabet::Symbol>& rightHandSide) {
int rSize = rightHandSide.size();
if(leftHandSide == initialSymbol && rSize == 0) {
for(const auto& rule : rules) {
for(const auto& ruleRHS : rule.second) {
if(any_of(ruleRHS.begin(), ruleRHS.end(), [&](const alphabet::Symbol& symbol) { return initialSymbol == symbol; })) {
throw GrammarException("Initial symbol " + (std::string) initialSymbol + "used on right hand side of already existing rule");
}
}
}
generatesEpsilon = true;
return rules[leftHandSide].insert(rightHandSide).second;
} else {
if(!nonterminalAlphabet.count(leftHandSide))
throw GrammarException("Rule must rewrite 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");
if(generatesEpsilon && symbol == initialSymbol)
throw GrammarException("Initial symbol is already allowed to be rewritten to epsilon");
}
return rules[leftHandSide].insert(rightHandSide).second;
}
}
const std::map<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>> EpsilonFreeCFG::getRules() const {
return rules;
}
bool EpsilonFreeCFG::removeRule(const alphabet::Symbol& leftHandSide, const std::vector<alphabet::Symbol>& rightHandSide) {
int rSize = rightHandSide.size();
if(leftHandSide == initialSymbol && rSize == 0) {
generatesEpsilon = false;
}
return rules[leftHandSide].erase(rightHandSide);
}
bool EpsilonFreeCFG::operator==(const GrammarBase& other) const {
return other == *this;
}
bool EpsilonFreeCFG::operator==(const EpsilonFreeCFG& other) const {
return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules;
}
void EpsilonFreeCFG::operator>>(std::ostream& out) const {
out << "(EpsilonFreeCFG"
<< "nonterminalAlphabet = " << nonterminalAlphabet
<< "terminalAlphabet = " << terminalAlphabet
<< "initialSymbol = " << initialSymbol
<< "rules = " << rules
<< ")";
}
} /* namespace grammar */
/*
* EpsilonFreeCFG.h
*
* Created on: Nov 17, 2013
* Author: Jan Travnicek
*/
#ifndef EPSILON_FREE_CFG_H_
#define EPSILON_FREE_CFG_H_
#include "../GrammarBase.h"
#include <map>
#include "../common/TerminalNonterminalAlphabetInitialSymbol.h"
namespace grammar {
/**
* Epsilon free context free grammar. Type 2 in Chomsky hierarchy. Produces context free languages.
*/
class EpsilonFreeCFG : public std::element<EpsilonFreeCFG, GrammarBase>, public TerminalNonterminalAlphabetInitialSymbol {
std::map<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>> rules;
bool generatesEpsilon;
public:
EpsilonFreeCFG(const alphabet::Symbol& initialSymbol);
EpsilonFreeCFG(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 alphabet::Symbol& leftHandSide, const std::vector<alphabet::Symbol>& rightHandSide);
const std::map<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>> getRules() const;
bool removeRule(const 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 EpsilonFreeCFG& other) const;
virtual void operator>>(std::ostream& os) const;
};
} /* namespace grammar */
#endif /* EPSILON_FREE_CFG_H_ */
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
namespace grammar { namespace grammar {
   
/** /**
* UnrestrictedGrammar grammar. Type 0 in Chomsky hierarchy. Produces recursively enumerable language. * Context sensitive grammar. Type 1 in Chomsky hierarchy. Produces context sensitive language.
*/ */
class CSG : public std::element<CSG, GrammarBase>, public TerminalNonterminalAlphabetInitialSymbol { class CSG : public std::element<CSG, GrammarBase>, public TerminalNonterminalAlphabetInitialSymbol {
std::map<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>> rules; std::map<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>> rules;
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
namespace grammar { namespace grammar {
   
/** /**
* Unrestricted grammar. Type 0 in Chomsky hierarchy. Produces recursively enumerable language. * Non contracting grammar. Type 1 in Chomsky hierarchy. Produces context sensitive language.
*/ */
class NonContractingGrammar : public std::element<NonContractingGrammar, GrammarBase>, public TerminalNonterminalAlphabetInitialSymbol { class NonContractingGrammar : public std::element<NonContractingGrammar, GrammarBase>, public TerminalNonterminalAlphabetInitialSymbol {
std::map<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>> rules; std::map<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>> rules;
......
...@@ -17,8 +17,8 @@ class LeftRG; ...@@ -17,8 +17,8 @@ class LeftRG;
class RightLG; class RightLG;
class RightRG; class RightRG;
class LG; class LG;
class CFG; #include "ContextFree/CFG.h"
class EpsilonFreeCFG; #include "ContextFree/EpsilonFreeCFG.h"
class CNF; class CNF;
class GNF; class GNF;
#include "ContextSensitive/CSG.h" #include "ContextSensitive/CSG.h"
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
namespace grammar { namespace grammar {
   
/** /**
* UnrestrictedGrammar grammar. Type 0 in Chomsky hierarchy. Produces recursively enumerable language. * Context preserving unrestricted grammar. Type 0 in Chomsky hierarchy. Produces recursively enumerable language.
*/ */
class ContextPreservingUnrestrictedGrammar : public std::element<ContextPreservingUnrestrictedGrammar, GrammarBase>, public TerminalNonterminalAlphabetInitialSymbol { class ContextPreservingUnrestrictedGrammar : public std::element<ContextPreservingUnrestrictedGrammar, GrammarBase>, public TerminalNonterminalAlphabetInitialSymbol {
std::map<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>> rules; std::map<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>> rules;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment