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

#ifndef _STRING_RANKED_TREE_H_
#define _STRING_RANKED_TREE_H_

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

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

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

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

} /* namespace core */

#endif /* _STRING_RANKED_TREE_H_ */
