package com.christophdietze.jack.shared.pgn;
import java.util.ArrayList;
import java.util.List;
import com.christophdietze.jack.shared.pgn.PgnToken.CommentToken;
import com.christophdietze.jack.shared.pgn.PgnToken.StringToken;
import com.christophdietze.jack.shared.pgn.PgnToken.TokenType;
public class PgnLexer {
private List<PgnToken> tokens = new ArrayList<PgnToken>();
private int curIndex;
private String inputString;
private char c;
public PgnLexer() {
}
public void lex(String pgnString) {
resetLexer();
inputString = pgnString;
try {
nextChar();
while (true) {
while (isWhitespace()) {
nextChar();
}
lexToken();
}
} catch (EndOfStreamException ex) {
}
}
public List<PgnToken> getTokens() {
return tokens;
}
private void resetLexer() {
tokens.clear();
curIndex = -1;
inputString = null;
c = '\0';
}
private void nextChar() throws EndOfStreamException {
curIndex++;
if (curIndex >= inputString.length()) {
throw new EndOfStreamException();
}
c = inputString.charAt(curIndex);
}
private boolean isWhitespace() {
return c == ' ' || c == '\t' || c == '\n' || c == '\r';
}
private boolean isSymbolContinuationChar() {
return (!isWhitespace() && c != '.');
}
private void addToken(PgnToken token) {
tokens.add(token);
}
private void lexToken() throws EndOfStreamException {
TokenType tokenType = TokenType.getTypeForCharacter(c);
if (tokenType != null) {
// we have a single char token
addToken(new PgnToken.SimpleToken((tokenType)));
nextChar();
} else if (c == '{') {
nextChar();
lexComment();
} else if (c == '\"') {
nextChar();
lexString();
// } else if (Character.isDigit(c)) {
// lexInteger();
} else {
lexSymbol();
}
}
private void lexComment() throws EndOfStreamException {
int startIndex = curIndex;
while (c != '}') {
nextChar();
}
addToken(new CommentToken(inputString.substring(startIndex, curIndex)));
nextChar();
}
private void lexString() throws EndOfStreamException {
int startIndex = curIndex;
while (c != '\"') {
nextChar();
}
addToken(new StringToken(inputString.substring(startIndex, curIndex)));
nextChar();
}
// private void lexInteger() throws EndOfStreamException {
// int startIndex = curIndex;
// try {
// while (!isWhitespace() && Character.isDigit(c)) {
// nextChar();
// }
// addToken(new PgnToken.IntegerToken(inputString.substring(
// startIndex,
// curIndex)));
// } catch (EndOfStreamException ex) {
// addToken(new PgnToken.IntegerToken(inputString.substring(
// startIndex,
// curIndex)));
// throw ex;
// }
// }
private void lexSymbol() throws EndOfStreamException {
int startIndex = curIndex;
try {
while (isSymbolContinuationChar()) {
nextChar();
}
addToken(new PgnToken.SymbolToken(inputString.substring(startIndex, curIndex)));
} catch (EndOfStreamException ex) {
addToken(new PgnToken.SymbolToken(inputString.substring(startIndex, curIndex)));
throw ex;
}
}
@SuppressWarnings("serial")
private static class EndOfStreamException extends Exception {
}
}