ThriftToken.java

package net.morimekta.providence.reflect.parser;

import net.morimekta.util.lexer.Token;

import javax.annotation.Nonnull;
import java.util.regex.Pattern;

public class ThriftToken extends Token<ThriftTokenType> {
    // Various symbols.
    public static final char kGenericStart  = '<';
    public static final char kGenericEnd    = '>';
    public static final char kMessageStart  = '{';
    public static final char kMessageEnd    = '}';
    public static final char kKeyValueSep   = ':';
    public static final char kFieldValueSep = '=';
    public static final char kParamsStart   = '(';
    public static final char kParamsEnd     = ')';
    public static final char kListStart     = '[';
    public static final char kListEnd       = ']';
    public static final char kLineSep1      = ',';
    public static final char kLineSep2      = ';';

    /**
     * Create a slice instance. The slice is only meant to be internal state
     * immutable, and not representing an immutable byte content.
     *
     * @param fb      The buffer to wrap.
     * @param off     The start offset to wrap.
     * @param len     The length to represent.
     * @param type    The token type represented.
     * @param lineNo  The current line number.
     * @param linePos The current line position.
     */
    public ThriftToken(char[] fb, int off, int len,
                       @Nonnull ThriftTokenType type, int lineNo, int linePos) {
        super(fb, off, len, type, lineNo, linePos);
    }

    public boolean isSymbol(char symbol) {
        return len == 1 && fb[off] == symbol;
    }

    /**
     * Parse token content as documentation.
     *
     * @return The documentation string.
     */
    public String parseDocumentation() {
        String        block   = toString().trim();
        String[]      lines   = block.split("\\r?\\n", Short.MAX_VALUE);
        StringBuilder builder = new StringBuilder();

        for (String line : lines) {
            builder.append(RE_BLOCK_LINE.matcher(line).replaceFirst(""));
            builder.append('\n');
        }
        return builder.toString().trim();
    }

    public boolean isFieldId() {
        return RE_FIELD_ID.matcher(this).matches();
    }

    public boolean isEnumValueId() {
        return RE_ENUM_ID.matcher(this).matches();
    }

    public boolean isInteger() {
        return RE_INTEGER.matcher(this).matches();
    }

    public boolean isReal() {
        return RE_REAL.matcher(this).matches();
    }

    public boolean isIdentifier() {
        return RE_IDENTIFIER.matcher(this).matches();
    }

    public boolean isQualifiedIdentifier() {
        return RE_QUALIFIED_IDENTIFIER.matcher(this).matches();
    }

    public boolean isDoubleQualifiedIdentifier() {
        return RE_DOUBLE_QUALIFIED_IDENTIFIER.matcher(this).matches();
    }

    public boolean isReferenceIdentifier() {
        return RE_REFERENCE_IDENTIFIER.matcher(this).matches();
    }

    // ---- INTERNAL ----

    private static final Pattern RE_IDENTIFIER                  = Pattern.compile(
            "[_a-zA-Z][_a-zA-Z0-9]*");
    private static final Pattern RE_QUALIFIED_IDENTIFIER        = Pattern.compile(
            "[_a-zA-Z][_a-zA-Z0-9]*[.][_a-zA-Z][_a-zA-Z0-9]*");
    private static final Pattern RE_DOUBLE_QUALIFIED_IDENTIFIER = Pattern.compile(
            "[_a-zA-Z][_a-zA-Z0-9]*[.][_a-zA-Z][_a-zA-Z0-9]*[.][_a-zA-Z][_a-zA-Z0-9]*");
    private static final Pattern RE_REFERENCE_IDENTIFIER        = Pattern.compile(
            "[_a-zA-Z][_a-zA-Z0-9]*([.][_a-zA-Z][_a-zA-Z0-9]*)*");
    private final static Pattern RE_BLOCK_LINE                  = Pattern.compile(
            "^([\\s]*[*])?[\\s]?");
    private static final Pattern RE_FIELD_ID                     = Pattern.compile(
            "([1-9][0-9]*)");
    private static final Pattern RE_ENUM_ID                     = Pattern.compile(
            "(0|[1-9][0-9]*)");
    private static final Pattern RE_INTEGER                     = Pattern.compile(
            "-?(0|[1-9][0-9]*|0[0-7]+|0x[0-9a-fA-F]+)");
    private static final Pattern RE_REAL                        = Pattern.compile(
            "-?(0?\\.[0-9]+|[1-9][0-9]*\\.[0-9]*)([eE][+-]?[0-9][0-9]*)?");
}