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

Epsilon free CFG

parent 14658dd0
No related branches found
No related tags found
No related merge requests found
......@@ -64,17 +64,8 @@ bool EpsilonFreeCFG::removeNonterminalSymbol(const alphabet::Symbol& 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;
if(rSize == 0) {
throw GrammarException("Epsilon rule is not allowed");
} else {
if(!nonterminalAlphabet.count(leftHandSide))
throw GrammarException("Rule must rewrite nonterminal symbol");
......@@ -82,8 +73,6 @@ bool EpsilonFreeCFG::addRule(const alphabet::Symbol& leftHandSide, const std::ve
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;
......@@ -95,20 +84,23 @@ const std::map<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>> Epsilo
}
 
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);
}
 
void EpsilonFreeCFG::setGeneratesEpsilon(bool genEps) {
generatesEpsilon = genEps;
}
bool EpsilonFreeCFG::getGeneratesEpsilon() const {
return generatesEpsilon;
}
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;
return this->nonterminalAlphabet == other.nonterminalAlphabet && this->terminalAlphabet == other.terminalAlphabet && this->initialSymbol == other.initialSymbol && this->rules == other.rules && this->generatesEpsilon == other.generatesEpsilon;
}
 
void EpsilonFreeCFG::operator>>(std::ostream& out) const {
......@@ -117,6 +109,7 @@ void EpsilonFreeCFG::operator>>(std::ostream& out) const {
<< "terminalAlphabet = " << terminalAlphabet
<< "initialSymbol = " << initialSymbol
<< "rules = " << rules
<< "generatesEpsilon = " << generatesEpsilon
<< ")";
}
 
......
......@@ -40,6 +40,9 @@ public:
 
bool removeNonterminalSymbol(const alphabet::Symbol& symbol);
 
void setGeneratesEpsilon(bool genEps);
bool getGeneratesEpsilon() const;
virtual bool operator==(const GrammarBase& other) const;
 
virtual bool operator==(const EpsilonFreeCFG& other) const;
......
......@@ -211,6 +211,9 @@ EpsilonFreeCFG GrammarFromXMLParser::parseEpsilonFreeCFG(std::list<sax::Token>&
 
parseRules(input, grammar);
 
bool generatesEpsilon = parseGeneratesEpsilon(input);
grammar.setGeneratesEpsilon(generatesEpsilon);
popToken(input, sax::Token::TokenType::END_ELEMENT, "EpsilonFreeCFG");
return grammar;
}
......
......@@ -126,6 +126,7 @@ std::list<sax::Token> GrammarToXMLComposer::compose(const EpsilonFreeCFG& gramma
composeTerminalAlphabet(out, grammar.getTerminalAlphabet());
composeInitialSymbol(out, grammar.getInitialSymbol());
composeRules(out, grammar);
composeGeneratesEpsilon(out, grammar.getGeneratesEpsilon());
 
out.push_back(sax::Token("EpsilonFreeCFG", sax::Token::TokenType::END_ELEMENT));
return out;
......
......@@ -170,6 +170,36 @@ void GrammarTest::testContextFreeParser() {
grammar::GrammarFromXMLParser parser;
grammar::LG grammar2 = parser.parseLG(tokens2);
 
CPPUNIT_ASSERT( grammar == grammar2 );
}
}
{
grammar::EpsilonFreeCFG grammar(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::IntegerLabel(1)))));
grammar.addNonterminalSymbol(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::IntegerLabel(1)))));
grammar.addNonterminalSymbol(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::IntegerLabel(2)))));
grammar.addNonterminalSymbol(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::IntegerLabel(3)))));
grammar.addTerminalSymbol(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::StringLabel("a")))));
grammar.addTerminalSymbol(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::StringLabel("b")))));
grammar.setGeneratesEpsilon(true);
grammar.addRule(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::IntegerLabel(1)))), std::vector<alphabet::Symbol> {alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::StringLabel("a")))), alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::IntegerLabel(2))))});
grammar.addRule(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::IntegerLabel(2)))), std::vector<alphabet::Symbol> {alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::StringLabel("b")))), alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::IntegerLabel(3))))});
grammar.addRule(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::IntegerLabel(1)))), std::vector<alphabet::Symbol> {alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::IntegerLabel(3))))});
grammar.addRule(alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::IntegerLabel(1)))), std::vector<alphabet::Symbol> {alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::StringLabel("a")))), alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::StringLabel("a")))), alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::StringLabel("a")))), alphabet::Symbol(alphabet::LabeledSymbol(label::Label(label::IntegerLabel(2))))});
CPPUNIT_ASSERT( grammar == grammar );
{
grammar::GrammarToXMLComposer composer;
std::list<sax::Token> tokens = composer.compose(grammar);
std::string tmp;
sax::SaxComposeInterface::printMemory(tmp, tokens);
std::list<sax::Token> tokens2;
sax::SaxParseInterface::parseMemory(tmp, tokens2);
grammar::GrammarFromXMLParser parser;
grammar::EpsilonFreeCFG grammar2 = parser.parseEpsilonFreeCFG(tokens2);
CPPUNIT_ASSERT( grammar == grammar2 );
}
}
......
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