From 45297d73da7ae0cd77b76f5806a8f6675767952d Mon Sep 17 00:00:00 2001 From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz> Date: Wed, 14 May 2014 10:05:46 +0200 Subject: [PATCH] allow epsilon as input or output in unknown trans --- .../src/automaton/AutomatonFromXMLParser.cpp | 51 +++++++++++++------ alib2/src/automaton/AutomatonFromXMLParser.h | 5 +- .../src/automaton/AutomatonToXMLComposer.cpp | 15 +++++- alib2/src/automaton/AutomatonToXMLComposer.h | 1 + alib2/src/automaton/UnknownTransition.cpp | 31 ++++++----- alib2/src/automaton/UnknownTransition.h | 16 +++--- alib2/src/std/variant.hpp | 34 +++++++++++++ alib2/src/string/Epsilon.cpp | 5 ++ alib2/src/string/Epsilon.h | 2 + 9 files changed, 120 insertions(+), 40 deletions(-) diff --git a/alib2/src/automaton/AutomatonFromXMLParser.cpp b/alib2/src/automaton/AutomatonFromXMLParser.cpp index 1909162229..e5bbbf96f3 100644 --- a/alib2/src/automaton/AutomatonFromXMLParser.cpp +++ b/alib2/src/automaton/AutomatonFromXMLParser.cpp @@ -57,7 +57,7 @@ void AutomatonFromXMLParser::parseStates(std::list<sax::Token> &input, UnknownAu void AutomatonFromXMLParser::parseInputAlphabet(std::list<sax::Token> &input, UnknownAutomaton& automaton) { popToken(input, sax::Token::START_ELEMENT, "inputAlphabet"); while (isToken(input, sax::Token::START_ELEMENT, "symbol")) { - automaton.addInputSymbol(parseSymbol(input, "symbol")); + automaton.addInputSymbol(parseSymbol(input)); } popToken(input, sax::Token::END_ELEMENT, "inputAlphabet"); } @@ -81,7 +81,7 @@ void AutomatonFromXMLParser::parseFinalStates(std::list<sax::Token> &input, Unkn void AutomatonFromXMLParser::parseStackAlphabet(std::list<sax::Token> &input, UnknownAutomaton& automaton) { popToken(input, sax::Token::START_ELEMENT, "stackAlphabet"); while (isToken(input, sax::Token::START_ELEMENT, "symbol")) { - automaton.addStackSymbol(parseSymbol(input, "symbol")); + automaton.addStackSymbol(parseSymbol(input)); } popToken(input, sax::Token::END_ELEMENT, "stackAlphabet"); } @@ -89,7 +89,7 @@ void AutomatonFromXMLParser::parseStackAlphabet(std::list<sax::Token> &input, Un void AutomatonFromXMLParser::parseStartSymbols(std::list<sax::Token> &input, UnknownAutomaton& automaton) { popToken(input, sax::Token::START_ELEMENT, "startSymbols"); while (isToken(input, sax::Token::START_ELEMENT, "symbol")) { - automaton.addInitialSymbol(parseSymbol(input, "symbol")); + automaton.addInitialSymbol(parseSymbol(input)); } popToken(input, sax::Token::END_ELEMENT, "startSymbols"); } @@ -97,14 +97,14 @@ void AutomatonFromXMLParser::parseStartSymbols(std::list<sax::Token> &input, Unk void AutomatonFromXMLParser::parseTapeAlphabet(std::list<sax::Token>& input, UnknownAutomaton& automaton) { popToken(input, sax::Token::START_ELEMENT, "tapeAlphabet"); while (isToken(input, sax::Token::START_ELEMENT, "symbol")) { - automaton.addTapeSymbol(parseSymbol(input, "symbol")); + automaton.addTapeSymbol(parseSymbol(input)); } popToken(input, sax::Token::END_ELEMENT, "tapeAlphabet"); } void AutomatonFromXMLParser::parseBlankSymbol(std::list<sax::Token>& input, UnknownAutomaton& automaton) { popToken(input, sax::Token::START_ELEMENT, "blankSymbol"); - automaton.setBlankSymbol(parseSymbol(input, "symbol")); + automaton.setBlankSymbol(parseSymbol(input)); popToken(input, sax::Token::END_ELEMENT, "blankSymbol"); } @@ -119,7 +119,7 @@ void AutomatonFromXMLParser::parseTransitions(std::list<sax::Token> &input, Unkn void AutomatonFromXMLParser::parsePop(std::list<sax::Token>& input, UnknownTransition& transition) { popToken(input, sax::Token::START_ELEMENT, "pop"); while (isToken(input, sax::Token::START_ELEMENT, "symbol")) { - transition.addPop(parseSymbol(input, "symbol")); + transition.addPop(parseSymbol(input)); } popToken(input, sax::Token::END_ELEMENT, "pop"); } @@ -127,7 +127,7 @@ void AutomatonFromXMLParser::parsePop(std::list<sax::Token>& input, UnknownTrans void AutomatonFromXMLParser::parsePush(std::list<sax::Token>& input, UnknownTransition& transition) { popToken(input, sax::Token::START_ELEMENT, "push"); while (isToken(input, sax::Token::START_ELEMENT, "symbol")) { - transition.addPush(parseSymbol(input, "symbol")); + transition.addPush(parseSymbol(input)); } popToken(input, sax::Token::END_ELEMENT, "push"); } @@ -140,23 +140,42 @@ State AutomatonFromXMLParser::parseState(std::list<sax::Token> &input, std::stri return state; } -alphabet::Symbol AutomatonFromXMLParser::parseSymbol(std::list<sax::Token>& input, std::string tagName) { - popToken(input, sax::Token::START_ELEMENT, tagName); - +alphabet::Symbol AutomatonFromXMLParser::parseSymbol(std::list<sax::Token>& input) { alphabet::Symbol result(""); - if (isTokenType(input, sax::Token::CHARACTER)) { + if (isToken(input, sax::Token::START_ELEMENT, "symbol")) { + popToken(input, sax::Token::START_ELEMENT, "symbol"); result = alphabet::Symbol(popTokenData(input, sax::Token::CHARACTER)); + popToken(input, sax::Token::END_ELEMENT, "symbol"); + } else if (isToken(input, sax::Token::START_ELEMENT, "blank")) { + result = alphabet::Blank(); + input.pop_front(); + popToken(input, sax::Token::END_ELEMENT,"blank"); + } else { + throw sax::ParserException(sax::Token("", sax::Token::CHARACTER), input.front()); + } + return result; +} + +std::variant<string::Epsilon, alphabet::Symbol> AutomatonFromXMLParser::parseInput(std::list<sax::Token>& input, std::string tagName) { + popToken(input, sax::Token::START_ELEMENT, tagName); + + std::variant<string::Epsilon, alphabet::Symbol> result; + if (isToken(input, sax::Token::START_ELEMENT, "symbol")) { + popToken(input, sax::Token::START_ELEMENT, "symbol"); + result.set<alphabet::Symbol>(alphabet::Symbol(popTokenData(input, sax::Token::CHARACTER))); + popToken(input, sax::Token::END_ELEMENT, "symbol"); } else if(isToken(input, sax::Token::START_ELEMENT, "epsilon")) { - result = alphabet::Symbol(""); //TODO predelat na opravdovy epsilon + result.set<string::Epsilon>(string::Epsilon()); input.pop_front(); - popToken(input, sax::Token::END_ELEMENT,"epsilon"); + popToken(input, sax::Token::END_ELEMENT, "epsilon"); } else if (isToken(input, sax::Token::START_ELEMENT, "blank")) { - result = alphabet::Blank(); + result.set<alphabet::Symbol>(alphabet::Blank()); input.pop_front(); popToken(input, sax::Token::END_ELEMENT,"blank"); } else { throw sax::ParserException(sax::Token("", sax::Token::CHARACTER), input.front()); } + popToken(input, sax::Token::END_ELEMENT, tagName); return result; } @@ -190,7 +209,7 @@ UnknownTransition AutomatonFromXMLParser::parseTransition(std::list<sax::Token>& if (isToken(input, sax::Token::START_ELEMENT, "from")) { transition.setFrom(parseState(input, "from")); } else if (isToken(input, sax::Token::START_ELEMENT, "input")) { - transition.setInput(parseSymbol(input, "input")); + transition.setInput(parseInput(input, "input")); } else if (isToken(input, sax::Token::START_ELEMENT, "to")) { transition.setTo(parseState(input, "to")); } else if (isToken(input, sax::Token::START_ELEMENT, "pop")) { @@ -198,7 +217,7 @@ UnknownTransition AutomatonFromXMLParser::parseTransition(std::list<sax::Token>& } else if (isToken(input, sax::Token::START_ELEMENT, "push")) { parsePush(input, transition); } else if (isToken(input, sax::Token::START_ELEMENT, "output")) { - transition.setOutput(parseSymbol(input, "output")); + transition.setOutput(parseInput(input, "output")); } else if (isToken(input, sax::Token::START_ELEMENT, "shift")) { transition.setShift(parseShift(input)); } else { diff --git a/alib2/src/automaton/AutomatonFromXMLParser.h b/alib2/src/automaton/AutomatonFromXMLParser.h index 3072505554..4196cdcfeb 100644 --- a/alib2/src/automaton/AutomatonFromXMLParser.h +++ b/alib2/src/automaton/AutomatonFromXMLParser.h @@ -13,7 +13,9 @@ #include <list> #include <set> +#include "../std/variant.hpp" #include "../sax/Token.h" +#include "../string/Epsilon.h" namespace automaton { @@ -37,7 +39,8 @@ protected: UnknownTransition parseTransition(std::list<sax::Token>& input); State parseState(std::list<sax::Token> &input, std::string tagName); - alphabet::Symbol parseSymbol(std::list<sax::Token> &input, std::string tagName); + std::variant<string::Epsilon, alphabet::Symbol> parseInput(std::list<sax::Token> &input, std::string tagName); + alphabet::Symbol parseSymbol(std::list<sax::Token> &input); Shift parseShift(std::list<sax::Token> &input); public: diff --git a/alib2/src/automaton/AutomatonToXMLComposer.cpp b/alib2/src/automaton/AutomatonToXMLComposer.cpp index 32ded991df..8e05cfa173 100644 --- a/alib2/src/automaton/AutomatonToXMLComposer.cpp +++ b/alib2/src/automaton/AutomatonToXMLComposer.cpp @@ -43,7 +43,7 @@ void AutomatonToXMLComposer::printUnknownTransitions(std::list<sax::Token>& out, } if(transition.hasInput()) { - printSymbol(out, transition.getInput(), "input"); + printInput(out, transition.getInput(), "input"); } if(transition.hasTo()) { @@ -58,7 +58,7 @@ void AutomatonToXMLComposer::printUnknownTransitions(std::list<sax::Token>& out, } if (transition.hasOutput()) { - printSymbol(out, transition.getOutput(), "output"); + printInput(out, transition.getOutput(), "output"); } if (transition.getShift() != Shift::NOT_SET) { @@ -77,6 +77,17 @@ void AutomatonToXMLComposer::printState(std::list<sax::Token>& out, const State& out.push_back(sax::Token(tagName, sax::Token::END_ELEMENT)); } +void AutomatonToXMLComposer::printInput(std::list<sax::Token>& out, const std::variant<string::Epsilon, alphabet::Symbol>& symbol, std::string tagName) { + out.push_back(sax::Token(tagName, sax::Token::START_ELEMENT)); + if(symbol.is<string::Epsilon>()) { + out.push_back(sax::Token("epsilon", sax::Token::START_ELEMENT)); + out.push_back(sax::Token("epsilon", sax::Token::END_ELEMENT)); + } else { + out.push_back(sax::Token(symbol.get<alphabet::Symbol>().getSymbol(), sax::Token::CHARACTER)); + } + out.push_back(sax::Token(tagName, sax::Token::END_ELEMENT)); +} + void AutomatonToXMLComposer::printSymbol(std::list<sax::Token>& out, const alphabet::Symbol& symbol, std::string tagName) { out.push_back(sax::Token(tagName, sax::Token::START_ELEMENT)); out.push_back(sax::Token(symbol.getSymbol(), sax::Token::CHARACTER)); diff --git a/alib2/src/automaton/AutomatonToXMLComposer.h b/alib2/src/automaton/AutomatonToXMLComposer.h index 6403c4bd00..7bda0daf6d 100644 --- a/alib2/src/automaton/AutomatonToXMLComposer.h +++ b/alib2/src/automaton/AutomatonToXMLComposer.h @@ -27,6 +27,7 @@ protected: static void printState(std::list<sax::Token>&, const State& state, std::string tagName); static void printSymbol(std::list<sax::Token>&, const alphabet::Symbol& symbol, std::string tagName); + static void printInput(std::list<sax::Token>&, const std::variant<string::Epsilon, alphabet::Symbol>&, std::string); static void printShift(std::list<sax::Token>&, const Shift& shift, std::string tagName); public: diff --git a/alib2/src/automaton/UnknownTransition.cpp b/alib2/src/automaton/UnknownTransition.cpp index 9b3f63d2fb..89e9f0ecce 100644 --- a/alib2/src/automaton/UnknownTransition.cpp +++ b/alib2/src/automaton/UnknownTransition.cpp @@ -14,8 +14,8 @@ UnknownTransition::UnknownTransition() : from(NULL), to(NULL), input(NULL), outp } -UnknownTransition::UnknownTransition(const State& from, const State& to, const std::vector<alphabet::Symbol>& pop, const std::vector<alphabet::Symbol>& push, const alphabet::Symbol& input, const alphabet::Symbol& output, Shift shift) : - from(new State(from)), to(new State(to)), pop(pop), push(push), input(new alphabet::Symbol(input)), output(new alphabet::Symbol(output)), shift(shift) { +UnknownTransition::UnknownTransition(const State& from, const State& to, const std::vector<alphabet::Symbol>& pop, const std::vector<alphabet::Symbol>& push, const std::variant<string::Epsilon, alphabet::Symbol>& input, const std::variant<string::Epsilon, alphabet::Symbol>& output, Shift shift) : + from(new State(from)), to(new State(to)), pop(pop), push(push), input(new std::variant<string::Epsilon, alphabet::Symbol>(input)), output(new std::variant<string::Epsilon, alphabet::Symbol>(output)), shift(shift) { } @@ -83,9 +83,9 @@ void UnknownTransition::addPush(const alphabet::Symbol& symbol) { push.push_back(symbol); } -void UnknownTransition::setOutput(const alphabet::Symbol& symbol) { +void UnknownTransition::setOutput(const std::variant<string::Epsilon, alphabet::Symbol>& symbol) { delete output; - output = new alphabet::Symbol(symbol); + output = new std::variant<string::Epsilon, alphabet::Symbol>(symbol); } bool UnknownTransition::hasOutput() const { @@ -97,13 +97,13 @@ void UnknownTransition::clearOutput() { output = NULL; } -const alphabet::Symbol& UnknownTransition::getOutput() const { +const std::variant<string::Epsilon, alphabet::Symbol>& UnknownTransition::getOutput() const { return *output; } -void UnknownTransition::setInput(const alphabet::Symbol& symbol) { +void UnknownTransition::setInput(const std::variant<string::Epsilon, alphabet::Symbol>& symbol) { delete input; - input = new alphabet::Symbol(symbol); + input = new std::variant<string::Epsilon, alphabet::Symbol>(symbol); } bool UnknownTransition::hasInput() const { @@ -115,7 +115,7 @@ void UnknownTransition::clearInput() { input = NULL; } -const alphabet::Symbol& UnknownTransition::getInput() const { +const std::variant<string::Epsilon, alphabet::Symbol>& UnknownTransition::getInput() const { return *input; } @@ -168,12 +168,15 @@ bool UnknownTransition::operator !=(const UnknownTransition& other) const { } std::ostream& operator<<(std::ostream& out, const UnknownTransition& transition) { - out << "(UnknownTransition" - << " from = " << ((transition.from == NULL) ? (std::string) "NULL" : *transition.from) - << " input = " << ((transition.input == NULL) ? (std::string) "NULL" : *transition.input) - << " to = " << ((transition.to == NULL) ? (std::string) "NULL" : *transition.to) - << " output = " << ((transition.output == NULL) ? (std::string) "NULL" : *transition.output) - << " pop = " << transition.pop + out << "(UnknownTransition" << " from = "; + if(transition.from == NULL) out << "NULL"; else out << *transition.from; + out << " input = "; + if(transition.input == NULL) out << "NULL"; else out << *transition.input; + out << " to = "; + if(transition.to == NULL) out << "NULL"; else out << *transition.to; + out << " output = "; + if(transition.output == NULL) out << "NULL"; else out << *transition.output; + out << " pop = " << transition.pop << " push = " << transition.push << " shift = " << SHIFT_NAMES[transition.shift] << ")"; diff --git a/alib2/src/automaton/UnknownTransition.h b/alib2/src/automaton/UnknownTransition.h index f04b34d269..96822cb57c 100644 --- a/alib2/src/automaton/UnknownTransition.h +++ b/alib2/src/automaton/UnknownTransition.h @@ -13,6 +13,8 @@ #include "State.h" #include "../alphabet/Symbol.h" #include "Shift.h" +#include "../std/variant.hpp" +#include "../string/Epsilon.h" namespace automaton { @@ -27,15 +29,15 @@ protected: std::vector<alphabet::Symbol> pop; std::vector<alphabet::Symbol> push; - alphabet::Symbol* input; - alphabet::Symbol* output; + std::variant<string::Epsilon, alphabet::Symbol>* input; + std::variant<string::Epsilon, alphabet::Symbol>* output; Shift shift; public: UnknownTransition(); - UnknownTransition(const State& from, const State& to, const std::vector<alphabet::Symbol>& pop, const std::vector<alphabet::Symbol>& push, const alphabet::Symbol& input, const alphabet::Symbol& output, Shift shift); + UnknownTransition(const State& from, const State& to, const std::vector<alphabet::Symbol>& pop, const std::vector<alphabet::Symbol>& push, const std::variant<string::Epsilon, alphabet::Symbol>& input, const std::variant<string::Epsilon, alphabet::Symbol>& output, Shift shift); ~UnknownTransition(); /** @@ -113,13 +115,13 @@ public: /** * @return the output symbol of the transition */ - const alphabet::Symbol& getInput() const; + const std::variant<string::Epsilon, alphabet::Symbol>& getInput() const; /** * Sets the output Symbol of the transition. * @param symbol Symbol to set */ - void setInput(const alphabet::Symbol& symbol); + void setInput(const std::variant<string::Epsilon, alphabet::Symbol>& symbol); /** * @return true if the input symbol is set @@ -134,13 +136,13 @@ public: /** * @return the output symbol of the transition */ - const alphabet::Symbol& getOutput() const; + const std::variant<string::Epsilon, alphabet::Symbol>& getOutput() const; /** * Sets the output Symbol of the transition. * @param symbol Symbol to set */ - void setOutput(const alphabet::Symbol& symbol); + void setOutput(const std::variant<string::Epsilon, alphabet::Symbol>& symbol); /** * @return true if the output symbol is set diff --git a/alib2/src/std/variant.hpp b/alib2/src/std/variant.hpp index 396e628e6f..784db111c4 100644 --- a/alib2/src/std/variant.hpp +++ b/alib2/src/std/variant.hpp @@ -70,6 +70,14 @@ struct variant_helper<F, Ts...> { return variant_helper<Ts...>::compareEq(this_t, this_v, other_t, other_v); } + inline static void print(ostream& out, const size_t id, const void* data) { + if (id == typeid(F).hash_code()) + out << *reinterpret_cast<const F*>(data); + else + variant_helper<Ts...>::print(out, id, data); + } + + inline static bool compareLess(size_t this_t, const void * this_v, size_t other_t, const void * other_v) { if (this_t == typeid(F).hash_code() && other_t != typeid(F).hash_code()) return true; @@ -88,6 +96,7 @@ inline static void destroy(size_t id, void * data) { } inline static bool move(size_t old_t, void * old_v, void * new_v) { return false; } inline static void copy(size_t old_t, const void * old_v, void * new_v) { } inline static bool compareEq(size_t this_t, const void * this_v, size_t other_t, const void * other_v) { return true; } +inline static void print(ostream& out, const size_t id, const void* data) {} inline static bool compareLess(size_t this_t, const void * this_v, size_t other_t, const void * other_v) { return false; } }; @@ -137,11 +146,31 @@ public: return helper_t::compareEq(type_id, &data, other.type_id, &other.data); } + bool operator!= (const variant<F, Ts...>& other) const + { + return !(*this == other); + } + bool operator< (const variant<F, Ts...>& other) const { return helper_t::compareLess(type_id, &data, other.type_id, &other.data); } + bool operator> (const variant<F, Ts...>& other) const + { + return other < *this; + } + + bool operator<= (const variant<F, Ts...>& other) const + { + return !(*this > other); + } + + bool operator>= (const variant<F, Ts...>& other) const + { + return !(*this < other); + } + template<typename T> bool is() const { return (type_id == typeid(T).hash_code()); @@ -192,6 +221,11 @@ public: ~variant() { helper_t::destroy(type_id, &data); } + + friend std::ostream& operator <<(std::ostream& out, const variant<F, Ts...>& obj) { + helper_t::print(out, obj.type_id, &obj.data); + return out; + } }; } /* namespace std */ diff --git a/alib2/src/string/Epsilon.cpp b/alib2/src/string/Epsilon.cpp index d758e43730..77a92db4af 100644 --- a/alib2/src/string/Epsilon.cpp +++ b/alib2/src/string/Epsilon.cpp @@ -25,6 +25,11 @@ bool Epsilon::operator!=(const Epsilon& other) const { return false; } +std::ostream& operator<<(std::ostream& out, const Epsilon& eps) { + out << (const String&) eps; + return out; +} + Epsilon Epsilon::EPSILON = Epsilon(); } /* namespace string */ diff --git a/alib2/src/string/Epsilon.h b/alib2/src/string/Epsilon.h index 6eb628e13a..18b4e9f796 100644 --- a/alib2/src/string/Epsilon.h +++ b/alib2/src/string/Epsilon.h @@ -32,6 +32,8 @@ public: bool operator==(const Epsilon& other) const; bool operator!=(const Epsilon& other) const; + + friend std::ostream& operator<<(std::ostream& out, const Epsilon& eps); static Epsilon EPSILON; }; -- GitLab