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

Noncontracting grammar

parent ed205ee1
No related branches found
No related tags found
No related merge requests found
...@@ -102,9 +102,8 @@ bool CSG::addRule(const std::vector<alphabet::Symbol>& leftHandSide, const std:: ...@@ -102,9 +102,8 @@ bool CSG::addRule(const std::vector<alphabet::Symbol>& leftHandSide, const std::
for(const alphabet::Symbol& symbol : rightHandSide) { for(const alphabet::Symbol& symbol : rightHandSide) {
if(terminalAlphabet.find(symbol) == terminalAlphabet.end() && nonterminalAlphabet.find(symbol) == nonterminalAlphabet.end()) 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"); throw GrammarException("Symbol \"" + (std::string) symbol.getSymbol() + "\" is not neither terminal nor nonterminal symbol");
if(generatesEpsilon && symbol == initialSymbol) { if(generatesEpsilon && symbol == initialSymbol)
throw GrammarException("Initial symbol is already allowed to be rewritten to epsilon"); throw GrammarException("Initial symbol is already allowed to be rewritten to epsilon");
}
} }
   
return rules[leftHandSide].insert(rightHandSide).second; return rules[leftHandSide].insert(rightHandSide).second;
......
/*
* NonContractingGrammar.cpp
*
* Created on: Nov 17, 2013
* Author: Jan Travnicek
*/
#include "NonContractingGrammar.h"
#include "../../std/map.hpp"
#include "../GrammarException.h"
#include <algorithm>
#include "../../alphabet/Symbol.h"
namespace grammar {
NonContractingGrammar::NonContractingGrammar(const alphabet::Symbol& initialSymbol) : TerminalNonterminalAlphabetInitialSymbol(initialSymbol), generatesEpsilon(false) {
}
NonContractingGrammar::NonContractingGrammar(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* NonContractingGrammar::clone() const {
return new NonContractingGrammar(*this);
}
GrammarBase* NonContractingGrammar::plunder() && {
return new NonContractingGrammar(std::move(*this));
}
bool NonContractingGrammar::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 NonContractingGrammar::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 NonContractingGrammar::addRule(const std::vector<alphabet::Symbol>& leftHandSide, const std::vector<alphabet::Symbol>& rightHandSide) {
int lSize = leftHandSide.size();
int rSize = rightHandSide.size();
if(lSize == 1 && leftHandSide[0] == 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(lSize > rSize)
throw GrammarException("Invalid size of right hand side of a rule");
if(std::all_of(leftHandSide.begin(), leftHandSide.end(), [&](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");
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<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>> NonContractingGrammar::getRules() const {
return rules;
}
bool NonContractingGrammar::removeRule(const std::vector<alphabet::Symbol>& leftHandSide, const std::vector<alphabet::Symbol>& rightHandSide) {
int lSize = leftHandSide.size();
int rSize = rightHandSide.size();
if(lSize == 1 && leftHandSide[0] == initialSymbol && rSize == 0) {
generatesEpsilon = false;
}
return rules[leftHandSide].erase(rightHandSide);
}
bool NonContractingGrammar::operator==(const GrammarBase& other) const {
return other == *this;
}
bool NonContractingGrammar::operator==(const NonContractingGrammar& other) const {
return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules;
}
void NonContractingGrammar::operator>>(std::ostream& out) const {
out << "(NonContractingGrammar"
<< "nonterminalAlphabet = " << nonterminalAlphabet
<< "terminalAlphabet = " << terminalAlphabet
<< "initialSymbol = " << initialSymbol
<< "rules = " << rules
<< ")";
}
} /* namespace grammar */
/*
* NonContractingGrammar.h
*
* Created on: Nov 17, 2013
* Author: Jan Travnicek
*/
#ifndef NON_CONTRACTING_GRAMMAR_H_
#define NON_CONTRACTING_GRAMMAR_H_
#include "../GrammarBase.h"
#include <map>
#include "../common/TerminalNonterminalAlphabetInitialSymbol.h"
namespace grammar {
/**
* Unrestricted grammar. Type 0 in Chomsky hierarchy. Produces recursively enumerable language.
*/
class NonContractingGrammar : public std::element<NonContractingGrammar, GrammarBase>, public TerminalNonterminalAlphabetInitialSymbol {
std::map<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>> rules;
bool generatesEpsilon;
public:
NonContractingGrammar(const alphabet::Symbol& initialSymbol);
NonContractingGrammar(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 NonContractingGrammar& other) const;
virtual void operator>>(std::ostream& os) const;
};
} /* namespace grammar */
#endif /* NON_CONTRACTING_GRAMMAR_H_ */
...@@ -21,8 +21,8 @@ class CFG; ...@@ -21,8 +21,8 @@ class CFG;
class EpsilonFreeCFG; class EpsilonFreeCFG;
class CNF; class CNF;
class GNF; class GNF;
class CSG; #include "ContextSensitive/CSG.h"
class NonContractingGrammar; #include "ContextSensitive/NonContractingGrammar.h"
#include "Unrestricted/ContextPreservingUnrestrictedGrammar.h" #include "Unrestricted/ContextPreservingUnrestrictedGrammar.h"
#include "Unrestricted/UnrestrictedGrammar.h" #include "Unrestricted/UnrestrictedGrammar.h"
#include "../sax/Token.h" #include "../sax/Token.h"
......
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