package com.laytonsmith.core.constructs; import java.io.File; import java.util.Arrays; import java.util.EnumSet; import java.util.Set; /** * * */ public class Token { public TType type; public String value; public final int line_num; public final int column; public final File file; public final Target target; private enum TokenVariant { ADDITIVE, EQUALITY, EXPONENTIAL, IDENTIFIER, LOGICAL_AND, LOGICAL_OR, DEFAULT_AND, DEFAULT_OR, MULTIPLICATIVE, PLUS_MINUS, POSTFIX, RELATIONAL, SYMBOL, UNARY, ASSIGNMENT, SEPARATOR, ATOMIC_LIT, WHITESPACE, KEYWORD } public enum TType { //TODO: Comment this out once the compiler is replaced, and clean up unused ones UNKNOWN(TokenVariant.IDENTIFIER), LSQUARE_BRACKET(TokenVariant.SEPARATOR), RSQUARE_BRACKET(TokenVariant.SEPARATOR), OPT_VAR_ASSIGN(TokenVariant.SEPARATOR), ALIAS_END(TokenVariant.SEPARATOR), COMMA(TokenVariant.SEPARATOR), FUNC_NAME(), FUNC_START(TokenVariant.SEPARATOR), FUNC_END(TokenVariant.SEPARATOR), NEWLINE(TokenVariant.WHITESPACE), MULTILINE_START(TokenVariant.SEPARATOR), MULTILINE_END(TokenVariant.SEPARATOR), COMMAND(), SEPERATOR(TokenVariant.SEPARATOR), STRING(TokenVariant.IDENTIFIER, TokenVariant.ATOMIC_LIT), VARIABLE(TokenVariant.IDENTIFIER), IVARIABLE(TokenVariant.IDENTIFIER), FINAL_VAR(TokenVariant.IDENTIFIER), LIT(TokenVariant.IDENTIFIER, TokenVariant.ATOMIC_LIT), DOT(TokenVariant.IDENTIFIER), SMART_STRING(TokenVariant.IDENTIFIER, TokenVariant.ATOMIC_LIT), BARE_STRING(TokenVariant.IDENTIFIER, TokenVariant.ATOMIC_LIT), ROOT(), LABEL(TokenVariant.SEPARATOR), DEREFERENCE(), SLICE(), PLUS(TokenVariant.SYMBOL, TokenVariant.UNARY, TokenVariant.ADDITIVE, TokenVariant.PLUS_MINUS), MINUS(TokenVariant.SYMBOL, TokenVariant.UNARY, TokenVariant.ADDITIVE, TokenVariant.PLUS_MINUS), MULTIPLICATION(TokenVariant.SYMBOL, TokenVariant.MULTIPLICATIVE), DIVISION(TokenVariant.SYMBOL, TokenVariant.MULTIPLICATIVE), EQUALS(TokenVariant.SYMBOL, TokenVariant.EQUALITY), NOT_EQUALS(TokenVariant.SYMBOL, TokenVariant.EQUALITY), STRICT_EQUALS(TokenVariant.SYMBOL, TokenVariant.EQUALITY), STRICT_NOT_EQUALS(TokenVariant.SYMBOL, TokenVariant.EQUALITY), GT(TokenVariant.SYMBOL, TokenVariant.RELATIONAL), LT(TokenVariant.SYMBOL, TokenVariant.RELATIONAL), LTE(TokenVariant.SYMBOL, TokenVariant.RELATIONAL), GTE(TokenVariant.SYMBOL, TokenVariant.RELATIONAL), LOGICAL_AND(TokenVariant.SYMBOL, TokenVariant.LOGICAL_AND), LOGICAL_OR(TokenVariant.SYMBOL, TokenVariant.LOGICAL_OR), DEFAULT_AND(TokenVariant.SYMBOL, TokenVariant.DEFAULT_AND), DEFAULT_OR(TokenVariant.SYMBOL, TokenVariant.DEFAULT_OR), LOGICAL_NOT(TokenVariant.SYMBOL, TokenVariant.UNARY), INCREMENT(TokenVariant.SYMBOL, TokenVariant.POSTFIX, TokenVariant.UNARY), DECREMENT(TokenVariant.SYMBOL, TokenVariant.POSTFIX, TokenVariant.UNARY), MODULO(TokenVariant.SYMBOL, TokenVariant.MULTIPLICATIVE), CONCAT(TokenVariant.SYMBOL, TokenVariant.ADDITIVE), EXPONENTIAL(TokenVariant.SYMBOL, TokenVariant.EXPONENTIAL), WHITESPACE(TokenVariant.WHITESPACE), LCURLY_BRACKET(TokenVariant.SEPARATOR), RCURLY_BRACKET(TokenVariant.SEPARATOR), IDENTIFIER(), DOUBLE(TokenVariant.IDENTIFIER, TokenVariant.ATOMIC_LIT), INTEGER(TokenVariant.IDENTIFIER, TokenVariant.ATOMIC_LIT), CONST_START(), ASSIGNMENT(TokenVariant.ASSIGNMENT, TokenVariant.SYMBOL), PLUS_ASSIGNMENT(TokenVariant.ASSIGNMENT, TokenVariant.SYMBOL, TokenVariant.ADDITIVE, TokenVariant.PLUS_MINUS), MINUS_ASSIGNMENT(TokenVariant.ASSIGNMENT, TokenVariant.SYMBOL, TokenVariant.ADDITIVE, TokenVariant.PLUS_MINUS), MULTIPLICATION_ASSIGNMENT(TokenVariant.ASSIGNMENT, TokenVariant.SYMBOL, TokenVariant.MULTIPLICATIVE), DIVISION_ASSIGNMENT(TokenVariant.ASSIGNMENT, TokenVariant.SYMBOL, TokenVariant.MULTIPLICATIVE), CONCAT_ASSIGNMENT(TokenVariant.ASSIGNMENT, TokenVariant.SYMBOL, TokenVariant.ADDITIVE), SEMICOLON(TokenVariant.SEPARATOR), KEYWORD(TokenVariant.KEYWORD); private final Set<TokenVariant> variants = EnumSet.noneOf(TokenVariant.class); private TType(TokenVariant... variants) { this.variants.addAll(Arrays.asList(variants)); } /** * True if the token is a symbol, i.e. + - = * * @return */ public boolean isSymbol() { return this.variants.contains(TokenVariant.SYMBOL); } /** * Returns true if the token is a postfix operator. This implies it is a prefix operator as well. -- ++ * * @return */ public boolean isPostfix() { return this.variants.contains(TokenVariant.POSTFIX); } /** * Returns true if this symbol is a unary operator, ! - + -- ++ * * @return */ public boolean isUnary() { return this.variants.contains(TokenVariant.UNARY); } /** * Returns true if this symbol is multiplicative * * @return */ public boolean isMultaplicative() { return this.variants.contains(TokenVariant.MULTIPLICATIVE); } /** * Returns true if this symbol is additive + += . etc * * @return */ public boolean isAdditive() { return this.variants.contains(TokenVariant.ADDITIVE); } /** * Returns true if this symbol is relational, < > * * @return */ public boolean isRelational() { return this.variants.contains(TokenVariant.RELATIONAL); } /** * Returns true if this symbol is equalitative, === == != !== * * @return */ public boolean isEquality() { return this.variants.contains(TokenVariant.EQUALITY); } // public boolean isBitwiseAnd(){ // return (this == BIT_AND); // } // // public boolean isBitwiseXor(){ // return (this == BIT_XOR); // } // // public boolean isBitwiseOr(){ // return (this == BIT_OR); // } /** * Returns true if this is a logical and * * @return */ public boolean isLogicalAnd() { return this.variants.contains(TokenVariant.LOGICAL_AND); } /** * Returns true if this is a default and * @return */ public boolean isDefaultAnd() { return this.variants.contains(TokenVariant.DEFAULT_AND); } /** * Return true if this is a logical or * * @return */ public boolean isLogicalOr() { return this.variants.contains(TokenVariant.LOGICAL_OR); } /** * Returns true if this is a default or * @return */ public boolean isDefaultOr() { return this.variants.contains(TokenVariant.DEFAULT_OR); } /** * Returns true if this is a plus/minus operator + - += -= * * @return */ public boolean isPlusMinus() { return this.variants.contains(TokenVariant.PLUS_MINUS); } /** * Returns true if this is an identifier. Variables, strings, bare strings, integers, doubles, etc. Unknown * tokens are assumed to be identifiers. * * @return */ public boolean isIdentifier() { return this.variants.contains(TokenVariant.IDENTIFIER); } /** * Returns true if this is an exponential symbol * ** * @return */ public boolean isExponential() { return this.variants.contains(TokenVariant.EXPONENTIAL); } /** * Returns true if this is an assigment operator = += etc * * @return */ public boolean isAssignment() { return this.variants.contains(TokenVariant.ASSIGNMENT); } /** * Returns true if this is a separator, that is, it ends a logical statement. [ ] { } ( ) , ; etc * * @return */ public boolean isSeparator() { return this.variants.contains(TokenVariant.SEPARATOR); } /** * Returns true if this is an atomic literal, that is a string (including bare strings), integer, or double * only. Variables are not included. * * @return */ public boolean isAtomicLit() { return this.variants.contains(TokenVariant.ATOMIC_LIT); } /** * Returns true if this is a whitespace token, i.e. space, tab, or newline. * * @return */ public boolean isWhitespace() { return this.variants.contains(TokenVariant.WHITESPACE); } public boolean isKeyword() { return this.variants.contains(TokenVariant.KEYWORD); } } public Token(TType type, String value, Target t) { this.type = type; this.value = value; this.line_num = t.line(); this.file = t.file(); this.column = t.col(); this.target = t; } public String val() { return value; } @Override public int hashCode() { int hash = 7; hash = 59 * hash + (this.type != null ? this.type.hashCode() : 0); hash = 59 * hash + (this.value != null ? this.value.hashCode() : 0); return hash; } @Override public boolean equals(Object o) { if (o instanceof Token) { Token t = (Token) o; return (this.type.equals(t.type) && this.value.equals(t.value)); } return false; } @Override public String toString() { if (type.equals(TType.NEWLINE)) { return "newline"; } if (type.equals(TType.STRING)) { return "'" + value + "'"; } return type + ":" + value; } public String toSimpleString() { if (type.equals(TType.STRING)) { return "'" + value + "'"; } return value; } public String toOutputString() { if (type.equals(TType.STRING)) { return value.replace("\\", "\\\\").replace("'", "\\'"); } return value; } public Target getTarget() { return target; } }