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

#pragma once

#include <tree/unranked/UnrankedPattern.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::UnrankedPattern < SymbolType > > {
	static tree::UnrankedPattern < SymbolType > parse ( std::istream & input );
	static bool first ( std::istream & input );
	static void compose ( std::ostream & output, const tree::UnrankedPattern < SymbolType > & tree );
};

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

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

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

	return tree::UnrankedPattern < SymbolType > ( alphabet::WildcardSymbol::instance < SymbolType > ( ), content );
}

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

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

} /* namespace core */

