Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
SinglePopNPDA.cpp 7.30 KiB
/*
 * SinglePopNPDA.cpp
 *
 *  Created on: Apr 10, 2013
 *      Author: martin
 */

#include "SinglePopNPDA.h"
#include "../../std/map.hpp"
#include "../AutomatonException.h"
#include <algorithm>

namespace automaton {

AutomatonBase* SinglePopNPDA::clone() const {
	return new SinglePopNPDA(*this);
}

AutomatonBase* SinglePopNPDA::plunder() && {
	return new SinglePopNPDA(std::move(*this));
}

bool SinglePopNPDA::removeState(const State& state) {
	if (initialStates.find(state) != initialStates.end()) {
		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 (std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, alphabet::Symbol>, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >::const_iterator transition = transitions.begin(); transition != transitions.end(); transition++) {
		if (state == std::get<0>(transition->first))
			throw AutomatonException("State \"" + (std::string) state.getName() + "\" is used in transition.");
		for(std::set<std::pair<State, std::vector<alphabet::Symbol> > >::iterator target = transition->second.begin(); target != transition->second.end(); target++) {
			if(target->first == state)
				throw AutomatonException("State \"" + (std::string) state.getName() + "\" is used in transition.");
		}
	}

	return states.erase(state);
}

bool SinglePopNPDA::removeInputSymbol(const alphabet::Symbol& symbol) {
	for (std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, alphabet::Symbol>, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >::const_iterator transition = transitions.begin(); transition != transitions.end(); transition++) {
		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 SinglePopNPDA::removeStackSymbol(const alphabet::Symbol& symbol) {
	for (std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, alphabet::Symbol>, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >::const_iterator transition = transitions.begin(); transition != transitions.end(); transition++) {
		if (symbol == std::get<2>(transition->first))
			throw AutomatonException("Stack symbol \"" + (std::string) symbol + "\" is used in transition.");

		for (std::set<std::pair<State, std::vector<alphabet::Symbol> > >::const_iterator target = transition->second.begin(); target != transition->second.end(); target++) {
			if (std::find(target->second.begin(), target->second.end(), symbol) != target->second.end())
				throw AutomatonException("Stack symbol \"" + (std::string) symbol + "\" is used in transition.");
		}
	}

	if(initialSymbols.find(symbol) != initialSymbols.end()) {
		throw AutomatonException("Stack symbol \"" + (std::string) symbol + "\" is start symbol.");
	}

	return stackAlphabet.erase(symbol);
}
bool SinglePopNPDA::addTransition(const State& from, const std::variant<string::Epsilon, alphabet::Symbol>& input, const alphabet::Symbol& pop, const State& to, const std::vector<alphabet::Symbol>& push) {
	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.");
	}

	if (stackAlphabet.find(pop) == stackAlphabet.end()) {
		throw AutomatonException("Stack symbol \"" + (std::string) pop + "\" doesn't exist.");
	}

	for(std::vector<alphabet::Symbol>::const_iterator pushSymbol = push.begin(); pushSymbol != push.end(); pushSymbol++) {
		if (stackAlphabet.find(*pushSymbol) == stackAlphabet.end()) {
			throw AutomatonException("Stack symbol \"" + (std::string) *pushSymbol + "\" doesn't exist.");
		}
	}

	std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, alphabet::Symbol> key(from, input, pop);
	std::pair<automaton::State, std::vector<alphabet::Symbol> > value = std::make_pair(to, push);
	
	return transitions[key].insert(value).second;
}

bool SinglePopNPDA::addTransition(const State& from, const alphabet::Symbol& input, const alphabet::Symbol& pop, const State& to, const std::vector<alphabet::Symbol>& push) {
	std::variant<string::Epsilon, alphabet::Symbol> inputVariant;
	inputVariant.set<alphabet::Symbol>(input);
	return addTransition(from, inputVariant, pop, to, push);
}

bool SinglePopNPDA::addTransition(const State& from, const alphabet::Symbol& pop, const State& to, const std::vector<alphabet::Symbol>& push) {
	std::variant<string::Epsilon, alphabet::Symbol> inputVariant;
	inputVariant.set<string::Epsilon>(string::Epsilon::EPSILON);
	return addTransition(from, inputVariant, pop, to, push);
}

bool SinglePopNPDA::removeTransition(const State& from, const std::variant<string::Epsilon, alphabet::Symbol>& input, const alphabet::Symbol& pop, const State& to, const std::vector<alphabet::Symbol>& push) {
	std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, alphabet::Symbol> key(from, input, pop);
	std::pair<automaton::State, std::vector<alphabet::Symbol> > value = std::make_pair(to, push);
	
	return transitions[key].erase(value);
}

bool SinglePopNPDA::removeTransition(const State& from, const alphabet::Symbol& input, const alphabet::Symbol& pop, const State& to, const std::vector<alphabet::Symbol>& push) {
	std::variant<string::Epsilon, alphabet::Symbol> inputVariant;
	inputVariant.set<alphabet::Symbol>(input);
	return removeTransition(from, inputVariant, pop, to, push);
}

bool SinglePopNPDA::removeTransition(const State& from, const alphabet::Symbol& pop, const State& to, const std::vector<alphabet::Symbol>& push) {
	std::variant<string::Epsilon, alphabet::Symbol> inputVariant;
	inputVariant.set<string::Epsilon>(string::Epsilon::EPSILON);
	return removeTransition(from, inputVariant, pop, to, push);
}

const std::map<std::tuple<State, std::variant<string::Epsilon, alphabet::Symbol>, alphabet::Symbol>, std::set<std::pair<State, std::vector<alphabet::Symbol> > > >& SinglePopNPDA::getTransitions() const {
	return transitions;
}

bool SinglePopNPDA::operator==(const AutomatonBase& other) const {
	return other == *this;
}

bool SinglePopNPDA::operator==(const SinglePopNPDA& other) const {
	return this->states == other.states && this->inputAlphabet == other.inputAlphabet && this->initialStates == other.initialStates && this->finalStates == other.finalStates && this->stackAlphabet == other.stackAlphabet && this->initialSymbols == other.initialSymbols && this->transitions == other.transitions;
}

void SinglePopNPDA::operator>>(std::ostream& out) const {
	out << "(SinglePopNPDA"
		<< "states = " << states
		<< "inputAlphabet = " << inputAlphabet
		<< "initialStates = " << initialStates
		<< "finalStates = " << finalStates
		<< "stackAlphabet = " << stackAlphabet
		<< "initialSymbols = " << initialSymbols
		<< "transitions = " << transitions
		<< ")";
}

} /* namespace automaton */