blob: 9f3bbfe9c4c540a7ce11973d3bf2a1931a222036 [file] [log] [blame]
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.google.dart.compiler.parser;
import java.util.HashMap;
import java.util.Map;
/**
* Dart tokens and associated data.
*
* Note: Token ordinals matter for some accessors, so don't change the order of these without
* knowing what you're doing.
*/
public enum Token {
/* End-of-stream. */
EOS(null, 0),
/* Punctuators. */
AT("@", 0),
LPAREN("(", 0),
RPAREN(")", 0),
LBRACK("[", 0),
RBRACK("]", 0),
LBRACE("{", 0),
RBRACE("}", 0),
COLON(":", 0),
SEMICOLON(";", 0),
PERIOD(".", 0),
CASCADE("..", 2),
ELLIPSIS("...", 0),
COMMA(",", 0),
CONDITIONAL("?", 3),
ARROW("=>", 0),
/* Assignment operators. */
ASSIGN("=", 1),
ASSIGN_BIT_OR("|=", 1),
ASSIGN_BIT_XOR("^=", 1),
ASSIGN_BIT_AND("&=", 1),
ASSIGN_SHL("<<=", 1),
ASSIGN_SAR(">>=", 1),
ASSIGN_ADD("+=", 1),
ASSIGN_SUB("-=", 1),
ASSIGN_MUL("*=", 1),
ASSIGN_DIV("/=", 1),
ASSIGN_MOD("%=", 1),
ASSIGN_TRUNC("~/=", 1),
/* Binary operators sorted by precedence. */
OR("||", 4),
AND("&&", 5),
BIT_OR("|", 6),
BIT_XOR("^", 7),
BIT_AND("&", 8),
SHL("<<", 11),
SAR(">>", 11),
ADD("+", 12),
SUB("-", 12),
MUL("*", 13),
DIV("/", 13),
TRUNC("~/", 13),
MOD("%", 13),
/* Compare operators sorted by precedence. */
EQ("==", 9),
NE("!=", 9),
EQ_STRICT("===", 9),
NE_STRICT("!==", 9),
LT("<", 10),
GT(">", 10),
LTE("<=", 10),
GTE(">=", 10),
AS("as", 10),
IS("is", 10),
/* Unary operators. */
NOT("!", 0),
BIT_NOT("~", 0),
/* Count operators (also unary). */
INC("++", 0),
DEC("--", 0),
/* [] operator overloading. */
INDEX("[]", 0),
ASSIGN_INDEX("[]=", 0),
/* Keywords. */
ASSERT("assert", 0),
BREAK("break", 0),
CASE("case", 0),
CATCH("catch", 0),
CLASS("class",0),
CONST("const", 0),
CONTINUE("continue", 0),
DEFAULT("default", 0),
DO("do", 0),
ELSE("else", 0),
EXTENDS("extends", 0),
FINAL("final", 0),
FINALLY("finally", 0),
FOR("for", 0),
IF("if", 0),
IN("in", 0),
NEW("new", 0),
RETURN("return", 0),
SUPER("super", 0),
SWITCH("switch", 0),
THIS("this", 0),
THROW("throw", 0),
TRY("try", 0),
VAR("var", 0),
VOID("void", 0),
WHILE("while", 0),
WITH("with", 0),
/* Literals. */
NULL_LITERAL("null", 0),
TRUE_LITERAL("true", 0),
FALSE_LITERAL("false", 0),
HEX_LITERAL(null, 0),
INTEGER_LITERAL(null, 0),
DOUBLE_LITERAL(null, 0),
STRING(null, 0),
/** String interpolation and string templates. */
STRING_SEGMENT(null, 0),
STRING_LAST_SEGMENT(null, 0),
// STRING_EMBED_EXP_START does not have a unique string representation in the code:
// "$id" yields the token STRING_EMBED_EXP_START after the '$', and similarly
// "${id}" yield the same token for '${'.
STRING_EMBED_EXP_START(null, 0),
STRING_EMBED_EXP_END(null, 0),
// Note: STRING_EMBED_EXP_END uses the same symbol as RBRACE, but it is
// recognized by the scanner when closing embedded expressions in string
// interpolation and string templates.
/* Directives */
LIBRARY("#library", 0),
IMPORT("#import", 0),
SOURCE("#source", 0),
RESOURCE("#resource", 0),
NATIVE("#native", 0),
/* Identifiers (not keywords). */
IDENTIFIER(null, 0),
WHITESPACE(null, 0),
/* Pseudo tokens. */
// If you add another pseudo token, don't forget to update the predicate below.
ILLEGAL(null, 0),
COMMENT(null, 0),
/**
* Non-token to be used by tools where a value outside the range of anything
* returned by the scanner is needed. This is the equivalent of -1 in a C
* tokenizer.
*
* This token is never returned by the scanner. It must have an ordinal
* value outside the range of all tokens returned by the scanner.
*/
NON_TOKEN(null, 0);
private static Map<String, Token> tokens = new HashMap<String, Token>();
static {
for (Token tok : Token.values()) {
if (tok.syntax_ != null) {
tokens.put(tok.syntax_, tok);
}
}
}
/**
* Given a string finds the corresponding token. Pseudo tokens (EOS, ILLEGAL and COMMENT) are
* ignored.
*/
public static Token lookup(String syntax) {
Token token = tokens.get(syntax);
if ("as".equals(syntax)) {
return IDENTIFIER;
}
if (token == null) {
return IDENTIFIER;
}
return token;
}
private final String syntax_;
private final int precedence_;
/**
* The <CODE>syntax</CODE> parameter serves two purposes: 1. map tokens that
* look like identifiers ("null", "true", etc.) to their correct token.
* 2. Find the string-representation of operators.</BR>
* When it is <CODE>null</CODE> then the token either doesn't have a unique
* representation, or it is a pseudo token (which doesn't physically appear
* in the source).
*/
Token(String syntax, int precedence) {
syntax_ = syntax;
precedence_ = precedence;
}
public Token asBinaryOperator() {
int ordinal = ordinal() - ASSIGN_BIT_OR.ordinal() + BIT_OR.ordinal();
return values()[ordinal];
}
public int getPrecedence() {
return precedence_;
}
public String getSyntax() {
return syntax_;
}
public boolean isEqualityOperator() {
int ordinal = ordinal();
return EQ.ordinal() <= ordinal && ordinal <= NE_STRICT.ordinal();
}
public boolean isRelationalOperator() {
int ordinal = ordinal();
return LT.ordinal() <= ordinal && ordinal <= GTE.ordinal();
}
public boolean isAssignmentOperator() {
int ordinal = ordinal();
return ASSIGN.ordinal() <= ordinal && ordinal <= ASSIGN_TRUNC.ordinal();
}
public boolean isBinaryOperator() {
int ordinal = ordinal();
return (ASSIGN.ordinal() <= ordinal && ordinal <= IS.ordinal())
|| (ordinal == COMMA.ordinal());
}
public boolean isCountOperator() {
int ordinal = ordinal();
return INC.ordinal() <= ordinal && ordinal <= DEC.ordinal();
}
public boolean isUnaryOperator() {
int ordinal = ordinal();
return NOT.ordinal() <= ordinal && ordinal <= DEC.ordinal();
}
public boolean isUserDefinableOperator() {
int ordinal = ordinal();
return ((BIT_OR.ordinal() <= ordinal && ordinal <= GTE.ordinal())
|| this == BIT_NOT || this == INDEX || this == ASSIGN_INDEX)
&& this != NE && this != EQ_STRICT && this != NE_STRICT;
}
@Override
public String toString() {
String result = getSyntax();
if (result == null) {
return name();
}
return result;
}
}