Token.java

/*
* Generated by: CongoCC Parser Generator. Token.java
*/
package de.schegge.rosinante.parser;

import de.schegge.rosinante.parser.ast.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class Token implements CharSequence, Node.TerminalNode { 

    public enum TokenType implements Node.NodeType { 
        EOF, ENUM("enum", true, false), SYNTAX("syntax"), IMPORT("import"), WEAK("weak"),
        PUBLIC("public"), PACKAGE("package"), OPTION("option"), MESSAGE("message"),
        REPEATED("repeated"), OPTIONAL("optional"), LPAREN("("), RPAREN(")"), LBRACE("{"),
        RBRACE("}"), LBRACKET("["), RBRACKET("]"), SEMICOLON(";"), COLON(":"), COMMA(","),
        DOT("."), DOUBLE("double"), FLOAT("float"), INT32("int32"), INT64("int64"),
        UINT32("uint32"), UINT64("uint64"), SINT32("sint32"), SINT64("sint64"), FIXED32("fixed32"),
        FIXED64("fixed64"), SFIXED32("sfixed32"), SFIXED64("sfixed64"), STRING("string"),
        BYTES("bytes"), BOOL("bool"), TRUE("true"), FALSE("false"), ZERO("0"), ASSIGN("="),
        _MINUS("-"), _PLUS("+"), _SLASH("/"), WHITESPACE, SINGLE_LINE_COMMENT, INTEGER_LITERAL,
        OCT_LITERAL, HEX_LITERAL, IDENTIFIER, FULL_IDENTIFIER, TYPE_IDENTIFIER, STRING_LITERAL,
        OPTION_NAME, DUMMY, INVALID;

        TokenType() { 
        }

        TokenType(String literalString) { 
            this.literalString = literalString;
        }

        private String literalString;

        public String getLiteralString() { 
            return literalString;
        }

        private boolean contextualKeyword, ignoreCase;

        TokenType(String literalString, boolean contextualKeyword, boolean ignoreCase) { 
            this.literalString = literalString;
            this.contextualKeyword = contextualKeyword;
            this.ignoreCase = ignoreCase;
        }

        public boolean isContextualKeyword() { 
            return contextualKeyword;
        }

        public boolean isIgnoreCase() { 
            return ignoreCase;
        }

        public boolean isUndefined() { 
            return this == DUMMY;
        }

        public boolean isInvalid() { 
            return this == INVALID;
        }

        public boolean isEOF() { 
            return this == EOF;
        }
    }

    private TokenSource tokenSource;
    private TokenType type = TokenType.DUMMY;
    private int beginOffset;
    private int endOffset;
    private boolean unparsed;
    private Node parent;
    private String cachedImage;

    /**
    * If cachedImage is set, then the various methods
    * that implement #java.lang.CharSequence use that string
    * rather than what is returned by getSource()
    */
    public void setCachedImage(String image) { 
        this.cachedImage = image;
    }

    public String getCachedImage() { 
        return this.cachedImage;
    }

    public void truncate(int amount) { 
        int newEndOffset = Math.max(getBeginOffset(), getEndOffset() - amount);
        setEndOffset(newEndOffset);
        if (cachedImage != null) { 
            cachedImage = cachedImage.substring(0, newEndOffset - getBeginOffset());
        }
    }

    /**
    * It would be extremely rare that an application
    * programmer would use this method. It needs to
    * be public because it is part of the de.schegge.rosinante.parser.Node interface.
    */
    public void setBeginOffset(int beginOffset) { 
        this.beginOffset = beginOffset;
    }

    /**
    * It would be extremely rare that an application
    * programmer would use this method. It needs to
    * be public because it is part of the de.schegge.rosinante.parser.Node interface.
    */
    public void setEndOffset(int endOffset) { 
        this.endOffset = endOffset;
    }

    /**
    * @return the TokenSource object that handles
    * location info for the tokens.
    */
    public TokenSource getTokenSource() { 
        return tokenSource;
    }

    /**
    * @return the line of source which contains the token.
    * This can be useful in error reporting.
    */
    public String getSourceLine() { 
        return tokenSource.getLine(this);
    }

    /**
    * It should be exceedingly rare that an application
    * programmer needs to use this method.
    */
    public void setTokenSource(TokenSource tokenSource) { 
        this.tokenSource = tokenSource;
    }

    public boolean isInvalid() { 
        return getType().isInvalid();
    }

    /**
    * Return the TokenType of this Token object
    */
    @Override
    public TokenType getType() { 
        return type;
    }

    protected void setType(TokenType type) { 
        this.type = type;
    }

    /**
    * @return whether this Token represent actual input or was it inserted somehow?
    */
    public boolean isVirtual() { 
        return type == TokenType.EOF;
    }

    /**
    * @return Did we skip this token in parsing?
    */
    public boolean isSkipped() { 
        return false;
    }

    public int getBeginOffset() { 
        return beginOffset;
    }

    public int getEndOffset() { 
        return endOffset;
    }

    /**
    * @return the next _cached_ regular (i.e. parsed) token
    * or null
    */
    @Override
    public final Token getNext() { 
        return getNextParsedToken();
    }

    /**
    * @return the previous regular (i.e. parsed) token
    * or null
    */
    public final Token getPrevious() { 
        Token result = previousCachedToken();
        while (result != null && result.isUnparsed()) { 
            result = result.previousCachedToken();
        }
        return result;
    }

    /**
    * @return the next regular (i.e. parsed) token
    */
    private Token getNextParsedToken() { 
        Token result = nextCachedToken();
        while (result != null && result.isUnparsed()) { 
            result = result.nextCachedToken();
        }
        return result;
    }

    /**
    * @return the next token of any sort (parsed or unparsed or invalid)
    */
    public Token nextCachedToken() { 
        if (getType() == TokenType.EOF) return null;
        TokenSource tokenSource = getTokenSource();
        return tokenSource != null ? (Token) tokenSource.nextCachedToken(getEndOffset()) : null;
    }

    /**
    * @return the previous token of any sort (parsed or unparsed or invalid)
    */
    public Token previousCachedToken() { 
        if (getTokenSource() == null) return null;
        return (Token) getTokenSource().previousCachedToken(getBeginOffset());
    }

    Token getPreviousToken() { 
        return previousCachedToken();
    }

    /**
    * @return the SKIPped characters before this token
    */
    public String getPrecedingSkippedChars() { 
        Token prevToken = previousCachedToken();
        if (prevToken == null) return "";
        int prevTokenEnd = prevToken.getEndOffset();
        if (prevTokenEnd == this.getBeginOffset()) return "";
        return getTokenSource().subSequence(prevTokenEnd, this.getBeginOffset()).toString();
    }

    public Token replaceType(TokenType type) { 
        if (type == this.getType()) { 
            return this;
        }
        Token result = newToken(type, getTokenSource(), getBeginOffset(), getEndOffset());
        result.cachedImage = this.cachedImage;
        getTokenSource().cacheToken(result);
        return result;
    }

    public String getSource() { 
        if (type == TokenType.EOF) return "";
        TokenSource ts = getTokenSource();
        int beginOffset = getBeginOffset();
        int endOffset = getEndOffset();
        return ts == null || beginOffset <= 0 && endOffset <= 0 ? null : ts.getText(beginOffset, endOffset);
    }

    protected Token() { 
    }

    protected Token(TokenType type, TokenSource tokenSource, int beginOffset, int endOffset) { 
        this.type = type;
        this.tokenSource = tokenSource;
        this.beginOffset = beginOffset;
        this.endOffset = endOffset;
    }

    public boolean isUnparsed() { 
        return unparsed;
    }

    public void setUnparsed(boolean unparsed) { 
        this.unparsed = unparsed;
    }

    /**
    * @return An iterator of the tokens preceding this one.
    */
    public Iterator<Token> precedingTokens() { 
        return new Iterator<Token>() { 

            Token currentPoint = Token.this;

            public boolean hasNext() { 
                return currentPoint.previousCachedToken() != null;
            }

            public Token next() { 
                Token previous = currentPoint.previousCachedToken();
                if (previous == null) throw new java.util.NoSuchElementException("No previous token!");
                return currentPoint = previous;
            }
        };
    }

    /**
    * @return a list of the unparsed tokens preceding this one in the order they appear in the input
    */
    public List<Token> precedingUnparsedTokens() { 
        List<Token> result = new ArrayList<>();
        Token t = this.previousCachedToken();
        while (t != null && t.isUnparsed()) { 
            result.add(t);
            t = t.previousCachedToken();
        }
        Collections.reverse(result);
        return result;
    }

    /**
    * @return An iterator of the (cached) tokens that follow this one.
    */
    public Iterator<Token> followingTokens() { 
        return new java.util.Iterator<Token>() { 

            Token currentPoint = Token.this;

            public boolean hasNext() { 
                return currentPoint.nextCachedToken() != null;
            }

            public Token next() { 
                Token next = currentPoint.nextCachedToken();
                if (next == null) throw new java.util.NoSuchElementException("No next token!");
                return currentPoint = next;
            }
        };
    }

    public void copyLocationInfo(Token from) { 
        setTokenSource(from.getTokenSource());
        setBeginOffset(from.getBeginOffset());
        setEndOffset(from.getEndOffset());
    }

    public void copyLocationInfo(Token start, Token end) { 
        setTokenSource(start.getTokenSource());
        if (tokenSource == null) setTokenSource(end.getTokenSource());
        setBeginOffset(start.getBeginOffset());
        setEndOffset(end.getEndOffset());
    }

    /**
    * A constructor for "synthetic" tokens, that were not vended by
    * a XXXLexer object.
    */
    public static Token newToken(TokenType type) { 
        Token result = newToken(type, null, 0, 0);
        return result;
    }

    /**
    * A constructor for "synthetic" tokens, that were not vended by
    * a XXXLexer object.
    */
    public static Token newToken(TokenType type, String image) { 
        Token result = newToken(type);
        result.setCachedImage(image);
        return result;
    }

    /**
    * This is the factory method used by the internal machinery to
    * instantiate a new token.
    */
    public static Token newToken(TokenType type, TokenSource tokenSource, int beginOffset, int endOffset) { 
        switch(type) { 
            case BYTES : 
                return new FieldType(TokenType.BYTES, tokenSource, beginOffset, endOffset);
            case ZERO : 
                return new ZERO(TokenType.ZERO, tokenSource, beginOffset, endOffset);
            case INTEGER_LITERAL : 
                return new INTEGER_LITERAL(TokenType.INTEGER_LITERAL, tokenSource, beginOffset, endOffset);
            case UINT32 : 
                return new FieldType(TokenType.UINT32, tokenSource, beginOffset, endOffset);
            case OPTIONAL : 
                return new KeyWord(TokenType.OPTIONAL, tokenSource, beginOffset, endOffset);
            case SINT64 : 
                return new FieldType(TokenType.SINT64, tokenSource, beginOffset, endOffset);
            case HEX_LITERAL : 
                return new HEX_LITERAL(TokenType.HEX_LITERAL, tokenSource, beginOffset, endOffset);
            case PACKAGE : 
                return new KeyWord(TokenType.PACKAGE, tokenSource, beginOffset, endOffset);
            case SEMICOLON : 
                return new Delimiter(TokenType.SEMICOLON, tokenSource, beginOffset, endOffset);
            case WHITESPACE : 
                return new Whitespace(TokenType.WHITESPACE, tokenSource, beginOffset, endOffset);
            case SFIXED64 : 
                return new FieldType(TokenType.SFIXED64, tokenSource, beginOffset, endOffset);
            case ENUM : 
                return new ConextualKeyWord(TokenType.ENUM, tokenSource, beginOffset, endOffset);
            case OPTION_NAME : 
                return new OPTION_NAME(TokenType.OPTION_NAME, tokenSource, beginOffset, endOffset);
            case OPTION : 
                return new KeyWord(TokenType.OPTION, tokenSource, beginOffset, endOffset);
            case LPAREN : 
                return new Delimiter(TokenType.LPAREN, tokenSource, beginOffset, endOffset);
            case DOT : 
                return new Delimiter(TokenType.DOT, tokenSource, beginOffset, endOffset);
            case TRUE : 
                return new TRUE(TokenType.TRUE, tokenSource, beginOffset, endOffset);
            case RPAREN : 
                return new Delimiter(TokenType.RPAREN, tokenSource, beginOffset, endOffset);
            case OCT_LITERAL : 
                return new OCT_LITERAL(TokenType.OCT_LITERAL, tokenSource, beginOffset, endOffset);
            case UINT64 : 
                return new FieldType(TokenType.UINT64, tokenSource, beginOffset, endOffset);
            case SINT32 : 
                return new FieldType(TokenType.SINT32, tokenSource, beginOffset, endOffset);
            case RBRACE : 
                return new Delimiter(TokenType.RBRACE, tokenSource, beginOffset, endOffset);
            case PUBLIC : 
                return new KeyWord(TokenType.PUBLIC, tokenSource, beginOffset, endOffset);
            case LBRACE : 
                return new Delimiter(TokenType.LBRACE, tokenSource, beginOffset, endOffset);
            case FLOAT : 
                return new FieldType(TokenType.FLOAT, tokenSource, beginOffset, endOffset);
            case INT32 : 
                return new FieldType(TokenType.INT32, tokenSource, beginOffset, endOffset);
            case ASSIGN : 
                return new ASSIGN(TokenType.ASSIGN, tokenSource, beginOffset, endOffset);
            case FIXED32 : 
                return new FieldType(TokenType.FIXED32, tokenSource, beginOffset, endOffset);
            case SYNTAX : 
                return new KeyWord(TokenType.SYNTAX, tokenSource, beginOffset, endOffset);
            case FULL_IDENTIFIER : 
                return new FULL_IDENTIFIER(TokenType.FULL_IDENTIFIER, tokenSource, beginOffset, endOffset);
            case WEAK : 
                return new KeyWord(TokenType.WEAK, tokenSource, beginOffset, endOffset);
            case IMPORT : 
                return new KeyWord(TokenType.IMPORT, tokenSource, beginOffset, endOffset);
            case MESSAGE : 
                return new KeyWord(TokenType.MESSAGE, tokenSource, beginOffset, endOffset);
            case SINGLE_LINE_COMMENT : 
                return new SingleLineComment(TokenType.SINGLE_LINE_COMMENT, tokenSource, beginOffset, endOffset);
            case DOUBLE : 
                return new FieldType(TokenType.DOUBLE, tokenSource, beginOffset, endOffset);
            case IDENTIFIER : 
                return new IDENTIFIER(TokenType.IDENTIFIER, tokenSource, beginOffset, endOffset);
            case COMMA : 
                return new Delimiter(TokenType.COMMA, tokenSource, beginOffset, endOffset);
            case INT64 : 
                return new FieldType(TokenType.INT64, tokenSource, beginOffset, endOffset);
            case REPEATED : 
                return new KeyWord(TokenType.REPEATED, tokenSource, beginOffset, endOffset);
            case LBRACKET : 
                return new Delimiter(TokenType.LBRACKET, tokenSource, beginOffset, endOffset);
            case RBRACKET : 
                return new Delimiter(TokenType.RBRACKET, tokenSource, beginOffset, endOffset);
            case COLON : 
                return new Delimiter(TokenType.COLON, tokenSource, beginOffset, endOffset);
            case FIXED64 : 
                return new FieldType(TokenType.FIXED64, tokenSource, beginOffset, endOffset);
            case TYPE_IDENTIFIER : 
                return new TYPE_IDENTIFIER(TokenType.TYPE_IDENTIFIER, tokenSource, beginOffset, endOffset);
            case BOOL : 
                return new FieldType(TokenType.BOOL, tokenSource, beginOffset, endOffset);
            case STRING : 
                return new FieldType(TokenType.STRING, tokenSource, beginOffset, endOffset);
            case FALSE : 
                return new FALSE(TokenType.FALSE, tokenSource, beginOffset, endOffset);
            case STRING_LITERAL : 
                return new STRING_LITERAL(TokenType.STRING_LITERAL, tokenSource, beginOffset, endOffset);
            case SFIXED32 : 
                return new FieldType(TokenType.SFIXED32, tokenSource, beginOffset, endOffset);
            case INVALID : 
                return new InvalidToken(tokenSource, beginOffset, endOffset);
            default : 
                return new Token(type, tokenSource, beginOffset, endOffset);
        }
    }

    public Node getParent() { 
        return parent;
    }

    public void setParent(Node parent) { 
        this.parent = parent;
    }

    public boolean isEmpty() { 
        return length() == 0;
    }

    public int length() { 
        if (cachedImage != null) return cachedImage.length();
        return endOffset - beginOffset;
    }

    public CharSequence subSequence(int start, int end) { 
        if (cachedImage != null) return cachedImage.substring(start, end);
        return getTokenSource().subSequence(beginOffset + start, beginOffset + end);
    }

    public char charAt(int offset) { 
        if (cachedImage != null) return cachedImage.charAt(offset);
        TokenSource ts = getTokenSource();
        return ts != null ? ts.charAt(beginOffset + offset) : this.getType().getLiteralString().charAt(offset);
    }

    /**
    * @deprecated Typically use just toString() or occasionally getCachedImage()
    */
    @Deprecated
    public String getImage() { 
        return toString();
    }

    @Override
    public String toString() { 
        if (cachedImage != null) { 
            return cachedImage;
        }
        String result = getSource();
        if (result == null) { 
            result = getType().getLiteralString();
        }
        return result;
    }
}