diff --git a/alib2data/src/automaton/AutomatonClasses.h b/alib2data/src/automaton/AutomatonClasses.h index 064b6d8ba75160b5d62ed9c06cc6bc8bdc9cdd1e..d1f120910bf6779a60ecb590e69139e0aaa796eb 100644 --- a/alib2data/src/automaton/AutomatonClasses.h +++ b/alib2data/src/automaton/AutomatonClasses.h @@ -23,6 +23,7 @@ #include "PDA/RealTimeHeightDeterministicDPDA.h" #include "PDA/RealTimeHeightDeterministicNPDA.h" #include "PDA/NPDA.h" +#include "PDA/NPDTA.h" #include "PDA/SinglePopNPDA.h" #include "TM/OneTapeDTM.h" #include "TA/DFTA.h" diff --git a/alib2data/src/automaton/AutomatonFeatures.h b/alib2data/src/automaton/AutomatonFeatures.h index 83cb35dce053d098d4ff44345d83fc15317ab53a..ec1eb6b9e3b3e7cc9f3286f11746b08dd45d8d2f 100644 --- a/alib2data/src/automaton/AutomatonFeatures.h +++ b/alib2data/src/automaton/AutomatonFeatures.h @@ -52,6 +52,7 @@ class VisiblyPushdownNPDA; class RealTimeHeightDeterministicDPDA; class RealTimeHeightDeterministicNPDA; class NPDA; +class NPDTA; class SinglePopNPDA; class OneTapeDTM; class DFTA; diff --git a/alib2data/src/automaton/PDA/NPDTA.cpp b/alib2data/src/automaton/PDA/NPDTA.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d80fc2109d4e0ca6d9e7fd633c0bb38a55e1e9e0 --- /dev/null +++ b/alib2data/src/automaton/PDA/NPDTA.cpp @@ -0,0 +1,290 @@ +/* + * NPDTA.cpp + * + * Created on: 10. 5. 2016 + * Author: Jakub Doupal + */ + +#include "NPDTA.h" +#include "../AutomatonException.h" +#include <algorithm> +#include <sstream> + +#include <sax/FromXMLParserHelper.h> +#include "../common/AutomatonFromXMLParser.h" +#include "../common/AutomatonToXMLComposer.h" +#include "../Automaton.h" +#include <object/Object.h> +#include <XmlApi.hpp> +#include <cast/CastApi.hpp> + +namespace automaton { + +NPDTA::NPDTA(State initialState, alphabet::Symbol initialPushdownSymbol) : SingleInitialSymbolPushdownStoreAlphabet(std::move(initialPushdownSymbol)), SingleInitialState(std::move(initialState)) { + +} + +AutomatonBase* NPDTA::clone() const { + return new NPDTA(*this); +} + +AutomatonBase* NPDTA::plunder() && { + return new NPDTA(std::move(*this)); +} + +bool NPDTA::removeState(const State& state) { + if (initialState == state) { + throw AutomatonException("State \"" + (std::string) state.getName() + "\" is initial state."); + } + + if (finalStates.find(state) != finalStates.end()) { + throw AutomatonException("State \"" + (std::string) state.getName() + "\" is final state."); + } + + for (const std::pair<const std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::tuple<State, std::vector<alphabet::Symbol>, std::vector<alphabet::Symbol> > > >& transition : transitions) { + if (state == std::get<0>(transition.first)) + throw AutomatonException("State \"" + (std::string) state.getName() + "\" is used in transition."); + for(const std::tuple<State, std::vector<alphabet::Symbol>, std::vector<alphabet::Symbol> >& target : transition.second) { + if(std::get<0>(target) == state) + throw AutomatonException("State \"" + (std::string) state.getName() + "\" is used in transition."); + } + } + + return states.erase(state); +} + +bool NPDTA::removeInputSymbol(const alphabet::Symbol& symbol) { + for (const std::pair<const std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::tuple<State, std::vector<alphabet::Symbol>, std::vector<alphabet::Symbol> > > >& transition : transitions) { + if (std::get<1>(transition.first).is<alphabet::Symbol>() && symbol == std::get<1>(transition.first).get<alphabet::Symbol>()) + throw AutomatonException("Symbol \"" + (std::string) symbol + "\" is used in transition."); + } + + return inputAlphabet.erase(symbol); +} + +bool NPDTA::removeStackSymbol(const alphabet::Symbol& symbol) { + if(initialSymbol == symbol) { + throw AutomatonException("Stack symbol \"" + (std::string) symbol + "\" is start symbol."); + } + + for (const std::pair<const std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::tuple<State, std::vector<alphabet::Symbol>, std::vector<alphabet::Symbol> > > >& transition : transitions) { + for (const alphabet::Symbol& popSymbol : std::get<2>(transition.first)) { + if (symbol == popSymbol) + throw AutomatonException("Stack symbol \"" + (std::string) symbol + "\" is used in transition."); + } + for (const std::tuple<State, std::vector<alphabet::Symbol>, std::vector<alphabet::Symbol> >& target : transition.second) { + if (std::find(std::get<1>(target).begin(), std::get<1>(target).end(), symbol) != std::get<1>(target).end()) + throw AutomatonException("Stack symbol \"" + (std::string) symbol + "\" is used in transition."); + } + } + + return stackAlphabet.erase(symbol); +} + +bool NPDTA::removeOutputSymbol(const alphabet::Symbol& symbol) { + for (const std::pair<const std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::tuple<State, std::vector<alphabet::Symbol>, std::vector<alphabet::Symbol> > > >& transition : transitions) { + for(const std::tuple<State, std::vector<alphabet::Symbol>, std::vector<alphabet::Symbol> >& target : transition.second) { + if (std::find(std::get<2>(target).begin(), std::get<2>(target).end(), symbol) != std::get<2>(target).end()) { + throw AutomatonException("Symbol \"" + (std::string) symbol + "\" is used in transition."); + } + } + } + + return outputAlphabet.erase(symbol); +} + +bool NPDTA::addTransition(State from, std::variant<string::Epsilon, alphabet::Symbol> input, std::vector<alphabet::Symbol> pop, State to, std::vector<alphabet::Symbol> push, std::vector<alphabet::Symbol> output) { + if (states.find(from) == states.end()) { + throw AutomatonException("State \"" + (std::string) from.getName() + "\" doesn't exist."); + } + + if (input.is<alphabet::Symbol>() && inputAlphabet.find(input.get<alphabet::Symbol>()) == inputAlphabet.end()) { + throw AutomatonException("Input symbol \"" + (std::string) input.get<alphabet::Symbol>() + "\" doesn't exist."); + } + + if (states.find(to) == states.end()) { + throw AutomatonException("State \"" + (std::string) to.getName() + "\" doesn't exist."); + } + + for(const alphabet::Symbol& popSymbol : pop) { + if (stackAlphabet.find(popSymbol) == stackAlphabet.end()) { + throw AutomatonException("Stack symbol \"" + (std::string) popSymbol + "\" doesn't exist."); + } + } + + for(const alphabet::Symbol& pushSymbol : push) { + if (stackAlphabet.find(pushSymbol) == stackAlphabet.end()) { + throw AutomatonException("Stack symbol \"" + (std::string) pushSymbol + "\" doesn't exist."); + } + } + + for(const alphabet::Symbol& outputSymbol : output) { + if (outputAlphabet.find(outputSymbol) == outputAlphabet.end()) { + throw AutomatonException("Output symbol \"" + (std::string) outputSymbol + "\" doesn't exist."); + } + } + + std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> > key(std::move(from), std::move(input), std::move(pop)); + std::tuple<State, std::vector<alphabet::Symbol>, std::vector<alphabet::Symbol> > value(std::move(to), std::move(push), std::move(output)); + + return transitions[std::move(key)].insert(std::move(value)).second; +} + +bool NPDTA::addTransition(State from, alphabet::Symbol input, std::vector<alphabet::Symbol> pop, State to, std::vector<alphabet::Symbol> push, std::vector<alphabet::Symbol> output) { + std::variant<string::Epsilon, alphabet::Symbol> inputVariant(std::move(input)); + return addTransition(std::move(from), std::move(inputVariant), std::move(pop), std::move(to), std::move(push), std::move(output)); +} + +bool NPDTA::addTransition(State from, std::vector<alphabet::Symbol> pop, State to, std::vector<alphabet::Symbol> push, std::vector<alphabet::Symbol> output) { + std::variant<string::Epsilon, alphabet::Symbol> inputVariant(string::Epsilon::EPSILON); + return addTransition(std::move(from), std::move(inputVariant), std::move(pop), std::move(to), std::move(push), std::move(output)); +} + +bool NPDTA::removeTransition(const State& from, const std::variant<string::Epsilon, alphabet::Symbol>& input, const std::vector<alphabet::Symbol>& pop, const State& to, const std::vector<alphabet::Symbol>& push, const std::vector<alphabet::Symbol>& output) { + std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> > key(from, input, pop); + std::tuple<State, std::vector<alphabet::Symbol>, std::vector<alphabet::Symbol> > value(to, push, output); + + return transitions[key].erase(value); +} + +bool NPDTA::removeTransition(const State& from, const alphabet::Symbol& input, const std::vector<alphabet::Symbol>& pop, const State& to, const std::vector<alphabet::Symbol>& push, const std::vector<alphabet::Symbol>& output) { + std::variant<string::Epsilon, alphabet::Symbol> inputVariant(input); + return removeTransition(from, inputVariant, pop, to, push, output); +} + +bool NPDTA::removeTransition(const State& from, const std::vector<alphabet::Symbol>& pop, const State& to, const std::vector<alphabet::Symbol>& push, const std::vector<alphabet::Symbol>& output) { + std::variant<string::Epsilon, alphabet::Symbol> inputVariant(string::Epsilon::EPSILON); + return removeTransition(from, inputVariant, pop, to, push, output); +} + +const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, std::vector<alphabet::Symbol> >, std::set<std::tuple<State, std::vector<alphabet::Symbol>, std::vector<alphabet::Symbol> > > >& NPDTA::getTransitions() const { + return transitions; +} + +std::set < std::pair < std::tuple < State, std::variant < string::Epsilon, alphabet::Symbol >, std::vector < alphabet::Symbol > >, std::tuple < State, std::vector < alphabet::Symbol >, std::vector < alphabet::Symbol > > > > NPDTA::getTransitionsFromState ( const State & from ) const { + if( states.find(from) == states.end()) + throw AutomatonException("State \"" + (std::string) from.getName() + "\" doesn't exist"); + + std::set < std::pair < std::tuple < State, std::variant < string::Epsilon, alphabet::Symbol >, std::vector < alphabet::Symbol > >, std::tuple < State, std::vector < alphabet::Symbol >, std::vector < alphabet::Symbol > > > > transitionsFromState; + for ( auto transition: transitions ) { + for ( auto iter: transition.second ) { + if ( std::get<0>(transition.first) == from ) { + transitionsFromState.insert(std::make_pair(transition.first, iter)); + } + } + } + + return transitionsFromState; +} + +int NPDTA::compare(const NPDTA& other) const { + auto first = std::tie(states, inputAlphabet, outputAlphabet, initialState, finalStates, stackAlphabet, initialSymbol, transitions); + auto second = std::tie(other.states, other.inputAlphabet, other.outputAlphabet, other.initialState, other.finalStates, other.stackAlphabet, other.initialSymbol, other.transitions); + + std::compare<decltype(first)> comp; + return comp(first, second); +} + +void NPDTA::operator>>(std::ostream& out) const { + out << "(NPDTA " + << "states = " << states + << "inputAlphabet = " << inputAlphabet + << "initialState = " << initialState + << "finalStates = " << finalStates + << "stackAlphabet = " << stackAlphabet + << "initialSymbol = " << initialSymbol + << "outputAlphabet = " << outputAlphabet + << "transitions = " << transitions + << ")"; +} + +NPDTA::operator std::string () const { + std::stringstream ss; + ss << *this; + return ss.str(); +} + +const std::string NPDTA::XML_TAG_NAME = "NPDTA"; + +NPDTA NPDTA::parse(std::deque<sax::Token>::iterator& input) { + sax::FromXMLParserHelper::popToken(input, sax::Token::TokenType::START_ELEMENT, NPDTA::XML_TAG_NAME); + + std::set<State> states = AutomatonFromXMLParser::parseStates(input); + std::set<alphabet::Symbol> inputSymbols = AutomatonFromXMLParser::parseInputAlphabet(input); + std::set<alphabet::Symbol> stackSymbols = AutomatonFromXMLParser::parseStackAlphabet(input); + std::set<alphabet::Symbol> outputSymbols = AutomatonFromXMLParser::parseOutputAlphabet(input); + State initialState = AutomatonFromXMLParser::parseInitialState(input); + alphabet::Symbol initialStackSymbol = AutomatonFromXMLParser::parseInitialStackSymbol(input); + std::set<State> finalStates = AutomatonFromXMLParser::parseFinalStates(input); + + NPDTA automaton(std::move(initialState), std::move(initialStackSymbol)); + automaton.setStates(std::move(states)); + automaton.setInputAlphabet(std::move(inputSymbols)); + automaton.setStackAlphabet(std::move(stackSymbols)); + automaton.setOutputAlphabet(std::move(outputSymbols)); + automaton.setFinalStates(std::move(finalStates)); + + AutomatonFromXMLParser::parseTransitions<NPDTA>(input, automaton); + + sax::FromXMLParserHelper::popToken(input, sax::Token::TokenType::END_ELEMENT, NPDTA::XML_TAG_NAME); + return automaton; +} + +void NPDTA::parseTransition(std::deque<sax::Token>::iterator& input, NPDTA& automaton) { + sax::FromXMLParserHelper::popToken(input, sax::Token::TokenType::START_ELEMENT, "transition"); + State from = AutomatonFromXMLParser::parseTransitionFrom(input); + std::variant<string::Epsilon, alphabet::Symbol> inputSymbol = AutomatonFromXMLParser::parseTransitionInputEpsilonSymbol(input); + std::vector<alphabet::Symbol> pop = AutomatonFromXMLParser::parseTransitionPop(input); + State to = AutomatonFromXMLParser::parseTransitionTo(input); + std::vector<alphabet::Symbol> push = AutomatonFromXMLParser::parseTransitionPush(input); + std::vector<alphabet::Symbol> output = AutomatonFromXMLParser::parseTransitionOutputSymbolMultiple(input); + sax::FromXMLParserHelper::popToken(input, sax::Token::TokenType::END_ELEMENT, "transition"); + + automaton.addTransition(std::move(from), std::move(inputSymbol), std::move(pop), std::move(to), std::move(push), std::move(output)); +} + +void NPDTA::compose(std::deque<sax::Token>& out) const { + out.emplace_back(NPDTA::XML_TAG_NAME, sax::Token::TokenType::START_ELEMENT); + + AutomatonToXMLComposer::composeStates(out, this->getStates()); + AutomatonToXMLComposer::composeInputAlphabet(out, this->getInputAlphabet()); + AutomatonToXMLComposer::composeStackAlphabet(out, this->getStackAlphabet()); + AutomatonToXMLComposer::composeOutputAlphabet(out, this->getOutputAlphabet()); + AutomatonToXMLComposer::composeInitialState(out, this->getInitialState()); + AutomatonToXMLComposer::composeInitialStackSymbol(out, this->getInitialSymbol()); + AutomatonToXMLComposer::composeFinalStates(out, this->getFinalStates()); + composeTransitions(out); + + out.emplace_back(NPDTA::XML_TAG_NAME, sax::Token::TokenType::END_ELEMENT); +} + +void NPDTA::composeTransitions(std::deque<sax::Token>& out) const { + out.emplace_back("transitions", sax::Token::TokenType::START_ELEMENT); + for(const auto& transition : this->getTransitions()) { + for(const auto& target: transition.second) { + out.emplace_back("transition", sax::Token::TokenType::START_ELEMENT); + + AutomatonToXMLComposer::composeTransitionFrom(out, std::get<0>(transition.first)); + AutomatonToXMLComposer::composeTransitionInputEpsilonSymbol(out, std::get<1>(transition.first)); + AutomatonToXMLComposer::composeTransitionPop(out, std::get<2>(transition.first)); + AutomatonToXMLComposer::composeTransitionTo(out, std::get<0>(target)); + AutomatonToXMLComposer::composeTransitionPush(out, std::get<1>(target)); + AutomatonToXMLComposer::composeTransitionOutputSymbolMultiple(out, std::get<2>(target)); + + out.emplace_back("transition", sax::Token::TokenType::END_ELEMENT); + } + } + + out.emplace_back("transitions", sax::Token::TokenType::END_ELEMENT); +} + +} /* namespace automaton */ + +namespace alib { + +auto NPDTAParserRegister = xmlApi<automaton::Automaton>::ParserRegister<automaton::NPDTA>(); +auto NPDTAParserRegister2 = xmlApi<alib::Object>::ParserRegister<automaton::NPDTA>(); + +auto NPDTACastBinder = castApi::CastPoolStringBinder<automaton::NPDTA>(automaton::NPDTA::XML_TAG_NAME); + +} /* namespace alib */ diff --git a/alib2data/src/automaton/PDA/NPDTA.h b/alib2data/src/automaton/PDA/NPDTA.h new file mode 100644 index 0000000000000000000000000000000000000000..c25e25eca4df80e8212933913fac431ca45fdefb --- /dev/null +++ b/alib2data/src/automaton/PDA/NPDTA.h @@ -0,0 +1,124 @@ +/* + * NPDTA.h + * + * Created on: 10. 5. 2016 + * Author: Jakub Doupal + */ + +#ifndef NPDTA_H_ +#define NPDTA_H_ + +#include <set> +#include <map> +#include <vector> +#include <variant> +#include "../AutomatonBase.h" +#include "../common/SingleInitialState.h" +#include "../common/SingleInitialSymbolPushdownStoreAlphabet.h" +#include "../common/InputAlphabet.h" +#include "../common/OutputAlphabet.h" +#include "../../alphabet/Symbol.h" +#include "../../string/Epsilon.h" + +namespace automaton { + +/** + * Push Down Translation Automaton + */ +class NPDTA : public AutomatonBase, public SingleInitialSymbolPushdownStoreAlphabet, public SingleInitialState, public InputAlphabet, public OutputAlphabet { +protected: + std::map < std::tuple < State, std::variant < string::Epsilon, alphabet::Symbol >, std::vector < alphabet::Symbol > >, std::set < std::tuple < State, std::vector < alphabet::Symbol >, std::vector < alphabet::Symbol > > > > transitions; + +public: + explicit NPDTA ( State initialState, alphabet::Symbol initialPushdownSymbol ); + + virtual AutomatonBase * clone ( ) const; + + virtual AutomatonBase * plunder ( ) &&; + + /** + * @copydoc Automaton::removeState(const State&) + */ + virtual bool removeState ( const State & state ); + + /** + * @copydoc Automaton::removeInputSymbol(const Symbol&) + */ + virtual bool removeInputSymbol ( const alphabet::Symbol & symbol ); + + /** + * @copydoc Automaton::removeStackSymbol(const Symbol&) + */ + virtual bool removeStackSymbol ( const alphabet::Symbol & symbol ); + + /** + * @copydoc Automaton::removeOutputSymbol(const Symbol&) + */ + virtual bool removeOutputSymbol ( const alphabet::Symbol & symbol ); + + /** + * Adds transition to the NPDTA. + * @param transition transition to add + * @throws AutomatonException when some part of the transition is not present + * in the NPDTA (state, input symbol, stack symbol, output symbol) or when transition already exists + */ + bool addTransition ( State from, std::variant < string::Epsilon, alphabet::Symbol > input, std::vector < alphabet::Symbol > pop, State to, std::vector < alphabet::Symbol > push, std::vector < alphabet::Symbol > output ); + + bool addTransition ( State from, alphabet::Symbol input, std::vector < alphabet::Symbol > pop, State to, std::vector < alphabet::Symbol > push, std::vector < alphabet::Symbol > output ); + + bool addTransition ( State from, std::vector < alphabet::Symbol > pop, State to, std::vector < alphabet::Symbol > push, std::vector < alphabet::Symbol > output ); + + /** + * Removes the transition from the NPDTA. + * @param transition transition to remove + * @throws AutomatonException when transition is not present in the NPDTA + */ + bool removeTransition ( const State & from, const std::variant < string::Epsilon, alphabet::Symbol > & input, const std::vector < alphabet::Symbol > & pop, const State & to, const std::vector < alphabet::Symbol > & push, const std::vector < alphabet::Symbol > & output ); + + bool removeTransition ( const State & from, const alphabet::Symbol & input, const std::vector < alphabet::Symbol > & pop, const State & to, const std::vector < alphabet::Symbol > & push, const std::vector < alphabet::Symbol > & output ); + + bool removeTransition ( const State & from, const std::vector < alphabet::Symbol > & pop, const State & to, const std::vector < alphabet::Symbol > & push, const std::vector < alphabet::Symbol > & output ); + + /** + * @return NPDTA transitions + */ + const std::map < std::tuple < State, std::variant < string::Epsilon, alphabet::Symbol >, std::vector < alphabet::Symbol > >, std::set < std::tuple < State, std::vector < alphabet::Symbol >, std::vector < alphabet::Symbol > > > > & getTransitions ( ) const; + + std::set < std::pair < std::tuple < State, std::variant < string::Epsilon, alphabet::Symbol >, std::vector < alphabet::Symbol > >, std::tuple < State, std::vector < alphabet::Symbol >, std::vector < alphabet::Symbol > > > > getTransitionsFromState ( const State & from ) const; + + virtual int compare ( const ObjectBase & other ) const { + if ( std::type_index ( typeid ( * this ) ) == std::type_index ( typeid ( other ) ) ) return this->compare ( ( decltype ( * this ) )other ); + + return std::type_index ( typeid ( * this ) ) - std::type_index ( typeid ( other ) ); + } + + virtual int compare ( const NPDTA & other ) const; + + virtual void operator >>( std::ostream & os ) const; + + virtual explicit operator std::string ( ) const; + + const static std::string XML_TAG_NAME; + + static NPDTA parse ( std::deque < sax::Token >::iterator & input ); + static void parseTransition ( std::deque < sax::Token >::iterator & input, NPDTA & automaton ); + + void compose ( std::deque < sax::Token > & out ) const; + void composeTransitions ( std::deque < sax::Token > & out ) const; +}; + +} /* namespace automaton */ + +namespace std { + +template < > +struct compare < automaton::NPDTA > { + int operator ()( const automaton::NPDTA & first, const automaton::NPDTA & second ) const { + return first.compare ( second ); + } + +}; + +} /* namespace std */ + +#endif /* NPDTA_H_ */ diff --git a/alib2data/src/automaton/common/AutomatonFromXMLParser.cpp b/alib2data/src/automaton/common/AutomatonFromXMLParser.cpp index 1dafb9b6c2a64e99d0be02d90410c1e0f0667c19..6456937337df76e63a388eac54caf4a16b5419cc 100644 --- a/alib2data/src/automaton/common/AutomatonFromXMLParser.cpp +++ b/alib2data/src/automaton/common/AutomatonFromXMLParser.cpp @@ -133,6 +133,17 @@ std::set < alphabet::Symbol > AutomatonFromXMLParser::parseInitialStackSymbols ( return initialSymbols; } +std::set < alphabet::Symbol > AutomatonFromXMLParser::parseOutputAlphabet ( std::deque < sax::Token >::iterator & input ) { + std::set < alphabet::Symbol > outputSymbols; + sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, "outputAlphabet" ); + + while ( sax::FromXMLParserHelper::isTokenType ( input, sax::Token::TokenType::START_ELEMENT ) ) + outputSymbols.insert ( alib::xmlApi < alphabet::Symbol >::parse ( input ) ); + + sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, "outputAlphabet" ); + return outputSymbols; +} + alphabet::Symbol AutomatonFromXMLParser::parseInitialStackSymbol ( std::deque < sax::Token >::iterator & input ) { sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, "initialStackSymbol" ); alphabet::Symbol initialSymbol ( alib::xmlApi < alphabet::Symbol >::parse ( input ) ); @@ -331,6 +342,17 @@ std::variant < string::Epsilon, alphabet::Symbol > AutomatonFromXMLParser::parse } } +std::vector < alphabet::Symbol > AutomatonFromXMLParser::parseTransitionOutputSymbolMultiple ( std::deque < sax::Token >::iterator & input ) { + std::vector < alphabet::Symbol > outputSymbols; + sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, "output" ); + + while ( sax::FromXMLParserHelper::isTokenType ( input, sax::Token::TokenType::START_ELEMENT ) ) + outputSymbols.push_back ( alib::xmlApi < alphabet::Symbol >::parse ( input ) ); + + sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::END_ELEMENT, "output" ); + return outputSymbols; +} + string::LinearString AutomatonFromXMLParser::parseTransitionInputString ( std::deque < sax::Token >::iterator & input ) { sax::FromXMLParserHelper::popToken ( input, sax::Token::TokenType::START_ELEMENT, "input" ); string::LinearString result ( alib::xmlApi < string::LinearString >::parse ( input ) ); diff --git a/alib2data/src/automaton/common/AutomatonFromXMLParser.h b/alib2data/src/automaton/common/AutomatonFromXMLParser.h index ff8621b240a35f3a8c8f5a636949574c8331973c..5decfbeb5e7aafbcb80fe5ea808eb15d057ccde3 100644 --- a/alib2data/src/automaton/common/AutomatonFromXMLParser.h +++ b/alib2data/src/automaton/common/AutomatonFromXMLParser.h @@ -36,6 +36,7 @@ public: static std::set<alphabet::Symbol> parseStackAlphabet(std::deque<sax::Token>::iterator& input); static std::set<alphabet::Symbol> parseInitialStackSymbols(std::deque<sax::Token>::iterator& input); static alphabet::Symbol parseInitialStackSymbol(std::deque<sax::Token>::iterator& input); + static std::set<alphabet::Symbol> parseOutputAlphabet(std::deque<sax::Token>::iterator& input); static std::set<alphabet::Symbol> parseTapeAlphabet(std::deque<sax::Token>::iterator& input); static State parseInitialState(std::deque<sax::Token>::iterator& input); static std::set<State> parseInitialStates(std::deque<sax::Token>::iterator& input); @@ -66,6 +67,7 @@ public: static alphabet::Symbol parseTransitionOutputSymbol(std::deque<sax::Token>::iterator& input); static std::variant<string::Epsilon, alphabet::Symbol> parseTransitionOutputEpsilonSymbol(std::deque<sax::Token>::iterator& input); static std::variant<string::Epsilon, alphabet::Symbol> parseTransitionOutputBlankEpsilonSymbol(std::deque<sax::Token>::iterator& input); + static std::vector<alphabet::Symbol> parseTransitionOutputSymbolMultiple(std::deque<sax::Token>::iterator& input); static alphabet::Symbol parseSymbolIO(std::deque<sax::Token>::iterator& input); static std::variant<string::Epsilon, alphabet::Symbol> parseEpsilonSymbolIO(std::deque<sax::Token>::iterator& input); diff --git a/alib2data/src/automaton/common/AutomatonToXMLComposer.cpp b/alib2data/src/automaton/common/AutomatonToXMLComposer.cpp index 16777ba68972f4083ba0b9c9cb57423009a5a9de..d36ae5b7a4385e464e564d1b8d20c58759ec10c1 100644 --- a/alib2data/src/automaton/common/AutomatonToXMLComposer.cpp +++ b/alib2data/src/automaton/common/AutomatonToXMLComposer.cpp @@ -108,6 +108,14 @@ void AutomatonToXMLComposer::composeInitialStackSymbol(std::deque<sax::Token>& o out.emplace_back("initialStackSymbol", sax::Token::TokenType::END_ELEMENT); } +void AutomatonToXMLComposer::composeOutputAlphabet(std::deque<sax::Token>& out, const std::set<alphabet::Symbol>& symbols) { + out.emplace_back("outputAlphabet", sax::Token::TokenType::START_ELEMENT); + for (const auto& symbol : symbols) { + alib::xmlApi<alphabet::Symbol>::compose(out, symbol); + } + out.emplace_back("outputAlphabet", sax::Token::TokenType::END_ELEMENT); +} + void AutomatonToXMLComposer::composeTapeAlphabet(std::deque<sax::Token>& out, const std::set<alphabet::Symbol>& symbols) { out.emplace_back("tapeAlphabet", sax::Token::TokenType::START_ELEMENT); for (const auto& symbol : symbols) { @@ -215,6 +223,14 @@ void AutomatonToXMLComposer::composeTransitionOutputSymbol(std::deque<sax::Token out.emplace_back("output", sax::Token::TokenType::END_ELEMENT); } +void AutomatonToXMLComposer::composeTransitionOutputSymbolMultiple(std::deque<sax::Token>& out, const std::vector<alphabet::Symbol>& symbols) { + out.emplace_back("output", sax::Token::TokenType::START_ELEMENT); + for (const auto& symbol : symbols) { + alib::xmlApi<alphabet::Symbol>::compose(out, symbol); + } + out.emplace_back("output", sax::Token::TokenType::END_ELEMENT); +} + void AutomatonToXMLComposer::composeTransitionInputEpsilonSymbol(std::deque<sax::Token>& out, const std::variant<string::Epsilon, alphabet::Symbol>& symbol) { out.emplace_back("input", sax::Token::TokenType::START_ELEMENT); if(symbol.is<string::Epsilon>()) { diff --git a/alib2data/src/automaton/common/AutomatonToXMLComposer.h b/alib2data/src/automaton/common/AutomatonToXMLComposer.h index cdc8a5e94a04295ad259bbdc5d39ab7a4007cb45..cc8fd67f37c31ee95a942f85523c5b6348733b69 100644 --- a/alib2data/src/automaton/common/AutomatonToXMLComposer.h +++ b/alib2data/src/automaton/common/AutomatonToXMLComposer.h @@ -39,6 +39,7 @@ public: static void composeStackAlphabet(std::deque<sax::Token>&, const std::set<alphabet::Symbol>& symbols); static void composeInitialStackSymbols(std::deque<sax::Token>&, const std::set<alphabet::Symbol>& symbols); static void composeInitialStackSymbol(std::deque<sax::Token>&, const alphabet::Symbol& symbols); + static void composeOutputAlphabet(std::deque<sax::Token>&, const std::set<alphabet::Symbol>& symbols); static void composeTapeAlphabet(std::deque<sax::Token>&, const std::set<alphabet::Symbol>& symbols); static void composeBlankSymbol(std::deque<sax::Token>&, const alphabet::Symbol& symbol); static void composeBottomOfTheStackSymbol(std::deque<sax::Token>&, const alphabet::Symbol& symbol); @@ -57,6 +58,7 @@ public: static void composeTransitionInputEpsilonSymbol(std::deque<sax::Token>&, const std::variant<string::Epsilon, alphabet::Symbol>&); static void composeTransitionOutputSymbol(std::deque<sax::Token>&, const alphabet::Symbol& symbol); static void composeTransitionOutputEpsilonSymbol(std::deque<sax::Token>&, const std::variant<string::Epsilon, alphabet::Symbol>&); + static void composeTransitionOutputSymbolMultiple(std::deque<sax::Token>&, const std::vector<alphabet::Symbol>& symbols); static void composeTransitionInputString(std::deque<sax::Token>&, const string::LinearString& string); static void composeTransitionInputRegexp(std::deque<sax::Token>&, const regexp::RegExp& regexp); }; diff --git a/alib2data/src/automaton/common/OutputAlphabet.cpp b/alib2data/src/automaton/common/OutputAlphabet.cpp new file mode 100644 index 0000000000000000000000000000000000000000..26c04d186b9811d8fbcc6a92f5c571eb3c67d593 --- /dev/null +++ b/alib2data/src/automaton/common/OutputAlphabet.cpp @@ -0,0 +1,39 @@ +/* + * OutputAlphabet.cpp + * + * Created on: 9. 5. 2016 + * Author: Jakub Doupal + */ + +#include "OutputAlphabet.h" + +#include <algorithm> +#include "../AutomatonException.h" + +namespace automaton { + +const std::set<alphabet::Symbol>& OutputAlphabet::getOutputAlphabet() const { + return outputAlphabet; +} + +bool OutputAlphabet::addOutputSymbol(alphabet::Symbol symbol) { + return outputAlphabet.insert(std::move(symbol)).second; +} + +void OutputAlphabet::addOutputSymbols(std::set<alphabet::Symbol> symbols) { + return outputAlphabet.insert(std::make_set_move_iterator(symbols.begin()), std::make_set_move_iterator(symbols.end())); +} + +void OutputAlphabet::setOutputAlphabet(std::set<alphabet::Symbol> newSymbols) { + std::set<alphabet::Symbol> removed; + std::set_difference(outputAlphabet.begin(), outputAlphabet.end(), newSymbols.begin(), newSymbols.end(), std::inserter(removed, removed.end())); + + for(const alphabet::Symbol& removedSymbol : removed) { + removeOutputSymbol(removedSymbol); + } + + outputAlphabet = std::move(newSymbols); +} + +} /* namespace automaton */ + diff --git a/alib2data/src/automaton/common/OutputAlphabet.h b/alib2data/src/automaton/common/OutputAlphabet.h new file mode 100644 index 0000000000000000000000000000000000000000..5f7c4a664ec9e0b8d3edaa2b78f531a5ad82e87f --- /dev/null +++ b/alib2data/src/automaton/common/OutputAlphabet.h @@ -0,0 +1,63 @@ +/* + * OutputAlphabet.h + * + * Created on: 9. 5. 2016 + * Author: Jakub Doupal + */ + +#ifndef OUTPUT_ALPHABET_H_ +#define OUTPUT_ALPHABET_H_ + +#include <set> +#include "../../alphabet/Symbol.h" + + +namespace automaton { + +/** + * Abstract base class for all translation automata. Contains common elements of automata. + */ +class OutputAlphabet { +protected: + std::set<alphabet::Symbol> outputAlphabet; +public: + /** + * Adds output symbol to output alphabet. + * @param symbol Symbol to add + * @throws AutomatonException when symbol already exists + */ + bool addOutputSymbol(alphabet::Symbol symbol); + + /** + * Adds output symbols to output alphabet. + * @param symbol Symbol to add + * @throws AutomatonException when symbol already exists + */ + void addOutputSymbols(std::set<alphabet::Symbol> symbols); + + /** + * Sets output symbols of the automaton. + * @param symbols Symbols to set + * @throws AutomatonException when symbol already exists + */ + void setOutputAlphabet(std::set<alphabet::Symbol> symbols); + + /** + * Removes output symbol from the output alphabet. + * @param symbol Symbol to remove + * @throws AutomatonException when symbol is not present in output alphabet + * or when symbol is part of the transition + */ + virtual bool removeOutputSymbol(const alphabet::Symbol& symbol) = 0; + + /** + * @return the output alphabet + */ + const std::set<alphabet::Symbol>& getOutputAlphabet() const; + +}; + +} /* namespace automaton */ + +#endif /* OUTPUT_ALPHABET_H_ */ +