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

#pragma once

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

template<class SymbolType >
tree::UnrankedNonlinearPattern < SymbolType > stringApi < tree::UnrankedNonlinearPattern < SymbolType > >::parse ( std::istream & input ) {
	tree::TreeFromStringLexer::Token token = tree::TreeFromStringLexer::next ( input );
	if ( token.type != tree::TreeFromStringLexer::TokenType::UNRANKED_NONLINEAR_PATTERN )
		throw exception::CommonException ( "Unrecognised UNRANKED_NONLINEAR_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::UnrankedNonlinearPattern < SymbolType > ( alphabet::WildcardSymbol::instance < SymbolType > ( ), nonlinearVariables, content );
}

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

template<class SymbolType >
void stringApi < tree::UnrankedNonlinearPattern < SymbolType > >::compose ( std::ostream &, const tree::UnrankedNonlinearPattern < SymbolType > & ) {
	throw exception::CommonException ( "Unimplemented." );
}

} /* namespace core */

