/* **********************************************
 * Duale Hochschule Baden-Württemberg Karlsruhe
 * Prof. Dr. Jörn Eisenbiegler
 * 
 * Vorlesung Übersetzerbau
 * Praxis AS-Scanner tabellengesteuert 1
 * 
 * **********************************************
 */

package de.dhbw.compiler.namenscanner;

import java.io.IOException;
import java.io.Reader;

import de.dhbw.compiler.namenscanner.Token;

public class NamenScanner {
		
	private final int ignore = -2;
	
	private Reader in = null;
	private StringBuffer text = new StringBuffer();
	
	private enum NamenState { WS, P, PE, PET, PETR, PETRA, PETE, PETER, A, AN, ANN, ANNA, EOF};
	
	private NamenState state = NamenState.WS;
	private int tokentype = Token.INVALID;

	
	public NamenScanner(Reader input) {
		this.in = input;
	}
	
	private Token step(int c, NamenState newState, boolean create, int newTokenType) {
		Token res = null;
		if (create) {
			res = new Token(tokentype, text.toString());
			text = new StringBuffer();
		}
		if (c!=ignore) {
			text.append((char)c);
		}
		state = newState;
		tokentype = newTokenType;
		return res;
	}
	
	public Token nextToken() throws Exception {
		Token token = null;
		while (token == null) {
			char c = nextCharacter();

			// peter
			switch (state) {
				case WS:
					switch (c) {
						case (char) -1: token = step(ignore, NamenState.EOF, false, Token.EOF); break;
						case ' ': case '\t': case '\n': case '\r': token = step(ignore, NamenState.WS, false, Token.INVALID); break;
						case 'p': token = step(c, NamenState.P, false, Token.INVALID); break;
						case 'a': token = step(c, NamenState.A, false, Token.INVALID); break;
						default:
							if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {
								token = step(c, NamenState.WS, false, Token.INVALID);
							} else {
								throw new Exception("Unexpected character: " + c + " (" + (int) c + ")");
							} break;
					} break;
				case P:
					switch (c) {
						case (char) -1: token = step(ignore, NamenState.EOF, false, Token.EOF); break;
						case ' ': case '\t': case '\n': case '\r': token = step(ignore, NamenState.WS, false, Token.INVALID); break;
						case '': token = step(c, NamenState.P, false, Token.INVALID); break;
						case 'A': token = step(c, NamenState.A, false, Token.INVALID); break;
						default:
							if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) {
								token = step(c, NamenState.WS, false, Token.INVALID);
							} else {
								throw new Exception("Unexpected character: " + c + " (" + (int) c + ")");
							} break;
					} break;
				case PE:
					break;
				case PET:
					break;
				case PETR:
					break;
				case PETRA:
					break;
				case PETE:
					break;
				case PETER:
					break;
				case A:
					break;
				case AN:
					break;
				case ANN:
					break;
				case ANNA:
					break;
				case EOF:
					break;
			}
		}
		return token;
	}

	private char nextCharacter() {
		try {
			return (char) in.read();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
