/*
 * StringFromStringParser.cpp
 *
 *  Created on: Nov 23, 2013
 *      Author: Jan Travnicek
 */

#include "StringFromStringParser.h"
#include "../exception/AlibException.h"
#include "Epsilon.h"
#include "LinearString.h"
#include "CyclicString.h"
#include "../label/StringLabel.h"
#include "../label/Label.h"
#include "../alphabet/LabeledSymbol.h"

namespace string {

StringFromStringParser::StringFromStringParser(std::istream& input) : m_StringLexer(input), m_SymbolParser(input)  {

}

String StringFromStringParser::parse() {
	return parse(std::set<FEATURES>({FEATURES::LINEAR, FEATURES::CYCLIC, FEATURES::EPSILON}));
}

String StringFromStringParser::parse(const std::set<FEATURES>& features) {
	StringFromStringLexer::Token token = m_StringLexer.token();
	if(token.type == StringFromStringLexer::TokenType::EPSILON) {
		if(!features.count(FEATURES::EPSILON)) throw exception::AlibException();
		return String(Epsilon());
	} else if(token.type == StringFromStringLexer::TokenType::LESS) {
		if(!features.count(FEATURES::CYCLIC)) throw exception::AlibException();
		std::vector<alphabet::Symbol> data = parseContent();
		if(token.type == StringFromStringLexer::TokenType::GREATER) {
			return String(CyclicString(data));
		} else {
			throw exception::AlibException();
		}
	} else if(token.type == StringFromStringLexer::TokenType::QUOTE) {
		if(!features.count(FEATURES::LINEAR)) throw exception::AlibException();
		std::vector<alphabet::Symbol> data = parseContent();
		if(token.type == StringFromStringLexer::TokenType::QUOTE) {
			return String(LinearString(data));
		} else {
			throw exception::AlibException();
		}
	} else {
		throw exception::AlibException();
	}
}

bool StringFromStringParser::first() {
	StringFromStringLexer::Token token = m_StringLexer.next().token();
	if(token.type == StringFromStringLexer::TokenType::EPSILON || token.type == StringFromStringLexer::TokenType::LESS || token.type == StringFromStringLexer::TokenType::QUOTE) {
		return true;
	} else {
		return false;
	}
}

bool StringFromStringParser::next() {
	StringFromStringLexer::Token token = m_StringLexer.next().token();
	if(token.type == StringFromStringLexer::TokenType::EPSILON || token.type == StringFromStringLexer::TokenType::LESS || token.type == StringFromStringLexer::TokenType::QUOTE || token.type == StringFromStringLexer::TokenType::GREATER) {
		return true;
	} else {
		return false;
	}
}

bool StringFromStringParser::last() {
	StringFromStringLexer::Token token = m_StringLexer.next().token();
	if(token.type == StringFromStringLexer::TokenType::TEOF) {
		return true;
	} else {
		return false;
	}
}

std::vector<alphabet::Symbol> StringFromStringParser::parseContent() {
	std::vector<alphabet::Symbol> data;
	do {
		next() || m_SymbolParser.next() || m_SymbolParser.m_LabelParser.next();

		StringFromStringLexer::Token token = m_StringLexer.token();
		if(token.type == StringFromStringLexer::TokenType::GREATER || token.type == StringFromStringLexer::TokenType::QUOTE)
			return data;
		data.push_back(m_SymbolParser.parse());
	} while(true);
}

} /* namespace string */