Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
RegExp.cpp 3.95 KiB
/*
 * RegExp.cpp
 *
 *  Created on: Nov 23, 2013
 *      Author: Martin Zak
 */

#include "RegExp.h"
#include "../AlibException.h"
#include "RegExpEmpty.h"
#include "RegExpSymbol.h"

#include <iostream>
#include <algorithm>

#include "../std/set.hpp"

namespace regexp {

RegExp::RegExp() {
	this->regExp = new RegExpEmpty();
}

RegExp::RegExp(const std::set<alphabet::Symbol>& alphabet, const RegExpElement& regExp) : alphabet(alphabet) {
	this->regExp = NULL;
	setRegExp(regExp);
}

RegExp::RegExp(std::set<alphabet::Symbol>&& alphabet, RegExpElement&& regExp) : alphabet(std::move(alphabet)) {
	this->regExp = NULL;
	setRegExp(std::move(regExp));
}

RegExp::RegExp(const RegExpElement& regExp) {
	regExp.computeMinimalAlphabet(alphabet);
	this->regExp = NULL;
	setRegExp(regExp);
}

RegExp::RegExp(RegExpElement&& regExp) {
	regExp.computeMinimalAlphabet(alphabet);
	this->regExp = NULL;
	setRegExp(std::move(regExp));
}

RegExp::RegExp(const RegExp& other) : regExp(other.regExp->clone()), alphabet(other.alphabet) {
	this->regExp->attachRegExp(this);
}

RegExp::RegExp(RegExp&& other) noexcept : regExp(other.regExp), alphabet(std::move(other.alphabet) ) {
	this->regExp->attachRegExp(this);
	other.regExp = NULL;
}

RegExp& RegExp::operator=(const RegExp& other) {
	if (this == &other) {
		return *this;
	}

	*this = RegExp(other);

	return *this;
}

RegExp& RegExp::operator=(RegExp&& other) noexcept {
	std::swap(this->regExp, other.regExp);
	std::swap(this->alphabet, other.alphabet);
	return *this;
}
RegExp::~RegExp() noexcept {
	delete regExp;
}

const RegExpElement& RegExp::getRegExp() const {
	return *regExp;
}

RegExpElement& RegExp::getRegExp() {
	return *regExp;
}

void RegExp::setRegExp(const RegExpElement& regExp) {
	delete this->regExp;
	this->regExp = regExp.clone();
	if(!this->regExp->attachRegExp(this))
		throw alib::AlibException("Input symbols not in the alphabet.");
}

void RegExp::setRegExp(RegExpElement&& regExp) {
	delete this->regExp;
	this->regExp = std::move(regExp).plunder();
	if(!this->regExp->attachRegExp(this))
		throw alib::AlibException("Input symbols not in the alphabet.");
}

const std::set<alphabet::Symbol>& RegExp::getAlphabet() const {
	return alphabet;
}

bool RegExp::addSymbolToAlphabet(const alphabet::Symbol & symbol) {
	return alphabet.insert(symbol).second;
}

void RegExp::setAlphabet(const std::set<alphabet::Symbol> & symbols) {
	std::set<alphabet::Symbol> minimalAlphabet;
	this->regExp->computeMinimalAlphabet(minimalAlphabet);
	std::set<alphabet::Symbol> removedSymbols;
	std::set_difference(minimalAlphabet.begin(), minimalAlphabet.end(), symbols.begin(), symbols.end(), std::inserter(removedSymbols, removedSymbols.end()));

	if(removedSymbols.size() > 0)
		throw alib::AlibException("Input symbols are used.");

	this->alphabet = symbols;
}

bool RegExp::removeSymbolFromAlphabet(const alphabet::Symbol & symbol) {
	if(this->regExp->testSymbol(symbol))
		throw alib::AlibException("Input symbol \"" + (std::string) symbol + "\" is used.");
	
	return alphabet.erase(symbol);
}

bool RegExp::isEmpty() const {
	return regExp->isEmpty();
}

bool RegExp::containsEmptyString() const {
	return regExp->containsEmptyString();
}

std::ostream& operator <<(std::ostream& out, const RegExp& regExp) {
	out << "(RegExp " << *(regExp.regExp) << ")";
	return out;
}

bool RegExp::operator<(const RegExp& other) const {
	if(*(this->regExp) < *(other.regExp)) {
	  return true;
	} else if(*(this->regExp) > *(other.regExp)) {
	  return false;
	} else {
	  return this->alphabet < other.alphabet;
	}
}

bool RegExp::operator<=(const RegExp& other) const {
	return !(other > *this);
}

bool RegExp::operator==(const RegExp& other) const {
	return *(this->regExp) == *(other.regExp) && this->alphabet == other.alphabet;
}

bool RegExp::operator!=(const RegExp& other) const {
	return !(*this == other);
}

bool RegExp::operator>(const RegExp& other) const {
	return other < *this;
}

bool RegExp::operator>=(const RegExp& other) const {
	return !(*this < other);
}

} /* namespace regexp */