diff --git a/alib2data/src/grammar/GrammarFromStringLexer.cpp b/alib2data/src/grammar/GrammarFromStringLexer.cpp index 7dcc4a9bfb3f621d28542da374933a61061e1a00..79a2a2e1bda7c93dec31d109da831d1379edda19 100644 --- a/alib2data/src/grammar/GrammarFromStringLexer.cpp +++ b/alib2data/src/grammar/GrammarFromStringLexer.cpp @@ -68,11 +68,66 @@ L0: token.value = "RIGHT_RG"; token.raw = "RIGHT_RG"; return token; + } else if(in.clear(), in >> "LEFT_RG") { + token.type = TokenType::LEFT_RG; + token.value = "LEFT_RG"; + token.raw = "LEFT_RG"; + return token; + } else if(in.clear(), in >> "RIGHT_LG") { + token.type = TokenType::RIGHT_LG; + token.value = "RIGHT_LG"; + token.raw = "RIGHT_LG"; + return token; + } else if(in.clear(), in >> "LEFT_LG") { + token.type = TokenType::LEFT_LG; + token.value = "LEFT_LG"; + token.raw = "LEFT_LG"; + return token; + } else if(in.clear(), in >> "LG") { + token.type = TokenType::LG; + token.value = "LG"; + token.raw = "LG"; + return token; + } else if(in.clear(), in >> "CFG") { + token.type = TokenType::CFG; + token.value = "CFG"; + token.raw = "CFG"; + return token; + } else if(in.clear(), in >> "EPSILON_FREE_CFG") { + token.type = TokenType::EPSILON_FREE_CFG; + token.value = "EPSILON_FREE_CFG"; + token.raw = "EPSILON_FREE_CFG"; + return token; + } else if(in.clear(), in >> "GNF") { + token.type = TokenType::GNF; + token.value = "GNF"; + token.raw = "GNF"; + return token; } else if(in.clear(), in >> "CNF") { token.type = TokenType::CNF; token.value = "CNF"; token.raw = "CNF"; return token; + } else if(in.clear(), in >> "CSG") { + token.type = TokenType::CSG; + token.value = "CSG"; + token.raw = "CSG"; + return token; + } else if(in.clear(), in >> "NON_CONTRACTING_GRAMMAR") { + token.type = TokenType::NON_CONTRACTING_GRAMMAR; + token.value = "NON_CONTRACTING_GRAMMAR"; + token.raw = "NON_CONTRACTING_GRAMMAR"; + return token; + } else if(in.clear(), in >> "CONTEXT_PRESERVING_UNRESTRICTED_GRAMMAR") { + token.type = TokenType::CONTEXT_PRESERVING_UNRESTRICTED_GRAMMAR; + token.value = "CONTEXT_PRESERVING_UNRESTRICTED_GRAMMAR"; + token.raw = "CONTEXT_PRESERVING_UNRESTRICTED_GRAMMAR"; + return token; + } else if(in.clear(), in >> "UNRESTRICTED_GRAMMAR") { + token.type = TokenType::UNRESTRICTED_GRAMMAR; + token.value = "UNRESTRICTED_GRAMMAR"; + token.raw = "UNRESTRICTED_GRAMMAR"; + return token; } else { in.putback(character); putback(in, std::move(token)); diff --git a/alib2data/src/grammar/GrammarFromStringLexer.h b/alib2data/src/grammar/GrammarFromStringLexer.h index 85020bc2b3b263dd5234177ce5d61d5452758786..6043b3353c52bfe7d3294bfd56847ca02f658696 100644 --- a/alib2data/src/grammar/GrammarFromStringLexer.h +++ b/alib2data/src/grammar/GrammarFromStringLexer.h @@ -25,7 +25,18 @@ public: EPSILON, MAPS_TO, RIGHT_RG, + LEFT_RG, + RIGHT_LG, + LEFT_LG, + LG, + CFG, + EPSILON_FREE_CFG, + GNF, CNF, + CSG, + NON_CONTRACTING_GRAMMAR, + CONTEXT_PRESERVING_UNRESTRICTED_GRAMMAR, + UNRESTRICTED_GRAMMAR, TEOF, ERROR, }; diff --git a/alib2data/src/grammar/GrammarFromStringParser.cpp b/alib2data/src/grammar/GrammarFromStringParser.cpp index 178a91e3c7213b0ed21abb2c593bdc1ac3c85cc3..fd67483e42b62c97d72c3520f1a1245c3f0236dd 100644 --- a/alib2data/src/grammar/GrammarFromStringParser.cpp +++ b/alib2data/src/grammar/GrammarFromStringParser.cpp @@ -10,26 +10,84 @@ #include "../exception/AlibException.h" #include "Regular/RightRG.h" +#include "Regular/LeftRG.h" +#include "Regular/RightLG.h" +#include "Regular/LeftLG.h" + +#include "ContextFree/LG.h" +#include "ContextFree/CFG.h" +#include "ContextFree/EpsilonFreeCFG.h" +#include "ContextFree/GNF.h" #include "ContextFree/CNF.h" +#include "ContextSensitive/CSG.h" +#include "ContextSensitive/NonContractingGrammar.h" + +#include "Unrestricted/ContextPreservingUnrestrictedGrammar.h" +#include "Unrestricted/UnrestrictedGrammar.h" + #include "../StringApi.hpp" namespace grammar { Grammar GrammarFromStringParser::parseGrammar(std::istream& input) const { - return parseGrammar(input, std::set<FEATURES>({FEATURES::CNF, FEATURES::RIGHT_RG})); + return parseGrammar(input, std::set<FEATURES>({FEATURES::LEFT_LG, FEATURES::LEFT_RG, FEATURES::RIGHT_LG, FEATURES::RIGHT_RG, FEATURES::LG, FEATURES::CFG, FEATURES::EPSILON_FREE_CFG, FEATURES::CNF, FEATURES::GNF, FEATURES::CSG, FEATURES::NON_CONTRACTING_GRAMMAR, FEATURES::CONTEXT_PRESERVING_UNRESTRICTED_GRAMMAR, FEATURES::UNRESTRICTED_GRAMMAR})); } Grammar GrammarFromStringParser::parseGrammar(std::istream& input, const std::set<FEATURES>& features) const { GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); - if(token.type == GrammarFromStringLexer::TokenType::CNF) { - if(!features.count(FEATURES::CNF)) throw exception::AlibException("Disabled formalism CNF"); + if(token.type == GrammarFromStringLexer::TokenType::LEFT_RG) { + if(!features.count(FEATURES::LEFT_RG)) throw exception::AlibException("Disabled Formalism LeftRG"); m_GrammarLexer.putback(input, token); - return Grammar(parseCNF(input)); + return Grammar(parseLeftRG(input)); } else if(token.type == GrammarFromStringLexer::TokenType::RIGHT_RG) { if(!features.count(FEATURES::RIGHT_RG)) throw exception::AlibException("Disabled Formalism RightRG"); m_GrammarLexer.putback(input, token); return Grammar(parseRightRG(input)); + } else if(token.type == GrammarFromStringLexer::TokenType::LEFT_LG) { + if(!features.count(FEATURES::LEFT_LG)) throw exception::AlibException("Disabled Formalism LeftLG"); + m_GrammarLexer.putback(input, token); + return Grammar(parseLeftLG(input)); + } else if(token.type == GrammarFromStringLexer::TokenType::RIGHT_LG) { + if(!features.count(FEATURES::RIGHT_LG)) throw exception::AlibException("Disabled Formalism RightLG"); + m_GrammarLexer.putback(input, token); + return Grammar(parseRightLG(input)); + } else if(token.type == GrammarFromStringLexer::TokenType::LG) { + if(!features.count(FEATURES::LG)) throw exception::AlibException("Disabled formalism LG"); + m_GrammarLexer.putback(input, token); + return Grammar(parseLG(input)); + } else if(token.type == GrammarFromStringLexer::TokenType::CFG) { + if(!features.count(FEATURES::CFG)) throw exception::AlibException("Disabled formalism CFG"); + m_GrammarLexer.putback(input, token); + return Grammar(parseCFG(input)); + } else if(token.type == GrammarFromStringLexer::TokenType::EPSILON_FREE_CFG) { + if(!features.count(FEATURES::EPSILON_FREE_CFG)) throw exception::AlibException("Disabled formalism EpsilonFreeCFG"); + m_GrammarLexer.putback(input, token); + return Grammar(parseEpsilonFreeCFG(input)); + } else if(token.type == GrammarFromStringLexer::TokenType::GNF) { + if(!features.count(FEATURES::GNF)) throw exception::AlibException("Disabled formalism GNF"); + m_GrammarLexer.putback(input, token); + return Grammar(parseGNF(input)); + } else if(token.type == GrammarFromStringLexer::TokenType::CNF) { + if(!features.count(FEATURES::CNF)) throw exception::AlibException("Disabled formalism CNF"); + m_GrammarLexer.putback(input, token); + return Grammar(parseCNF(input)); + } else if(token.type == GrammarFromStringLexer::TokenType::NON_CONTRACTING_GRAMMAR) { + if(!features.count(FEATURES::NON_CONTRACTING_GRAMMAR)) throw exception::AlibException("Disabled formalism NonContractingGrammar"); + m_GrammarLexer.putback(input, token); + return Grammar(parseNonContractingGrammar(input)); + } else if(token.type == GrammarFromStringLexer::TokenType::CSG) { + if(!features.count(FEATURES::CSG)) throw exception::AlibException("Disabled formalism CSG"); + m_GrammarLexer.putback(input, token); + return Grammar(parseCSG(input)); + } else if(token.type == GrammarFromStringLexer::TokenType::CONTEXT_PRESERVING_UNRESTRICTED_GRAMMAR) { + if(!features.count(FEATURES::CONTEXT_PRESERVING_UNRESTRICTED_GRAMMAR)) throw exception::AlibException("Disabled formalism ContextPreservingUnrestrictedGrammar"); + m_GrammarLexer.putback(input, token); + return Grammar(parseContextPreservingUnrestrictedGrammar(input)); + } else if(token.type == GrammarFromStringLexer::TokenType::UNRESTRICTED_GRAMMAR) { + if(!features.count(FEATURES::UNRESTRICTED_GRAMMAR)) throw exception::AlibException("Disabled formalism UnrestrictedGrammar"); + m_GrammarLexer.putback(input, token); + return Grammar(parseUnrestrictedGrammar(input)); } else { throw exception::AlibException("Formalism not recognised (token = \"" + token.value + "\")"); } @@ -123,17 +181,116 @@ std::map<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>> GrammarFromS return result; } -RightRG GrammarFromStringParser::parseRightRG(std::istream& input) const { - throw exception::AlibException("Unimplemented"); +template<class T> +T GrammarFromStringParser::parseCFLikeGrammar(std::istream& input) const { + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::TUPLE_BEGIN) { + throw exception::AlibException("Unrecognised Tuple begin token."); + } + + std::set<alphabet::Symbol> nonterminals = parseSet(input); + + token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::COMMA) { + throw exception::AlibException("Unrecognised Comma token."); + } + + std::set<alphabet::Symbol> terminals = parseSet(input); + + token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::COMMA) { + throw exception::AlibException("Unrecognised Comma token."); + } + + std::map<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>> rules = parseCFLikeRules(input); + + token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::COMMA) { + throw exception::AlibException("Unrecognised Comma token."); + } + + alphabet::Symbol initialSymbol = alib::stringApi<alphabet::Symbol>::parse(input); + + token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::TUPLE_END) { + throw exception::AlibException("Unrecognised Tuple end token."); + } + + T grammar(nonterminals, terminals, initialSymbol); + for(const auto& rule : rules) { + for(const auto& ruleRHS : rule.second) { + grammar.addRawRule(rule.first, ruleRHS); + } + } + return grammar; } -CNF GrammarFromStringParser::parseCNF(std::istream& input) const { +std::map<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>> GrammarFromStringParser::parseCSLikeRules(std::istream& input) const { + std::map<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>> result; + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); - if(token.type != GrammarFromStringLexer::TokenType::CNF) { - throw exception::AlibException("Unrecognised CNF token."); + if(token.type != GrammarFromStringLexer::TokenType::SET_BEGIN) { + throw exception::AlibException(); } token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::SET_END) { + m_GrammarLexer.putback(input, token); + while(true) { + std::vector<alphabet::Symbol> lhs; + while(true) { + lhs.push_back(alib::stringApi<alphabet::Symbol>::parse(input)); + token = m_GrammarLexer.next(input); + if(token.type == GrammarFromStringLexer::TokenType::MAPS_TO) { + break; + } + m_GrammarLexer.putback(input, token); + } + + if(token.type != GrammarFromStringLexer::TokenType::MAPS_TO) { + throw exception::AlibException(); + } + + while(true) { + std::vector<alphabet::Symbol> rhs; + + token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::COMMA && token.type != GrammarFromStringLexer::TokenType::SET_END && token.type != GrammarFromStringLexer::TokenType::SEPARATOR) while(true) { + m_GrammarLexer.putback(input, token); + + rhs.push_back(alib::stringApi<alphabet::Symbol>::parse(input)); + token = m_GrammarLexer.next(input); + if(token.type == GrammarFromStringLexer::TokenType::SEPARATOR || token.type == GrammarFromStringLexer::TokenType::COMMA || token.type == GrammarFromStringLexer::TokenType::SET_END) { + break; + } + } + result[lhs].insert(rhs); + if(token.type == GrammarFromStringLexer::TokenType::COMMA || token.type == GrammarFromStringLexer::TokenType::SET_END) { + break; + } + if(token.type != GrammarFromStringLexer::TokenType::SEPARATOR) { + throw exception::AlibException("Expected SEPARATOR, SETEND or COMMA token"); + } + } + + if(token.type == GrammarFromStringLexer::TokenType::SET_END) { + break; + } + if(token.type != GrammarFromStringLexer::TokenType::COMMA) { + throw exception::AlibException("Expected SET_END or COMMA token"); + } + } + } + + if(token.type != GrammarFromStringLexer::TokenType::SET_END) { + throw exception::AlibException("Expected SET_END token"); + } + return result; +} + +template<class T> +T GrammarFromStringParser::parseCSLikeGrammar(std::istream& input) const { + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); if(token.type != GrammarFromStringLexer::TokenType::TUPLE_BEGIN) { throw exception::AlibException("Unrecognised Tuple begin token."); } @@ -152,7 +309,139 @@ CNF GrammarFromStringParser::parseCNF(std::istream& input) const { throw exception::AlibException("Unrecognised Comma token."); } - std::map<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>> rules = parseCFLikeRules(input); + std::map<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>> rules = parseCSLikeRules(input); + + token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::COMMA) { + throw exception::AlibException("Unrecognised Comma token."); + } + + alphabet::Symbol initialSymbol = alib::stringApi<alphabet::Symbol>::parse(input); + + token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::TUPLE_END) { + throw exception::AlibException("Unrecognised Tuple end token."); + } + + T grammar(nonterminals, terminals, initialSymbol); + for(const auto& rule : rules) { + for(const auto& ruleRHS : rule.second) { + grammar.addRule(rule.first, ruleRHS); + } + } + return grammar; +} + +std::map<std::tuple<std::vector<alphabet::Symbol>, alphabet::Symbol, std::vector<alphabet::Symbol>>, std::set<std::vector<alphabet::Symbol>>> GrammarFromStringParser::parsePreservingCSLikeRules(std::istream& input) const { + std::map<std::tuple<std::vector<alphabet::Symbol>, alphabet::Symbol, std::vector<alphabet::Symbol>>, std::set<std::vector<alphabet::Symbol>>> result; + + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::SET_BEGIN) { + throw exception::AlibException(); + } + + token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::SET_END) { + m_GrammarLexer.putback(input, token); + while(true) { + std::vector<alphabet::Symbol> lContext; + token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::SEPARATOR) while(true) { + m_GrammarLexer.putback(input, token); + lContext.push_back(alib::stringApi<alphabet::Symbol>::parse(input)); + token = m_GrammarLexer.next(input); + if(token.type == GrammarFromStringLexer::TokenType::SEPARATOR) { + break; + } + } + + if(token.type != GrammarFromStringLexer::TokenType::SEPARATOR) { + throw exception::AlibException(); + } + + alphabet::Symbol lhs = alib::stringApi<alphabet::Symbol>::parse(input); + + token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::SEPARATOR) { + throw exception::AlibException(); + } + + std::vector<alphabet::Symbol> rContext; + token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::MAPS_TO) while(true) { + m_GrammarLexer.putback(input, token); + rContext.push_back(alib::stringApi<alphabet::Symbol>::parse(input)); + token = m_GrammarLexer.next(input); + if(token.type == GrammarFromStringLexer::TokenType::MAPS_TO) { + break; + } + } + + if(token.type != GrammarFromStringLexer::TokenType::MAPS_TO) { + throw exception::AlibException(); + } + + std::tuple<std::vector<alphabet::Symbol>, alphabet::Symbol, std::vector<alphabet::Symbol>> key = std::make_tuple(lContext, lhs, rContext); + + while(true) { + std::vector<alphabet::Symbol> rhs; + + token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::COMMA && token.type != GrammarFromStringLexer::TokenType::SET_END && token.type != GrammarFromStringLexer::TokenType::SEPARATOR) while(true) { + m_GrammarLexer.putback(input, token); + + rhs.push_back(alib::stringApi<alphabet::Symbol>::parse(input)); + token = m_GrammarLexer.next(input); + if(token.type == GrammarFromStringLexer::TokenType::SEPARATOR || token.type == GrammarFromStringLexer::TokenType::COMMA || token.type == GrammarFromStringLexer::TokenType::SET_END) { + break; + } + } + result[key].insert(rhs); + if(token.type == GrammarFromStringLexer::TokenType::COMMA || token.type == GrammarFromStringLexer::TokenType::SET_END) { + break; + } + if(token.type != GrammarFromStringLexer::TokenType::SEPARATOR) { + throw exception::AlibException("Expected SEPARATOR, SETEND or COMMA token"); + } + } + + if(token.type == GrammarFromStringLexer::TokenType::SET_END) { + break; + } + if(token.type != GrammarFromStringLexer::TokenType::COMMA) { + throw exception::AlibException("Expected SET_END or COMMA token"); + } + } + } + + if(token.type != GrammarFromStringLexer::TokenType::SET_END) { + throw exception::AlibException("Expected SET_END token"); + } + return result; +} + +template<class T> +T GrammarFromStringParser::parsePreservingCSLikeGrammar(std::istream& input) const { + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::TUPLE_BEGIN) { + throw exception::AlibException("Unrecognised Tuple begin token."); + } + + std::set<alphabet::Symbol> nonterminals = parseSet(input); + + token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::COMMA) { + throw exception::AlibException("Unrecognised Comma token."); + } + + std::set<alphabet::Symbol> terminals = parseSet(input); + + token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::COMMA) { + throw exception::AlibException("Unrecognised Comma token."); + } + + std::map<std::tuple<std::vector<alphabet::Symbol>, alphabet::Symbol, std::vector<alphabet::Symbol>>, std::set<std::vector<alphabet::Symbol>>> rules = parsePreservingCSLikeRules(input); token = m_GrammarLexer.next(input); if(token.type != GrammarFromStringLexer::TokenType::COMMA) { @@ -166,13 +455,130 @@ CNF GrammarFromStringParser::parseCNF(std::istream& input) const { throw exception::AlibException("Unrecognised Tuple end token."); } - CNF cnf(nonterminals, terminals, initialSymbol); + T grammar(nonterminals, terminals, initialSymbol); for(const auto& rule : rules) { for(const auto& ruleRHS : rule.second) { - cnf.addRawRule(rule.first, ruleRHS); + grammar.addRule(std::get<0>(rule.first), std::get<1>(rule.first), std::get<2>(rule.first), ruleRHS); } } - return cnf; + return grammar; +} + +RightRG GrammarFromStringParser::parseRightRG(std::istream& input) const { + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::RIGHT_RG) { + throw exception::AlibException("Unrecognised RightRG token."); + } + + return parseCFLikeGrammar<RightRG>(input); +} + +LeftRG GrammarFromStringParser::parseLeftRG(std::istream& input) const { + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::LEFT_RG) { + throw exception::AlibException("Unrecognised LeftRG token."); + } + + return parseCFLikeGrammar<LeftRG>(input); +} + +RightLG GrammarFromStringParser::parseRightLG(std::istream& input) const { + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::RIGHT_LG) { + throw exception::AlibException("Unrecognised RightLG token."); + } + + return parseCFLikeGrammar<RightLG>(input); +} + +LeftLG GrammarFromStringParser::parseLeftLG(std::istream& input) const { + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::LEFT_LG) { + throw exception::AlibException("Unrecognised LeftLG token."); + } + + return parseCFLikeGrammar<LeftLG>(input); +} + +LG GrammarFromStringParser::parseLG(std::istream& input) const { + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::LG) { + throw exception::AlibException("Unrecognised LG token."); + } + + return parseCFLikeGrammar<LG>(input); +} + +CFG GrammarFromStringParser::parseCFG(std::istream& input) const { + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::CFG) { + throw exception::AlibException("Unrecognised CFG token."); + } + + return parseCFLikeGrammar<CFG>(input); +} + +EpsilonFreeCFG GrammarFromStringParser::parseEpsilonFreeCFG(std::istream& input) const { + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::EPSILON_FREE_CFG) { + throw exception::AlibException("Unrecognised EpsilonFreeCFG token."); + } + + return parseCFLikeGrammar<EpsilonFreeCFG>(input); +} + +GNF GrammarFromStringParser::parseGNF(std::istream& input) const { + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::GNF) { + throw exception::AlibException("Unrecognised GNF token."); + } + + return parseCFLikeGrammar<GNF>(input); +} + +CNF GrammarFromStringParser::parseCNF(std::istream& input) const { + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::CNF) { + throw exception::AlibException("Unrecognised CNF token."); + } + + return parseCFLikeGrammar<CNF>(input); +} + +NonContractingGrammar GrammarFromStringParser::parseNonContractingGrammar(std::istream& input) const { + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::NON_CONTRACTING_GRAMMAR) { + throw exception::AlibException("Unrecognised NonContractingGrammar token."); + } + + return parseCSLikeGrammar<NonContractingGrammar>(input); +} + +CSG GrammarFromStringParser::parseCSG(std::istream& input) const { + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::CSG) { + throw exception::AlibException("Unrecognised CSG token."); + } + + return parsePreservingCSLikeGrammar<CSG>(input); +} + +ContextPreservingUnrestrictedGrammar GrammarFromStringParser::parseContextPreservingUnrestrictedGrammar(std::istream& input) const { + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::CONTEXT_PRESERVING_UNRESTRICTED_GRAMMAR) { + throw exception::AlibException("Unrecognised ContextPreservingUnrestrictedGrammar token."); + } + + return parsePreservingCSLikeGrammar<ContextPreservingUnrestrictedGrammar>(input); +} + +UnrestrictedGrammar GrammarFromStringParser::parseUnrestrictedGrammar(std::istream& input) const { + GrammarFromStringLexer::Token token = m_GrammarLexer.next(input); + if(token.type != GrammarFromStringLexer::TokenType::UNRESTRICTED_GRAMMAR) { + throw exception::AlibException("Unrecognised UnrestrictedGrammar token."); + } + + return parseCSLikeGrammar<UnrestrictedGrammar>(input); } } /* namespace grammar */ diff --git a/alib2data/src/grammar/GrammarFromStringParser.h b/alib2data/src/grammar/GrammarFromStringParser.h index 9f2fead4353b5648be48890540aabe2014ef91c0..a77ae036c19d22797cfb5d7a6e057eb9126b44e5 100644 --- a/alib2data/src/grammar/GrammarFromStringParser.h +++ b/alib2data/src/grammar/GrammarFromStringParser.h @@ -28,14 +28,35 @@ class GrammarFromStringParser { GrammarFromStringLexer m_GrammarLexer; std::set<alphabet::Symbol> parseSet(std::istream& input) const; + std::map<alphabet::Symbol, std::set<std::vector<alphabet::Symbol>>> parseCFLikeRules(std::istream& input) const; + template<class T> T parseCFLikeGrammar(std::istream& input) const; + + std::map<std::vector<alphabet::Symbol>, std::set<std::vector<alphabet::Symbol>>> parseCSLikeRules(std::istream& input) const; + template<class T> T parseCSLikeGrammar(std::istream& input) const; + + std::map<std::tuple<std::vector<alphabet::Symbol>, alphabet::Symbol, std::vector<alphabet::Symbol>>, std::set<std::vector<alphabet::Symbol>>> parsePreservingCSLikeRules(std::istream& input) const; + template<class T> T parsePreservingCSLikeGrammar(std::istream& input) const; Grammar parseGrammar(std::istream& input) const; Grammar parseGrammar(std::istream& input, const std::set<FEATURES>& features) const; RightRG parseRightRG(std::istream& input) const; + LeftRG parseLeftRG(std::istream& input) const; + RightLG parseRightLG(std::istream& input) const; + LeftLG parseLeftLG(std::istream& input) const; + + LG parseLG(std::istream& input) const; + CFG parseCFG(std::istream& input) const; + EpsilonFreeCFG parseEpsilonFreeCFG(std::istream& input) const; + GNF parseGNF(std::istream& input) const; CNF parseCNF(std::istream& input) const; + NonContractingGrammar parseNonContractingGrammar(std::istream& input) const; + CSG parseCSG(std::istream& input) const; + ContextPreservingUnrestrictedGrammar parseContextPreservingUnrestrictedGrammar(std::istream& input) const; + UnrestrictedGrammar parseUnrestrictedGrammar(std::istream& input) const; + template<typename T> friend class alib::stringApi; }; diff --git a/alib2data/src/grammar/GrammarToStringComposer.cpp b/alib2data/src/grammar/GrammarToStringComposer.cpp index 4daef6225ff75f6f3001a5d4737d30ec0a5cffe1..f106f61f4d905ca8dfba20114859a96fe4984b74 100644 --- a/alib2data/src/grammar/GrammarToStringComposer.cpp +++ b/alib2data/src/grammar/GrammarToStringComposer.cpp @@ -1,47 +1,139 @@ #include "GrammarToStringComposer.h" #include <sstream> + +#include "Regular/RightRG.h" +#include "Regular/RightLG.h" +#include "Regular/LeftRG.h" +#include "Regular/LeftLG.h" + +#include "ContextFree/CFG.h" +#include "ContextFree/EpsilonFreeCFG.h" +#include "ContextFree/LG.h" #include "ContextFree/CNF.h" +#include "ContextFree/GNF.h" -#include "../StringApi.hpp" +#include "ContextSensitive/CSG.h" +#include "ContextSensitive/NonContractingGrammar.h" -namespace grammar { +#include "Unrestricted/ContextPreservingUnrestrictedGrammar.h" +#include "Unrestricted/UnrestrictedGrammar.h" -void GrammarToStringComposer::compose(std::ostream& output, const Grammar& grammar) const { - grammar.getData().Accept((void*) &output, *this); -} +#include "../StringApi.hpp" -void GrammarToStringComposer::compose(std::ostream& output, const LeftLG& grammar) const { - // TODO -} +namespace grammar { -void GrammarToStringComposer::compose(std::ostream& output, const LeftRG& grammar) const { - // TODO -} +template<class T> +void GrammarToStringComposer::composeCFLikeGrammar(std::ostream& output, const T& grammar) const { + bool first; -void GrammarToStringComposer::compose(std::ostream& output, const RightLG& grammar) const { - // TODO -} + output << " (" << std::endl; -void GrammarToStringComposer::compose(std::ostream& output, const RightRG& grammar) const { - // TODO + output << "{"; + first = false; + for(const auto& symbol : grammar.getNonterminalAlphabet() ) { + if(first) + output << ", "; + else + first = true; + alib::stringApi<alphabet::Symbol>::compose(output, symbol); + } + output << "}," << std::endl; + output << "{"; + first = false; + for(const auto& symbol : grammar.getTerminalAlphabet() ) { + if(first) + output << ", "; + else + first = true; + alib::stringApi<alphabet::Symbol>::compose(output, symbol); + } + output << "}," << std::endl; + output << "{ "; + first = true; + for(const auto& rule : grammar.getRawRules() ) { + if(first) + first = false; + else + output << "," << std::endl << " "; + alib::stringApi<alphabet::Symbol>::compose(output, rule.first); + output << " ->"; + bool innerFirst = true; + for(const auto& rhs : rule.second) { + if(innerFirst) + innerFirst = false; + else + output << " |"; + for(const auto& symbol : rhs) { + output << " "; + alib::stringApi<alphabet::Symbol>::compose(output, symbol); + } + } + } + output << "}," << std::endl; + alib::stringApi<alphabet::Symbol>::compose(output, grammar.getInitialSymbol()); + output << ")" << std::endl; } -void GrammarToStringComposer::compose(std::ostream& output, const LG& grammar) const { - // TODO -} +template<class T> +void GrammarToStringComposer::composeCSLikeGrammar(std::ostream& output, const T& grammar) const { + bool first; -void GrammarToStringComposer::compose(std::ostream& output, const CFG& grammar) const { - // TODO -} + output << " (" << std::endl; -void GrammarToStringComposer::compose(std::ostream& output, const EpsilonFreeCFG& grammar) const { - // TODO + output << "{"; + first = false; + for(const auto& symbol : grammar.getNonterminalAlphabet() ) { + if(first) + output << ", "; + else + first = true; + alib::stringApi<alphabet::Symbol>::compose(output, symbol); + } + output << "}," << std::endl; + output << "{"; + first = false; + for(const auto& symbol : grammar.getTerminalAlphabet() ) { + if(first) + output << ", "; + else + first = true; + alib::stringApi<alphabet::Symbol>::compose(output, symbol); + } + output << "}," << std::endl; + output << "{"; + first = true; + for(const auto& rule : grammar.getRules() ) { + if(first) + first = false; + else + output << "," << std::endl << " "; + for(const auto& symbol : rule.first) { + output << " "; + alib::stringApi<alphabet::Symbol>::compose(output, symbol); + } + output << " ->"; + bool innerFirst = true; + for(const auto& rhs : rule.second) { + if(innerFirst) + innerFirst = false; + else + output << " |"; + for(const auto& symbol : rhs) { + output << " "; + alib::stringApi<alphabet::Symbol>::compose(output, symbol); + } + } + } + output << "}," << std::endl; + alib::stringApi<alphabet::Symbol>::compose(output, grammar.getInitialSymbol()); + output << ")" << std::endl; } -void GrammarToStringComposer::compose(std::ostream& output, const CNF& grammar) const { +template<class T> +void GrammarToStringComposer::composePreservingCSLikeGrammar(std::ostream& output, const T& grammar) const { bool first; - output << "CNF (" << std::endl; + output << " (" << std::endl; output << "{"; first = false; @@ -63,14 +155,24 @@ void GrammarToStringComposer::compose(std::ostream& output, const CNF& grammar) alib::stringApi<alphabet::Symbol>::compose(output, symbol); } output << "}," << std::endl; - output << "{ "; + output << "{"; first = true; - for(const auto& rule : grammar.getRawRules() ) { + for(const auto& rule : grammar.getRules() ) { if(first) first = false; else - output << "," << std::endl << " "; - alib::stringApi<alphabet::Symbol>::compose(output, rule.first); + output << "," << std::endl << " "; + for(const auto& symbol : std::get<0>(rule.first)) { + output << " "; + alib::stringApi<alphabet::Symbol>::compose(output, symbol); + } + output << " | "; + alib::stringApi<alphabet::Symbol>::compose(output, std::get<1>(rule.first)); + output << " |"; + for(const auto& symbol : std::get<2>(rule.first)) { + output << " "; + alib::stringApi<alphabet::Symbol>::compose(output, symbol); + } output << " ->"; bool innerFirst = true; for(const auto& rhs : rule.second) { @@ -89,24 +191,73 @@ void GrammarToStringComposer::compose(std::ostream& output, const CNF& grammar) output << ")" << std::endl; } +void GrammarToStringComposer::compose(std::ostream& output, const Grammar& grammar) const { + grammar.getData().Accept((void*) &output, *this); +} + +void GrammarToStringComposer::compose(std::ostream& output, const LeftLG& grammar) const { + output << "LEFT_LG"; + composeCFLikeGrammar(output, grammar); +} + +void GrammarToStringComposer::compose(std::ostream& output, const LeftRG& grammar) const { + output << "LEFT_RG"; + composeCFLikeGrammar(output, grammar); +} + +void GrammarToStringComposer::compose(std::ostream& output, const RightLG& grammar) const { + output << "RIGHT_LG"; + composeCFLikeGrammar(output, grammar); +} + +void GrammarToStringComposer::compose(std::ostream& output, const RightRG& grammar) const { + output << "RIGHT_RG"; + composeCFLikeGrammar(output, grammar); +} + +void GrammarToStringComposer::compose(std::ostream& output, const LG& grammar) const { + output << "LG"; + composeCFLikeGrammar(output, grammar); +} + +void GrammarToStringComposer::compose(std::ostream& output, const CFG& grammar) const { + output << "CFG"; + composeCFLikeGrammar(output, grammar); +} + +void GrammarToStringComposer::compose(std::ostream& output, const EpsilonFreeCFG& grammar) const { + output << "EPSILON_FREE_CFG"; + composeCFLikeGrammar(output, grammar); +} + +void GrammarToStringComposer::compose(std::ostream& output, const CNF& grammar) const { + output << "CNF"; + composeCFLikeGrammar(output, grammar); +} + void GrammarToStringComposer::compose(std::ostream& output, const GNF& grammar) const { - // TODO + output << "GNF"; + composeCFLikeGrammar(output, grammar); } void GrammarToStringComposer::compose(std::ostream& output, const CSG& grammar) const { - // TODO + output << "CSG"; + composePreservingCSLikeGrammar(output, grammar); } void GrammarToStringComposer::compose(std::ostream& output, const NonContractingGrammar& grammar) const { - // TODO + output << "NON_CONTRACTING_GRAMMAR"; + composeCSLikeGrammar(output, grammar); } void GrammarToStringComposer::compose(std::ostream& output, const ContextPreservingUnrestrictedGrammar& grammar) const { - // TODO + output << "CONTEXT_PRESERVING_UNRESTRICTED_GRAMMAR"; + composePreservingCSLikeGrammar(output, grammar); } void GrammarToStringComposer::compose(std::ostream& output, const UnrestrictedGrammar& grammar) const { - // TODO + output << "UNRESTRICTED_GRAMMAR"; + composeCSLikeGrammar(output, grammar); } void GrammarToStringComposer::Visit(void* data, const LeftLG& grammar) const { diff --git a/alib2data/src/grammar/GrammarToStringComposer.h b/alib2data/src/grammar/GrammarToStringComposer.h index 6707e0dc8cbd79536714f0b8458fd5b161e46c28..28a74f9626de8771c2c0c199f548eb090070c00f 100644 --- a/alib2data/src/grammar/GrammarToStringComposer.h +++ b/alib2data/src/grammar/GrammarToStringComposer.h @@ -25,6 +25,10 @@ class GrammarToStringComposer : public VisitableGrammarBase::const_visitor_type void Visit(void*, const ContextPreservingUnrestrictedGrammar& grammar) const; void Visit(void*, const UnrestrictedGrammar& grammar) const; + template<class T> void composeCFLikeGrammar(std::ostream& output, const T& grammar) const; + template<class T> void composeCSLikeGrammar(std::ostream& input, const T& grammar) const; + template<class T> void composePreservingCSLikeGrammar(std::ostream& input, const T& grammar) const; + public: /** * Prints XML representation of Automaton to the output stream. diff --git a/alib2data/src/label/LabelFromStringParser.cpp b/alib2data/src/label/LabelFromStringParser.cpp index d5ec9894b97fdd0cf4a22a163dcf89188f5548bd..230ab80617637cde15bebd5adcc9ecc7768af8ac 100644 --- a/alib2data/src/label/LabelFromStringParser.cpp +++ b/alib2data/src/label/LabelFromStringParser.cpp @@ -65,9 +65,11 @@ Label LabelFromStringParser::parseLabel(std::istream& input, const std::set<FEAT return Label(label::LabelPairLabel(std::make_pair(firstLabel, secondLabel))); } case LabelFromStringLexer::TokenType::SET_END: + throw exception::AlibException("Unexpected start of Label SET_END."); case LabelFromStringLexer::TokenType::PAIR_END: + throw exception::AlibException("Unexpected start of Label PAIR_END."); case LabelFromStringLexer::TokenType::COMMA: - throw exception::AlibException("Unexpected start of Label."); + throw exception::AlibException("Unexpected start of Label COMMA."); case LabelFromStringLexer::TokenType::ERROR: if(!features.count(FEATURES::PRIMITIVE)) throw exception::AlibException(); m_Lexer.putback(input, token); diff --git a/alib2data/test-src/grammar/GrammarTest.cpp b/alib2data/test-src/grammar/GrammarTest.cpp index a318a0de965b79c302da740305caafe6cb3289f5..61f255dfe0cd8d9a2776d024c7d29b8855fb5d69 100644 --- a/alib2data/test-src/grammar/GrammarTest.cpp +++ b/alib2data/test-src/grammar/GrammarTest.cpp @@ -39,6 +39,63 @@ void GrammarTest::stringParserTest() { grammar::Grammar grammar2 = alib::StringDataFactory::fromString<grammar::Grammar>(output); + CPPUNIT_ASSERT( grammar == grammar2 ); + } + { + std::string input = "RIGHT_RG (\n" + "{A, B, S},\n" + "{a, b},\n" + "{ A -> a | a A,\n" + " B -> b | b B,\n" + " S -> | a A | a S | b B},\n" + "S)\n"; + grammar::Grammar grammar = alib::StringDataFactory::fromString<grammar::Grammar>(input); + + std::string output = alib::StringDataFactory::toString(grammar); + + std::cout << "\"" << input << "\"" << std::endl << std::endl << "\"" << output << "\"" << std::endl; + CPPUNIT_ASSERT( input == output ); + + grammar::Grammar grammar2 = alib::StringDataFactory::fromString<grammar::Grammar>(output); + + CPPUNIT_ASSERT( grammar == grammar2 ); + } + { + std::string input = "NON_CONTRACTING_GRAMMAR (\n" + "{A, B, S},\n" + "{a, b},\n" + "{ A A -> B B | a A,\n" + " B -> b | b B,\n" + " S -> A S | B B | S A},\n" + "S)\n"; + grammar::Grammar grammar = alib::StringDataFactory::fromString<grammar::Grammar>(input); + + std::string output = alib::StringDataFactory::toString(grammar); + + std::cout << "\"" << input << "\"" << std::endl << std::endl << "\"" << output << "\"" << std::endl; + CPPUNIT_ASSERT( input == output ); + + grammar::Grammar grammar2 = alib::StringDataFactory::fromString<grammar::Grammar>(output); + + CPPUNIT_ASSERT( grammar == grammar2 ); + } + { + std::string input = "CSG (\n" + "{A, B, S},\n" + "{a, b},\n" + "{ | B | -> b | b B,\n" + " | S | -> A S | B B | S A,\n" + " A | A | -> B B | a A},\n" + "S)\n"; + grammar::Grammar grammar = alib::StringDataFactory::fromString<grammar::Grammar>(input); + + std::string output = alib::StringDataFactory::toString(grammar); + + std::cout << "\"" << input << "\"" << std::endl << std::endl << "\"" << output << "\"" << std::endl; + CPPUNIT_ASSERT( input == output ); + + grammar::Grammar grammar2 = alib::StringDataFactory::fromString<grammar::Grammar>(output); + CPPUNIT_ASSERT( grammar == grammar2 ); } }