/* * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.apache.flex.compiler.internal.parsing.as; import java.lang.reflect.Field; import org.apache.flex.compiler.internal.parsing.TokenBase; import org.apache.flex.compiler.parsing.IASToken; import org.apache.flex.compiler.parsing.ICMToken; import com.google.common.collect.ImmutableMap; /** * ActionScript token (output unit of ASTokenizer/ASTokenFixer, input unit of * ASTreeAssembler). */ public class ASToken extends TokenBase implements IASToken, ASTokenTypes { /** * Builds a new {@link ASToken} * * @param tokenType type of token * @param start start of token * @param end end of token * @param line line of token * @param tokenText token type from ASTokenTypes */ public ASToken(final int tokenType, int start, int end, int line, int column, CharSequence tokenText) { super(tokenType, start, end, line, column, tokenText); } /** * Copy constructor * * @param other the ASToken to copy */ public ASToken(ASToken other) { super(other); } @Override public ASToken clone() { return new ASToken(this); } @Override public ICMToken changeType(int type) { return new ASToken(type, getStart(), getEnd(), getLine(), getColumn(), getText()); } /** * Is this an open token (e.g. "(", "{", "[") * * @param tokenType type of the token * @return true iff this is an open token */ public static final boolean isOpenToken(final int tokenType) { switch (tokenType) { case TOKEN_PAREN_OPEN: case TOKEN_BLOCK_OPEN: case TOKEN_SQUARE_OPEN: case TOKEN_E4X_BINDING_OPEN: return true; default: return false; } } /** * Unknown open block token type. * * @see #getOpenBlockTokenType() */ public static final int UNKNOWN_OPEN_BLOCK_TOKEN_TYPE = -1; public static final int getOpenBlockTokenType(int tokenType) { switch (tokenType) { case TOKEN_KEYWORD_CATCH: case TOKEN_KEYWORD_DO: case TOKEN_KEYWORD_WHILE: case TOKEN_KEYWORD_FOR: case TOKEN_RESERVED_WORD_EACH: case TOKEN_KEYWORD_WITH: case TOKEN_KEYWORD_ELSE: case TOKEN_KEYWORD_IF: case TOKEN_KEYWORD_SWITCH: case TOKEN_KEYWORD_CASE: case TOKEN_KEYWORD_DEFAULT: case TOKEN_KEYWORD_TRY: case TOKEN_KEYWORD_FINALLY: return TOKEN_BLOCK_OPEN; case TOKEN_KEYWORD_CLASS: return TOKEN_BLOCK_OPEN; case TOKEN_KEYWORD_FUNCTION: return TOKEN_BLOCK_OPEN; case TOKEN_KEYWORD_INTERFACE: return TOKEN_BLOCK_OPEN; case TOKEN_KEYWORD_PACKAGE: return TOKEN_BLOCK_OPEN; } return UNKNOWN_OPEN_BLOCK_TOKEN_TYPE; } public final int getOpenBlockTokenType() { return getOpenBlockTokenType(type); } /** * Is this an open block token * * @return true if this is an open block token */ public final boolean isOpenBlockToken() { return ASToken.isOpenBlockToken(getType()); } public static final boolean isOpenBlockToken(final int tokenType) { switch (tokenType) { case TOKEN_BLOCK_OPEN: case TOKEN_E4X_BINDING_OPEN: return true; default: return false; } } /** * Is this an open token (e.g. "(", "{", "[") * * @return true iff this is an open token */ public final boolean isOpenToken() { return ASToken.isOpenToken(getType()); } /** * Is this a close token (e.g. ")", "}", "]") * * @param tokenType type of the token * @return true if this is an close token */ public static final boolean isCloseToken(final int tokenType) { switch (tokenType) { case TOKEN_PAREN_CLOSE: case TOKEN_BLOCK_CLOSE: case TOKEN_SQUARE_CLOSE: case TOKEN_E4X_BINDING_CLOSE: return true; default: return false; } } /** * Is this a close block token * * @return true if this is a close block token */ public final boolean isCloseBlockToken() { return ASToken.isCloseBlockToken(getType()); } /** * Is this a close token * * @param tokenType type of the token * @return true if this is an close token */ public static final boolean isCloseBlockToken(final int tokenType) { switch (tokenType) { case TOKEN_BLOCK_CLOSE: case TOKEN_E4X_BINDING_CLOSE: return true; default: return false; } } /** * Is this a close token (e.g. ")", "}", "]") * * @return true iff this is an close token */ public final boolean isCloseToken() { return ASToken.isCloseToken(getType()); } /** * If this is an open token, get the matching close token. If this is a * close token, get the matching open token * * @param tokenType type of the token * @return balancing token (or 0 if this isn't an open/close token) */ public static final int getBalancingToken(final int tokenType) { switch (tokenType) { case TOKEN_PAREN_OPEN: return TOKEN_PAREN_CLOSE; case TOKEN_PAREN_CLOSE: return TOKEN_PAREN_OPEN; case TOKEN_BLOCK_OPEN: return TOKEN_BLOCK_CLOSE; case TOKEN_BLOCK_CLOSE: return TOKEN_BLOCK_OPEN; case TOKEN_TYPED_COLLECTION_OPEN: return TOKEN_TYPED_COLLECTION_CLOSE; case TOKEN_TYPED_LITERAL_OPEN: return TOKEN_TYPED_LITERAL_CLOSE; case TOKEN_TYPED_LITERAL_CLOSE: return TOKEN_TYPED_LITERAL_OPEN; case TOKEN_SQUARE_OPEN: return TOKEN_SQUARE_CLOSE; case TOKEN_SQUARE_CLOSE: return TOKEN_SQUARE_OPEN; case TOKEN_TYPED_COLLECTION_CLOSE: return TOKEN_TYPED_COLLECTION_OPEN; case TOKEN_E4X_BINDING_OPEN: return TOKEN_E4X_BINDING_CLOSE; case TOKEN_E4X_BINDING_CLOSE: return TOKEN_E4X_BINDING_OPEN; default: return 0; } } /** * If this is an open token, get the matching close token. If this is a * close token, get the matching open token * * @return balancing token (or 0 if this isn't an open/close token) */ public final int getBalancingToken() { return ASToken.getBalancingToken(getType()); } /** * Determine whether or not this token is capable of causing a containment * problem. If a token can cause canContain to return false when it's passed * in as containedType, then it must return true. This is used to improve * the performance of ASTokenFixer.locateBottommostContainerProblem. * * @param tokenType type of the token * @return true if the token can cause canContain to return false. */ private static final boolean canCauseContainmentProblems(final int tokenType) { switch (tokenType) { case TOKEN_KEYWORD_PACKAGE: case TOKEN_KEYWORD_CLASS: case TOKEN_KEYWORD_INTERFACE: case TOKEN_KEYWORD_FUNCTION: case TOKEN_KEYWORD_VAR: case TOKEN_BLOCK_OPEN: case TOKEN_BLOCK_CLOSE: return true; default: return false; } } /** * Determine whether or not this token is capable of causing a containment * problem. If a token can cause canContain to return false when it's passed * in as containedType, then it must return true. This is used to improve * the performance of ASTokenFixer.locateBottommostContainerProblem. * * @return true iff the token can cause canContain to return false. */ public final boolean canCauseContainmentProblems() { return ASToken.canCauseContainmentProblems(getType()); } public final boolean isOperator() { return ASToken.isOperator(this); } private static final boolean isOperator(ASToken token) { switch (token.getType()) { case TOKEN_OPERATOR_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_NOT: case TOKEN_OPERATOR_LOGICAL_NOT: case TOKEN_OPERATOR_MINUS: case TOKEN_OPERATOR_PLUS: case TOKEN_OPERATOR_MEMBER_ACCESS: case TOKEN_OPERATOR_NS_QUALIFIER: case TOKEN_OPERATOR_STAR: case TOKEN_OPERATOR_DIVISION: case TOKEN_OPERATOR_MODULO: case TOKEN_OPERATOR_BITWISE_LEFT_SHIFT: case TOKEN_OPERATOR_BITWISE_RIGHT_SHIFT: case TOKEN_OPERATOR_BITWISE_UNSIGNED_RIGHT_SHIFT: case TOKEN_OPERATOR_LESS_THAN: case TOKEN_OPERATOR_GREATER_THAN: case TOKEN_OPERATOR_LESS_THAN_EQUALS: case TOKEN_OPERATOR_GREATER_THAN_EQUALS: case TOKEN_OPERATOR_EQUAL: case TOKEN_OPERATOR_NOT_EQUAL: case TOKEN_OPERATOR_STRICT_EQUAL: case TOKEN_OPERATOR_STRICT_NOT_EQUAL: case TOKEN_OPERATOR_BITWISE_AND: case TOKEN_OPERATOR_BITWISE_XOR: case TOKEN_OPERATOR_BITWISE_OR: case TOKEN_OPERATOR_LOGICAL_AND: case TOKEN_OPERATOR_LOGICAL_OR: case TOKEN_OPERATOR_PLUS_ASSIGNMENT: case TOKEN_OPERATOR_MINUS_ASSIGNMENT: case TOKEN_OPERATOR_MULTIPLICATION_ASSIGNMENT: case TOKEN_OPERATOR_DIVISION_ASSIGNMENT: case TOKEN_OPERATOR_MODULO_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_AND_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_OR_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_XOR_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_LEFT_SHIFT_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_RIGHT_SHIFT_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_UNSIGNED_RIGHT_SHIFT_ASSIGNMENT: case TOKEN_OPERATOR_LOGICAL_AND_ASSIGNMENT: case TOKEN_OPERATOR_LOGICAL_OR_ASSIGNMENT: case TOKEN_KEYWORD_IN: case TOKEN_OPERATOR_TERNARY: case TOKEN_OPERATOR_DECREMENT: case TOKEN_OPERATOR_INCREMENT: case TOKEN_KEYWORD_AS: case TOKEN_KEYWORD_IS: case TOKEN_KEYWORD_DELETE: case TOKEN_KEYWORD_TYPEOF: case TOKEN_KEYWORD_INSTANCEOF: case TOKEN_OPERATOR_ATSIGN: case TOKEN_OPERATOR_DESCENDANT_ACCESS: return true; default: return false; } } public final boolean isE4X() { return ASToken.isE4X(type); } public static final boolean isE4X(final int type) { switch (type) { case TOKEN_E4X_CDATA: case TOKEN_E4X_COMMENT: case TOKEN_E4X_OPEN_TAG_START: case TOKEN_E4X_CLOSE_TAG_START: case TOKEN_E4X_TAG_END: case TOKEN_E4X_EMPTY_TAG_END: case TOKEN_E4X_NAME: case TOKEN_E4X_WHITESPACE: case TOKEN_E4X_DOTTED_NAME_PART: case TOKEN_E4X_NAME_DOT: case TOKEN_E4X_EQUALS: case HIDDEN_TOKEN_E4X: case TOKEN_E4X_PROCESSING_INSTRUCTION: case TOKEN_E4X_STRING: case TOKEN_E4X_XMLNS: case TOKEN_E4X_ENTITY: case TOKEN_E4X_DECIMAL_ENTITY: case TOKEN_E4X_HEX_ENTITY: case TOKEN_E4X_TEXT: case TOKEN_LITERAL_XMLLIST: case TOKEN_E4X_XMLLIST_CLOSE: return true; } return false; } public final boolean isLiteral() { return ASToken.isLiteral(type); } private static final boolean isLiteral(final int type) { switch (type) { case TOKEN_KEYWORD_TRUE: case TOKEN_KEYWORD_FALSE: case TOKEN_LITERAL_NUMBER: case TOKEN_VOID_0: case TOKEN_KEYWORD_NULL: case TOKEN_LITERAL_HEX_NUMBER: case TOKEN_LITERAL_REGEXP: case TOKEN_LITERAL_STRING: case TOKEN_LITERAL_XMLLIST: case TOKEN_E4X_XMLLIST_CLOSE: return true; default: return false; } } public static final boolean isDefinitionKeyword(final int type) { switch (type) { case TOKEN_KEYWORD_CLASS: case TOKEN_KEYWORD_FUNCTION: case TOKEN_KEYWORD_INTERFACE: case TOKEN_RESERVED_WORD_NAMESPACE: case TOKEN_KEYWORD_VAR: case TOKEN_KEYWORD_CONST: return true; } return false; } public static boolean isModifier(final int type) { switch (type) { case TOKEN_MODIFIER_DYNAMIC: case TOKEN_MODIFIER_FINAL: case TOKEN_MODIFIER_NATIVE: case TOKEN_MODIFIER_OVERRIDE: case TOKEN_MODIFIER_STATIC: return true; } return false; } public final boolean isModifier() { return isModifier(type); } public static final boolean isStatementKeyword(final int type) { switch (type) { case TOKEN_KEYWORD_FOR: case TOKEN_KEYWORD_WHILE: case TOKEN_KEYWORD_WITH: case TOKEN_KEYWORD_FINALLY: case TOKEN_KEYWORD_CASE: case TOKEN_KEYWORD_SWITCH: case TOKEN_KEYWORD_DO: case TOKEN_KEYWORD_DEFAULT: case TOKEN_KEYWORD_BREAK: case TOKEN_KEYWORD_CONTINUE: case TOKEN_KEYWORD_IF: case TOKEN_KEYWORD_ELSE: return true; } return false; } public final boolean isStatementKeyword() { return ASToken.isStatementKeyword(type); } /** * Check if the token is a contextual reserved word. * * @return True if the token is a contextual reserved word. */ public final boolean isContextualReservedWord() { switch (type) { case TOKEN_MODIFIER_DYNAMIC: case TOKEN_MODIFIER_FINAL: case TOKEN_MODIFIER_NATIVE: case TOKEN_MODIFIER_OVERRIDE: case TOKEN_MODIFIER_STATIC: case TOKEN_MODIFIER_VIRTUAL: case TOKEN_RESERVED_WORD_GET: case TOKEN_RESERVED_WORD_SET: case TOKEN_RESERVED_WORD_NAMESPACE: case TOKEN_RESERVED_WORD_CONFIG: case TOKEN_RESERVED_WORD_EXTENDS: case TOKEN_RESERVED_WORD_EACH: case TOKEN_RESERVED_WORD_IMPLEMENTS: case TOKEN_RESERVED_WORD_GOTO: return true; default: return false; } } /** * Returns whether this token represents an ActionScript keyword. * <p> * For missing "private", "protected", "public", "internal", see * https://bugs.adobe.com/jira/browse/ASLSPEC-8 * * @return True if the token is a reserved keyword. */ public final boolean isKeyword() { switch (type) { case TOKEN_KEYWORD_AS: case TOKEN_KEYWORD_BREAK: case TOKEN_KEYWORD_CASE: case TOKEN_KEYWORD_CATCH: case TOKEN_KEYWORD_CLASS: case TOKEN_KEYWORD_CONST: case TOKEN_KEYWORD_CONTINUE: case TOKEN_KEYWORD_DEFAULT: case TOKEN_KEYWORD_DELETE: case TOKEN_KEYWORD_DO: case TOKEN_KEYWORD_ELSE: case TOKEN_KEYWORD_FALSE: case TOKEN_KEYWORD_FINALLY: case TOKEN_KEYWORD_FOR: case TOKEN_KEYWORD_FUNCTION: case TOKEN_KEYWORD_IF: case TOKEN_KEYWORD_IMPORT: case TOKEN_KEYWORD_IN: case TOKEN_KEYWORD_INCLUDE: case TOKEN_KEYWORD_INSTANCEOF: case TOKEN_KEYWORD_INTERFACE: case TOKEN_KEYWORD_IS: case TOKEN_KEYWORD_NEW: case TOKEN_KEYWORD_NULL: case TOKEN_KEYWORD_PACKAGE: case TOKEN_KEYWORD_RETURN: case TOKEN_KEYWORD_SUPER: case TOKEN_KEYWORD_SWITCH: case TOKEN_KEYWORD_THIS: case TOKEN_KEYWORD_THROW: case TOKEN_KEYWORD_TRUE: case TOKEN_KEYWORD_TRY: case TOKEN_KEYWORD_TYPEOF: case TOKEN_KEYWORD_USE: case TOKEN_KEYWORD_VAR: case TOKEN_KEYWORD_VOID: case TOKEN_KEYWORD_WHILE: case TOKEN_KEYWORD_WITH: return true; default: return false; } } /** * Check if the token is either a "keyword" or a "contextual reserved word". * * @return True if the token is either a "keyword" or a * "contextual reserved word". */ public final boolean isKeywordOrContextualReservedWord() { return isKeyword() || isContextualReservedWord(); } public static final boolean canExistInMetadata(final int tokenType) { switch (tokenType) { //this is the valid set of tokens contained within metadata case TOKEN_PAREN_OPEN: case TOKEN_PAREN_CLOSE: case TOKEN_IDENTIFIER: case TOKEN_COMMA: case TOKEN_SQUARE_CLOSE: case TOKEN_OPERATOR_ASSIGNMENT: case TOKEN_KEYWORD_INCLUDE: case TOKEN_KEYWORD_DEFAULT: case TOKEN_KEYWORD_TRUE: case TOKEN_KEYWORD_FALSE: case TOKEN_LITERAL_HEX_NUMBER: case TOKEN_KEYWORD_NULL: case TOKEN_LITERAL_NUMBER: case TOKEN_LITERAL_STRING: return true; } return false; } public final boolean canExistInMetadata() { return canExistInMetadata(type); } public static final boolean canFollowMetadata(final int tokenType) { switch (tokenType) { case TOKEN_IDENTIFIER: case TOKEN_ASDOC_COMMENT: case HIDDEN_TOKEN_MULTI_LINE_COMMENT: case HIDDEN_TOKEN_SINGLE_LINE_COMMENT: case TOKEN_SQUARE_OPEN: return true; //we're a valid following token for metadata } return false; } public final boolean canFollowMetadata() { return canFollowMetadata(type); } public static final boolean canFollowUserNamespaceAnnotation(final int tokenType) { switch (tokenType) { case TOKEN_KEYWORD_FUNCTION: case TOKEN_KEYWORD_VAR: case TOKEN_KEYWORD_CONST: case TOKEN_MODIFIER_DYNAMIC: case TOKEN_MODIFIER_FINAL: case TOKEN_MODIFIER_NATIVE: case TOKEN_MODIFIER_OVERRIDE: case TOKEN_MODIFIER_STATIC: return true; } return false; } public final boolean canFollowUserNamespace() { return canFollowUserNamespaceAnnotation(type); } /** * @return True if a "function" keyword after this token should be * considered an anonymous function (closure). */ public final boolean canPreceedAnonymousFunction() { switch (type) { case TOKEN_OPERATOR_ASSIGNMENT: // x = function () {...}; case TOKEN_COMMA: // foo(x, function() {...}); case TOKEN_PAREN_OPEN: // foo(function() {...}, ...); case TOKEN_SQUARE_OPEN: // x = [ function() {...}, ...]; case TOKEN_KEYWORD_NEW: // x = new function() {...}; case TOKEN_KEYWORD_RETURN: // return new function() {...}; case TOKEN_COLON: // obj = { fn: function() {...} }; return true; default: return false; } } /** * Returns true if the token type can come before the operators * <code>+</code> or <code>-</code> * * @param tokenType the token type to check * @return true if able to come before */ public static final boolean canPreceedSignedOperator(final int tokenType) { if (isLiteral(tokenType)) return true; switch (tokenType) { case TOKEN_PAREN_CLOSE: case TOKEN_SQUARE_CLOSE: case TOKEN_IDENTIFIER: case TOKEN_OPERATOR_DECREMENT: case TOKEN_OPERATOR_INCREMENT: case TOKEN_KEYWORD_THIS: case TOKEN_KEYWORD_SUPER: return true; } return false; } /** * Returns true if the token can come before the operators <code>+</code> or * <code>-</code> * * @return true if able to come before */ public final boolean canPreceedSignedOperator() { return canPreceedSignedOperator(type); } public final boolean canPreceedE4X() { return canPreceedE4X(type); } public static final boolean canPreceedE4X(final int tokenType) { switch (tokenType) { case TOKEN_SEMICOLON: case TOKEN_PAREN_OPEN: case TOKEN_COMMA: case TOKEN_OPERATOR_ASSIGNMENT: case TOKEN_KEYWORD_RETURN: case TOKEN_KEYWORD_THROW: case TOKEN_SQUARE_OPEN: //array/vector initializer open // case TOKEN_OPERATOR_BINARY: case TOKEN_OPERATOR_DIVISION: case TOKEN_OPERATOR_MODULO: case TOKEN_OPERATOR_BITWISE_LEFT_SHIFT: case TOKEN_OPERATOR_BITWISE_RIGHT_SHIFT: case TOKEN_OPERATOR_BITWISE_UNSIGNED_RIGHT_SHIFT: case TOKEN_OPERATOR_LESS_THAN: case TOKEN_OPERATOR_GREATER_THAN: case TOKEN_OPERATOR_LESS_THAN_EQUALS: case TOKEN_OPERATOR_GREATER_THAN_EQUALS: case TOKEN_OPERATOR_EQUAL: case TOKEN_OPERATOR_NOT_EQUAL: case TOKEN_OPERATOR_STRICT_EQUAL: case TOKEN_OPERATOR_STRICT_NOT_EQUAL: case TOKEN_OPERATOR_BITWISE_AND: case TOKEN_OPERATOR_BITWISE_XOR: case TOKEN_OPERATOR_BITWISE_OR: case TOKEN_OPERATOR_LOGICAL_AND: case TOKEN_OPERATOR_LOGICAL_OR: case TOKEN_OPERATOR_PLUS: case TOKEN_OPERATOR_MINUS: case TOKEN_OPERATOR_BITWISE_NOT: case TOKEN_OPERATOR_LOGICAL_NOT: case TOKEN_OPERATOR_PLUS_ASSIGNMENT: case TOKEN_OPERATOR_MINUS_ASSIGNMENT: case TOKEN_OPERATOR_MULTIPLICATION_ASSIGNMENT: case TOKEN_OPERATOR_DIVISION_ASSIGNMENT: case TOKEN_OPERATOR_MODULO_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_AND_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_OR_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_XOR_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_LEFT_SHIFT_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_RIGHT_SHIFT_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_UNSIGNED_RIGHT_SHIFT_ASSIGNMENT: // Ternary("?") and Colon(":") are for XML literals inside ternary expressions: // For example: boolValue ? <True></True> : <False></False> case TOKEN_OPERATOR_TERNARY: case TOKEN_COLON: case -1: //nothing return true; } return false; } /** * Check if regular-expression literal can follow a token of given type. * * @param tokenType Token type * @return True if {@link ASTokenTypes#TOKEN_LITERAL_REGEXP} can follow the * given token type. */ public static final boolean canPreceedRegex(final int tokenType) { switch (tokenType) { case TOKEN_PAREN_OPEN: case TOKEN_SQUARE_OPEN: // i.e. var a:Array = [ /foo/, /bar/ ] ; case TOKEN_COMMA: case TOKEN_COLON: case TOKEN_OPERATOR_ASSIGNMENT: case TOKEN_KEYWORD_RETURN: case TOKEN_KEYWORD_THROW: case TOKEN_SEMICOLON: case TOKEN_BLOCK_OPEN: case TOKEN_BLOCK_CLOSE: case TOKEN_OPERATOR_DIVISION: case TOKEN_OPERATOR_MODULO: case TOKEN_OPERATOR_BITWISE_LEFT_SHIFT: case TOKEN_OPERATOR_BITWISE_RIGHT_SHIFT: case TOKEN_OPERATOR_BITWISE_UNSIGNED_RIGHT_SHIFT: case TOKEN_OPERATOR_LESS_THAN: case TOKEN_OPERATOR_GREATER_THAN: case TOKEN_OPERATOR_LESS_THAN_EQUALS: case TOKEN_OPERATOR_GREATER_THAN_EQUALS: case TOKEN_OPERATOR_EQUAL: case TOKEN_OPERATOR_NOT_EQUAL: case TOKEN_OPERATOR_STRICT_EQUAL: case TOKEN_OPERATOR_STRICT_NOT_EQUAL: case TOKEN_OPERATOR_BITWISE_AND: case TOKEN_OPERATOR_BITWISE_XOR: case TOKEN_OPERATOR_BITWISE_OR: case TOKEN_OPERATOR_LOGICAL_AND: case TOKEN_OPERATOR_LOGICAL_OR: case TOKEN_OPERATOR_PLUS: case TOKEN_OPERATOR_MINUS: case TOKEN_OPERATOR_BITWISE_NOT: case TOKEN_OPERATOR_LOGICAL_NOT: case TOKEN_OPERATOR_PLUS_ASSIGNMENT: case TOKEN_OPERATOR_MINUS_ASSIGNMENT: case TOKEN_OPERATOR_MULTIPLICATION_ASSIGNMENT: case TOKEN_OPERATOR_DIVISION_ASSIGNMENT: case TOKEN_OPERATOR_MODULO_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_AND_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_OR_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_XOR_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_LEFT_SHIFT_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_RIGHT_SHIFT_ASSIGNMENT: case TOKEN_OPERATOR_BITWISE_UNSIGNED_RIGHT_SHIFT_ASSIGNMENT: // The following ones are RegEx after a unary operator. case TOKEN_KEYWORD_VOID: case TOKEN_KEYWORD_TYPEOF: case TOKEN_KEYWORD_DELETE: case TOKEN_OPERATOR_INCREMENT: case TOKEN_OPERATOR_DECREMENT: case -1: //no previous token return true; } return false; } private static ImmutableMap<Integer, String> tokenNames; /** * Create a lookup map for token names using reflections. */ private static synchronized void initializeTokenNames() { if (tokenNames != null) return; final ImmutableMap.Builder<Integer, String> builder = new ImmutableMap.Builder<Integer, String>(); final ASToken token = new ASToken(UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, ""); for (final Field field : ASTokenTypes.class.getFields()) { if (field.getType().equals(Integer.TYPE)) { int tokenType; try { tokenType = field.getInt(token); } catch (Exception e) { throw new RuntimeException(e); } builder.put(tokenType, field.getName()); } } tokenNames = builder.build(); } /** * Get the display string for the token type * * @return display string for the token type */ @Override protected String getTypeString() { initializeTokenNames(); return tokenNames.get(getType()); } @Override public ASTokenKind getTokenKind() { switch (getType()) { case EOF: return ASTokenKind.EOF; case HIDDEN_TOKEN_COMMENT: case HIDDEN_TOKEN_MULTI_LINE_COMMENT: case HIDDEN_TOKEN_SINGLE_LINE_COMMENT: case TOKEN_ASDOC_COMMENT: return ASTokenKind.COMMENT; case TOKEN_MODIFIER_DYNAMIC: case TOKEN_MODIFIER_FINAL: case TOKEN_MODIFIER_NATIVE: case TOKEN_MODIFIER_OVERRIDE: case TOKEN_MODIFIER_STATIC: return ASTokenKind.MODIFIER; case HIDDEN_TOKEN_BUILTIN_NS: case TOKEN_NAMESPACE_ANNOTATION: return ASTokenKind.NAMESPACE; case TOKEN_DIRECTIVE_DEFAULT_XML: return ASTokenKind.DEFAULT_XML_STATEMENT; case TOKEN_BLOCK_CLOSE: return ASTokenKind.SCOPE_CLOSE; case TOKEN_BLOCK_OPEN: return ASTokenKind.SCOPE_OPEN; case TOKEN_LITERAL_STRING: return ASTokenKind.STRING_LITERAL; case TOKEN_LITERAL_NUMBER: case TOKEN_LITERAL_HEX_NUMBER: return ASTokenKind.NUMBER_LITERAL; case TOKEN_KEYWORD_TRUE: case TOKEN_KEYWORD_FALSE: return ASTokenKind.BOOLEAN_LITERAL; case TOKEN_VOID_0: case TOKEN_KEYWORD_NULL: return ASTokenKind.OBJECT_LITERAL; case TOKEN_LITERAL_REGEXP: return ASTokenKind.REGEX_LITERAL; case TOKEN_LITERAL_XMLLIST: case TOKEN_E4X_XMLLIST_CLOSE: return ASTokenKind.XMLLIST_LITERAL; case TOKEN_PAREN_OPEN: return ASTokenKind.PAREN_OPEN; case TOKEN_PAREN_CLOSE: return ASTokenKind.PAREN_CLOSE; case TOKEN_SQUARE_OPEN: return ASTokenKind.BRACKET_OPEN; case TOKEN_SQUARE_CLOSE: return ASTokenKind.BRACKET_CLOSE; case TOKEN_ATTRIBUTE: return ASTokenKind.METADATA; case TOKEN_SEMICOLON: return ASTokenKind.SEMICOLON; case TOKEN_COLON: return ASTokenKind.COLON; case TOKEN_COMMA: return ASTokenKind.OPERATOR; case TOKEN_E4X_BINDING_CLOSE: return ASTokenKind.E4X_BINDING_CLOSE; case TOKEN_E4X_BINDING_OPEN: return ASTokenKind.E4X_BINDING_OPEN; case TOKEN_TYPED_COLLECTION_CLOSE: case TOKEN_TYPED_LITERAL_CLOSE: return ASTokenKind.TYPED_COLLECTION_CLOSE; case TOKEN_TYPED_COLLECTION_OPEN: case TOKEN_TYPED_LITERAL_OPEN: return ASTokenKind.TYPED_COLLECTION_OPEN; case TOKEN_ELLIPSIS: return ASTokenKind.OPERATOR; case TOKEN_KEYWORD_INCLUDE: return ASTokenKind.INCLUDE; default: if (isKeywordOrContextualReservedWord()) return ASTokenKind.KEYWORD; if (isOperator()) return ASTokenKind.OPERATOR; if (getType() == TOKEN_IDENTIFIER) //handle this after keywords return ASTokenKind.IDENTIFIER; if (isE4X()) return ASTokenKind.XML_LITERAL; } return ASTokenKind.UNKNOWN; } /** * Get {@code IASToken.ASTokenKind} from a given token type. * * @param type AS token type. * @return Token kind. */ public static synchronized ASTokenKind typeToKind(final int type) { TOKEN_TYPE_TO_KIND_CONVERTER.setType(type); return TOKEN_TYPE_TO_KIND_CONVERTER.getTokenKind(); } /** * Surrogate token used by {@link #typeToKind(int)} so that we don't have to * create a new {@code ASToken} object every time we convert. */ private static final ASToken TOKEN_TYPE_TO_KIND_CONVERTER = new ASToken(ASTokenTypes.EOF, UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN, ""); @Override public final boolean isMultiLineComment() { return getType() == HIDDEN_TOKEN_MULTI_LINE_COMMENT || getType() == TOKEN_ASDOC_COMMENT; } }