// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.npc.util.expression.compile;

import java.text.ParseException;
import javax.annotation.Nonnull;

public class LexerContext<Token>
{
    private String expression;
    private int length;
    private int position;
    private Token token;
    private int tokenPosition;
    @Nonnull
    private StringBuilder tokenString;
    private double tokenNumber;
    
    public LexerContext() {
        this.tokenString = new StringBuilder(200);
    }
    
    public void init(@Nonnull final String expression) {
        this.expression = expression;
        this.length = expression.length();
        this.position = 0;
    }
    
    public void resetToken() {
        this.tokenPosition = this.position;
        this.tokenString.setLength();
    }
    
    public Token setToken(final Token token) {
        return this.token = token;
    }
    
    public String getExpression() {
        return this.expression;
    }
    
    public Token getToken() {
        return this.token;
    }
    
    public int getTokenPosition() {
        return this.tokenPosition;
    }
    
    @Nonnull
    public String getTokenString() {
        return this.tokenString.toString();
    }
    
    public double getTokenNumber() {
        return this.tokenNumber;
    }
    
    protected char nextChar(final String error) throws ParseException {
        ++this.position;
        if (this.position >= this.length) {
            throw new ParseException(error, this.tokenPosition);
        }
        return this.expression.charAt(this.position);
    }
    
    protected boolean haveChar() {
        return this.position < this.length;
    }
    
    protected char currentChar() {
        return this.expression.charAt(this.position);
    }
    
    protected char peekChar(final char defaultChar) {
        return (this.position < this.length) ? this.currentChar() : defaultChar;
    }
    
    protected char peekChar() {
        return (this.position < this.length) ? this.currentChar() : '\0';
    }
    
    protected char peekChar(final int lookahead, final char defaultChar) {
        return (this.position + lookahead < this.length) ? this.expression.charAt(this.position + lookahead) : defaultChar;
    }
    
    protected char peekChar(final int lookahead) {
        return (this.position + lookahead < this.length) ? this.expression.charAt(this.position + lookahead) : '\0';
    }
    
    protected boolean eatWhiteSpace() {
        while (this.position < this.length && Character.isWhitespace(this.expression.charAt(this.position))) {
            ++this.position;
        }
        return this.position < this.length;
    }
    
    protected char addTokenCharacter(final char ch) {
        this.tokenString.append(ch);
        ++this.position;
        return this.peekChar();
    }
    
    protected int getPosition() {
        return this.position;
    }
    
    protected void setPosition(final int position) {
        this.position = position;
    }
    
    protected void adjustPosition(final int newPosition) {
        if (newPosition < this.position) {
            this.tokenString.setLength();
        }
        this.position = newPosition;
    }
    
    protected boolean isNumber(final char firstLetter) {
        return Character.isDigit(firstLetter) || (firstLetter == '.' && Character.isDigit(this.peekChar(1, '\0')));
    }
    
    protected void parseNumber(final char firstChar) throws ParseException {
        char ch = firstChar;
        this.tokenNumber = 0.0;
        ch = this.copyDigits(ch);
        if (this.position < this.length && ch == '.') {
            this.tokenString.append(ch);
            ++this.position;
            if (!Character.isDigit(this.currentChar())) {
                throw new ParseException("Invalid number format", this.tokenPosition);
            }
            ch = this.copyDigits(ch);
        }
        if (this.position < this.length && (ch == 'e' || ch == 'E')) {
            this.tokenString.append(ch);
            ch = this.nextChar("Invalid number format");
            if (ch == '-' || ch == '+') {
                this.tokenString.append(ch);
                ch = this.nextChar("Invalid number format");
            }
            if (!Character.isDigit(ch)) {
                throw new ParseException("Invalid number format", this.tokenPosition);
            }
            this.copyDigits(ch);
        }
        this.tokenNumber = Double.parseDouble(this.tokenString.toString());
    }
    
    private char copyDigits(char ch) {
        while (this.position < this.length) {
            ch = this.currentChar();
            if (!Character.isDigit(ch)) {
                break;
            }
            this.tokenString.append(ch);
            ++this.position;
        }
        return ch;
    }
    
    protected void parseIdent(final char firstLetter) {
        this.tokenString.append(firstLetter);
        ++this.position;
        while (this.position < this.length && (Character.isLetterOrDigit(this.currentChar()) || this.currentChar() == '_')) {
            this.tokenString.append(this.currentChar());
            ++this.position;
        }
    }
    
    protected void parseString(final char delimiter) throws ParseException {
        this.tokenPosition = this.position;
        for (char ch = this.nextChar("Unterminated string"); ch != delimiter; ch = this.nextChar("Unterminated string")) {
            this.tokenString.append((ch != '\\') ? ch : this.nextChar("Unterminated string"));
        }
        ++this.position;
    }
}
