/*
 * RankedPattern.h
 *
 * Created on: Sep 27, 2017
 * Author: Jan Travnicek
 */

#pragma once

#include <tree/ranked/RankedPattern.h>
#include <core/stringApi.hpp>

#include <tree/TreeFromStringLexer.h>

#include <tree/string/common/TreeFromStringParserCommon.h>
#include <tree/string/common/TreeToStringComposerCommon.h>

namespace core {

template<class SymbolType >
struct stringApi < tree::RankedPattern < SymbolType > > {
	static tree::RankedPattern < SymbolType > parse ( std::istream & input );
	static bool first ( std::istream & input );
	static void compose ( std::ostream & output, const tree::RankedPattern < SymbolType > & tree );
};

template<class SymbolType >
tree::RankedPattern < SymbolType > stringApi < tree::RankedPattern < SymbolType > >::parse ( std::istream & input ) {
	tree::TreeFromStringLexer::Token token = tree::TreeFromStringLexer::next ( input );
	if ( token.type != tree::TreeFromStringLexer::TokenType::RANKED_PATTERN )
		throw exception::CommonException ( "Unrecognised RANKED_PATTERN token." );

	ext::set < common::ranked_symbol < SymbolType > > nonlinearVariables;
	bool isPattern = false;

	ext::tree < common::ranked_symbol < SymbolType > > content = tree::TreeFromStringParserCommon::parseRankedContent < SymbolType > ( input, isPattern, nonlinearVariables );
	if ( ! isPattern || !nonlinearVariables.empty ( ) )
		throw exception::CommonException ( "Invalid input" );

	return tree::RankedPattern < SymbolType > ( alphabet::WildcardSymbol::instance < common::ranked_symbol < SymbolType > > ( ), content );
}

template<class SymbolType >
bool stringApi < tree::RankedPattern < SymbolType > >::first ( std::istream & input ) {
	tree::TreeFromStringLexer::Token token = tree::TreeFromStringLexer::next ( input );
	bool res = token.type == tree::TreeFromStringLexer::TokenType::RANKED_PATTERN;
	tree::TreeFromStringLexer::putback ( input, token );
	return res;
}

template<class SymbolType >
void stringApi < tree::RankedPattern < SymbolType > >::compose ( std::ostream & output, const tree::RankedPattern < SymbolType > & tree ) {
	output << "RANKED_PATTERN ";
	tree::TreeToStringComposerCommon::compose ( output, tree.getSubtreeWildcard ( ), tree.getContent ( ) );
}

} /* namespace core */

