diff --git a/alib/src/grammar/Grammar.cpp b/alib/src/grammar/Grammar.cpp index 4b02480f473ead79d9bb854342966978f14e18fa..f76c90ce1cb8ed3677393e584dda4cd0ff8607d9 100644 --- a/alib/src/grammar/Grammar.cpp +++ b/alib/src/grammar/Grammar.cpp @@ -14,24 +14,6 @@ namespace grammar { using namespace std; using namespace alphabet; -bool Grammar::usesExistingSymbols(const Rule& rule) const{ - const list<Symbol>& leftSide = rule.getLeftSide(); - for(list<Symbol>::const_iterator left = leftSide.begin(); left != leftSide.end(); left ++) { - if(terminalSymbols.find(*left) == terminalSymbols.end() && nonTerminalSymbols.find(*left) == nonTerminalSymbols.end()) { - return false; - } - } - - const list<Symbol>& rightSide = rule.getRightSide(); - for(list<Symbol>::const_iterator right = rightSide.begin(); right != rightSide.end(); right++) { - if(terminalSymbols.find(*right) == terminalSymbols.end() && nonTerminalSymbols.find(*right) == nonTerminalSymbols.end()) { - return false; - } - } - - return true; -} - Grammar::~Grammar() { } @@ -109,6 +91,16 @@ void Grammar::setStartSymbol(const Symbol& symbol) { startSymbol = symbol; } +void Grammar::addRule(const Rule& rule) { + if (!isValidRule(rule)) { + throw GrammarException("Rule is not valid for this grammar."); + } + + if (!rules.insert(rule).second) { + throw GrammarException("Rule already exists."); + } +} + void Grammar::toXML(ostream& out) const { GrammarPrinter::toXML(*this, out); } diff --git a/alib/src/grammar/Grammar.h b/alib/src/grammar/Grammar.h index a16c91bce0243bfc78c15ed7c37e52c2e55a810f..33fbe2e64f8fe4c4d67a6c4d6c1996b51edc1f00 100644 --- a/alib/src/grammar/Grammar.h +++ b/alib/src/grammar/Grammar.h @@ -26,7 +26,7 @@ protected: set<Rule> rules; Symbol startSymbol; - bool usesExistingSymbols(const Rule& rule) const; + virtual bool isValidRule(const Rule& rule) const = 0; public: virtual ~Grammar(); @@ -38,14 +38,14 @@ public: void removeNonTerminalSymbol(const Symbol& symbol); const set<Symbol>& getNonTerminalSymbols() const; - virtual void addRule(const Rule& rule) = 0; + void addRule(const Rule& rule); void removeRule(const Rule& rule); const set<Rule>& getRules() const; const Symbol& getStartSymbol() const; void setStartSymbol(const Symbol& symbol); - virtual void toXML(ostream& out) const; + void toXML(ostream& out) const; }; } /* namespace grammar */ diff --git a/alib/src/grammar/RightRegularGrammar.cpp b/alib/src/grammar/RightRegularGrammar.cpp index 2f7b4c5c8950bef253ebd489651339f46def0cc4..fb552d648cd9baa0873fb0354ec6a040bed0eeae 100644 --- a/alib/src/grammar/RightRegularGrammar.cpp +++ b/alib/src/grammar/RightRegularGrammar.cpp @@ -11,18 +11,8 @@ namespace grammar { -void RightRegularGrammar::addRule(const Rule& rule) { - if (!isValidRule(rule)) { - throw GrammarException("Not a right regular grammar rule."); - } - - if (!rules.insert(rule).second) { - throw GrammarException("Rule already exists."); - } -} - bool RightRegularGrammar::isValidRule(const Rule& rule) const { - return usesExistingSymbols(rule) && checkLeftSide(rule.getLeftSide()) && checkRightSide(rule.getRightSide()); + return checkLeftSide(rule.getLeftSide()) && checkRightSide(rule.getRightSide()); } bool RightRegularGrammar::checkLeftSide(const list<Symbol>& leftSide) const { @@ -40,9 +30,7 @@ bool RightRegularGrammar::checkLeftSide(const list<Symbol>& leftSide) const { bool RightRegularGrammar::checkRightSide(const list<Symbol>& rightSide) const { if (rightSide.size() == 0) { return true; - } - - if (rightSide.size() == 1) { + } else if (rightSide.size() == 1) { const Symbol& symbol = rightSide.front(); //check epsilon @@ -50,27 +38,26 @@ bool RightRegularGrammar::checkRightSide(const list<Symbol>& rightSide) const { return true; } - if (terminalSymbols.find(symbol) == terminalSymbols.end() - && nonTerminalSymbols.find(symbol) == nonTerminalSymbols.end()) { - return false; + //check that symbol exists + return ((terminalSymbols.find(symbol) != terminalSymbols.end()) + || (nonTerminalSymbols.find(symbol) != nonTerminalSymbols.end())); + + } else { + //check if all symbols except the last one are terminal symbols + for (list<Symbol>::const_iterator symbol = rightSide.begin(); symbol != --rightSide.end(); symbol++) { + if (terminalSymbols.find(*symbol) == terminalSymbols.end()) { + return false; + } } - return true; - } - //check if all symbols except the last are terminal symbols - for (list<Symbol>::const_iterator symbol = rightSide.begin(); symbol != --rightSide.end(); symbol++) { - if (terminalSymbols.find(*symbol) == terminalSymbols.end()) { + //check if last symbol is nonterminal + const Symbol& lastSymbol = *(--rightSide.end()); + if (nonTerminalSymbols.find(lastSymbol) == nonTerminalSymbols.end()) { return false; } - } - //check if last symbol is nonterminal - const Symbol& lastSymbol = *(--rightSide.end()); - if (nonTerminalSymbols.find(lastSymbol) == nonTerminalSymbols.end()) { - return false; + return true; } - - return true; } } diff --git a/alib/src/grammar/RightRegularGrammar.h b/alib/src/grammar/RightRegularGrammar.h index 46a8e52eb433d1f9bac6e292ba2a21b6787581b5..deffa166ec6564083a27c47d717eeeb6c943305f 100644 --- a/alib/src/grammar/RightRegularGrammar.h +++ b/alib/src/grammar/RightRegularGrammar.h @@ -12,14 +12,12 @@ namespace grammar { -class RightRegularGrammar: public grammar::Grammar { +class RightRegularGrammar: public Grammar { private: bool checkLeftSide(const list<Symbol>& leftSide) const; bool checkRightSide(const list<Symbol>& rightSide) const; public: bool isValidRule(const Rule& rule) const; - void addRule(const Rule& rule); - }; } /* namespace grammar */ diff --git a/alib/src/grammar/UnknownGrammar.cpp b/alib/src/grammar/UnknownGrammar.cpp index 19b02d82f84531a1aef51aef2b885fd701bb663f..ae89e343dc30143c1b638495cb01aedccca6a489 100644 --- a/alib/src/grammar/UnknownGrammar.cpp +++ b/alib/src/grammar/UnknownGrammar.cpp @@ -10,14 +10,23 @@ namespace grammar { -void UnknownGrammar::addRule(const Rule& rule) { - usesExistingSymbols(rule); +bool UnknownGrammar::isValidRule(const Rule& rule) const { + for (auto const & symbol : rule.getLeftSide()) { + if (terminalSymbols.find(symbol) == terminalSymbols.end() + && nonTerminalSymbols.find(symbol) == nonTerminalSymbols.end()) { + return false; + } + } - if(!rules.insert(rule).second) { - throw GrammarException("Rule already exists."); + for (auto const & right : rule.getRightSide()) { + if (terminalSymbols.find(right) == terminalSymbols.end() + && nonTerminalSymbols.find(right) == nonTerminalSymbols.end()) { + return false; + } } + + return true; } } /* namespace grammar */ - diff --git a/alib/src/grammar/UnknownGrammar.h b/alib/src/grammar/UnknownGrammar.h index a3f182958957cfef11a3804ae9e3bbee5cf5095a..8f03a98ff7a5d7cdd77474a796bc5affd0c3b4be 100644 --- a/alib/src/grammar/UnknownGrammar.h +++ b/alib/src/grammar/UnknownGrammar.h @@ -13,8 +13,8 @@ namespace grammar { class UnknownGrammar: public grammar::Grammar { -public: - void addRule(const Rule& rule); +protected: + bool isValidRule(const Rule& rule) const; }; } /* namespace grammar */ diff --git a/examples/grammar/regular.xml b/examples/grammar/rightRegular.xml similarity index 68% rename from examples/grammar/regular.xml rename to examples/grammar/rightRegular.xml index 18e5614bb0b362bfc0fc52998f67ea34cb19f715..1e3f164c4127a51cfa61f8fe734d3c829893d03c 100644 --- a/examples/grammar/regular.xml +++ b/examples/grammar/rightRegular.xml @@ -6,6 +6,7 @@ <terminalSymbols> <symbol>a</symbol> + <symbol>b</symbol> </terminalSymbols> <rules> @@ -27,6 +28,17 @@ <symbol>a</symbol> </rightSide> </rule> + <rule> + <leftSide> + <symbol>A</symbol> + </leftSide> + <rightSide> + <symbol>b</symbol> + <symbol>b</symbol> + <symbol>b</symbol> + <symbol>A</symbol> + </rightSide> + </rule> </rules> <startSymbol>S</startSymbol>