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

#include "TreeFromStringLexer.h"

namespace tree {

TreeFromStringLexer::Token TreeFromStringLexer::next ( std::istream & input ) {
	TreeFromStringLexer::Token token;

	token.type = TokenType::ERROR;
	token.value = "";
	token.raw = "";
	char character;

L0:
	character = input.get ( );
	if ( input.eof ( ) || character == EOF ) {
		token.type = TokenType::TEOF;
		return token;
	} else if ( ext::isspace ( character ) ) {
		token.raw += character;
		goto L0;
	} else if ( character == '#' ) {
		token.value += character;
		token.raw += character;
		goto L1;
	} else if ( character == '$' ) {
		token.raw += character;
		goto L3;
	} else if ( character == '|' ) {
		token.type = TokenType::BAR;
		token.value += character;
		token.raw += character;
		return token;
	} else if ( ( character >= '0' ) && ( character <= '9' ) ) {
		token.type = TokenType::RANK;
		token.value += character;
		token.raw += character;
		goto L2;
	} else if(input.clear (), input.unget(), input >> ext::string ( "RANKED_TREE" ) ) {
		token.type = TokenType::RANKED_TREE;
		token.value = "RANKED_TREE";
		token.raw += "RANKED_TREE";
		return token;
	} else if(input.clear(), input >> ext::string ( "RANKED_PATTERN" ) ) {
		token.type = TokenType::RANKED_PATTERN;
		token.value = "RANKED_PATTERN";
		token.raw += "RANKED_PATTERN";
		return token;
	} else if(input.clear(), input >> ext::string ( "RANKED_NONLINEAR_PATTERN" ) ) {
		token.type = TokenType::RANKED_NONLINEAR_PATTERN;
		token.value = "RANKED_NONLINEAR_PATTERN";
		token.raw += "RANKED_NONLINEAR_PATTERN";
		return token;
	} else if(input.clear(), input >> ext::string ( "UNRANKED_TREE" ) ) {
		token.type = TokenType::UNRANKED_TREE;
		token.value = "UNRANKED_TREE";
		token.raw += "UNRANKED_TREE";
		return token;
	} else if(input.clear(), input >> ext::string ( "UNRANKED_PATTERN" ) ) {
		token.type = TokenType::UNRANKED_PATTERN;
		token.value = "UNRANKED_PATTERN";
		token.raw += "UNRANKED_PATTERN";
		return token;
	} else if(input.clear(), input >> ext::string ( "UNRANKED_NONLINEAR_PATTERN" ) ) {
		token.type = TokenType::UNRANKED_NONLINEAR_PATTERN;
		token.value = "UNRANKED_NONLINEAR_PATTERN";
		token.raw += "UNRANKED_NONLINEAR_PATTERN";
		return token;
	} else {
		input.clear ( );
		putback ( input, token );
		token.raw = "";
		token.type = TokenType::ERROR;
		return token;
	}

L1:	character = input.get ( );

	if ( input.eof ( ) ) {
		token.type = TokenType::TEOF;
		return token;
	} else if ( character == 'S' ) {
		token.type = TokenType::SUBTREE_WILDCARD;
		token.value += character;
		token.raw += character;
		return token;
	} else {
		input.clear ( );
		input.unget ( );
		putback ( input, token );
		token.raw = "";
		token.type = TokenType::ERROR;
		return token;
	}

L2:	character = input.get ( );

	if ( input.eof ( ) ) {
		return token;
	} else if ( ( character >= '0' ) && ( character <= '9' ) ) {
		token.value += character;
		token.raw += character;
		goto L2;
	} else {
		input.clear ( );
		input.unget ( );
		return token;
	}

L3:	character = input.get ( );

	if ( input.eof ( ) ) {
		token.type = TokenType::TEOF;
		return token;
	} else if ( ( character >= 'A' ) && ( character <= 'Z' ) ) {
		token.type = TokenType::NONLINEAR_VARIABLE;
		token.value += character;
		token.raw += character;
		return token;
	} else {
		input.clear ( );
		input.unget ( );
		putback ( input, token );
		token.raw = "";
		token.type = TokenType::ERROR;
		return token;
	}
}

} /* namespace tree */
