// 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;
  }
}
