blob: fa8b1499dddfe1c66b260944c9548026aa4bdabe [file] [log] [blame]
/*
*
* 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.royale.compiler.internal.parsing.as;
import java.lang.reflect.Field;
import org.apache.royale.compiler.config.CompilerDiagnosticsConstants;
import org.apache.royale.compiler.internal.parsing.TokenBase;
import org.apache.royale.compiler.parsing.IASToken;
import org.apache.royale.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:
case TOKEN_MODIFIER_ABSTRACT:
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_MODIFIER_ABSTRACT:
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:
case TOKEN_MODIFIER_ABSTRACT:
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()
{
if ((CompilerDiagnosticsConstants.diagnostics & CompilerDiagnosticsConstants.ASTOKEN) == CompilerDiagnosticsConstants.ASTOKEN)
System.out.println("ASToken waiting for lock for " + getSourcePath() + ":" + getLine() + ":" + getColumn());
initializeTokenNames();
if ((CompilerDiagnosticsConstants.diagnostics & CompilerDiagnosticsConstants.ASTOKEN) == CompilerDiagnosticsConstants.ASTOKEN)
System.out.println("ASToken done with lock for " + getSourcePath() + ":" + getLine() + ":" + getColumn());
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:
case TOKEN_MODIFIER_ABSTRACT:
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;
}
}