// Copyright (c) 2011, 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.

library dart2js.tokens.keywords;

import '../util/characters.dart' as Characters show
    $a;

import 'precedence.dart' show
    PrecedenceInfo;
import 'precedence_constants.dart' as Precedence show
    AS_INFO,
    IS_INFO,
    KEYWORD_INFO;

/**
 * A keyword in the Dart programming language.
 */
class Keyword {
  static const List<Keyword> values = const <Keyword> [
      const Keyword("assert"),
      const Keyword("break"),
      const Keyword("case"),
      const Keyword("catch"),
      const Keyword("class"),
      const Keyword("const"),
      const Keyword("continue"),
      const Keyword("default"),
      const Keyword("do"),
      const Keyword("else"),
      const Keyword("enum"),
      const Keyword("extends"),
      const Keyword("false"),
      const Keyword("final"),
      const Keyword("finally"),
      const Keyword("for"),
      const Keyword("if"),
      const Keyword("in"),
      const Keyword("new"),
      const Keyword("null"),
      const Keyword("rethrow"),
      const Keyword("return"),
      const Keyword("super"),
      const Keyword("switch"),
      const Keyword("this"),
      const Keyword("throw"),
      const Keyword("true"),
      const Keyword("try"),
      const Keyword("var"),
      const Keyword("void"),
      const Keyword("while"),
      const Keyword("with"),

      // TODO(ahe): Don't think this is a reserved word.
      // See: http://dartbug.com/5579
      const Keyword("is", info: Precedence.IS_INFO),

      const Keyword("abstract", isBuiltIn: true),
      const Keyword("as", info: Precedence.AS_INFO, isBuiltIn: true),
      const Keyword("dynamic", isBuiltIn: true),
      const Keyword("export", isBuiltIn: true),
      const Keyword("external", isBuiltIn: true),
      const Keyword("factory", isBuiltIn: true),
      const Keyword("get", isBuiltIn: true),
      const Keyword("implements", isBuiltIn: true),
      const Keyword("import", isBuiltIn: true),
      const Keyword("library", isBuiltIn: true),
      const Keyword("operator", isBuiltIn: true),
      const Keyword("part", isBuiltIn: true),
      const Keyword("set", isBuiltIn: true),
      const Keyword("static", isBuiltIn: true),
      const Keyword("typedef", isBuiltIn: true),

      const Keyword("hide", isPseudo: true),
      const Keyword("native", isPseudo: true),
      const Keyword("of", isPseudo: true),
      const Keyword("on", isPseudo: true),
      const Keyword("show", isPseudo: true),
      const Keyword("source", isPseudo: true),
      const Keyword("deferred", isPseudo: true),
      const Keyword("async", isPseudo: true),
      const Keyword("sync", isPseudo: true),
      const Keyword("await", isPseudo: true),
      const Keyword("yield", isPseudo: true)];

  final String syntax;
  final bool isPseudo;
  final bool isBuiltIn;
  final PrecedenceInfo info;

  static Map<String, Keyword> _keywords;
  static Map<String, Keyword> get keywords {
    if (_keywords == null) {
      _keywords = computeKeywordMap();
    }
    return _keywords;
  }

  const Keyword(this.syntax,
                {this.isPseudo: false,
                 this.isBuiltIn: false,
                 this.info: Precedence.KEYWORD_INFO});

  static Map<String, Keyword> computeKeywordMap() {
    Map<String, Keyword> result = new Map<String, Keyword>();
    for (Keyword keyword in values) {
      result[keyword.syntax] = keyword;
    }
    return result;
  }

  String toString() => syntax;
}

/**
 * Abstract state in a state machine for scanning keywords.
 */
abstract class KeywordState {
  KeywordState(this.keyword);

  KeywordState next(int c);
  final Keyword keyword;

  static KeywordState _KEYWORD_STATE;
  static KeywordState get KEYWORD_STATE {
    if (_KEYWORD_STATE == null) {
      List<String> strings =
          new List<String>(Keyword.values.length);
      for (int i = 0; i < Keyword.values.length; i++) {
        strings[i] = Keyword.values[i].syntax;
      }
      strings.sort((a,b) => a.compareTo(b));
      _KEYWORD_STATE = computeKeywordStateTable(0, strings, 0, strings.length);
    }
    return _KEYWORD_STATE;
  }

  static KeywordState computeKeywordStateTable(int start, List<String> strings,
                                               int offset, int length) {
    List<KeywordState> result = new List<KeywordState>(26);
    assert(length != 0);
    int chunk = 0;
    int chunkStart = -1;
    bool isLeaf = false;
    for (int i = offset; i < offset + length; i++) {
      if (strings[i].length == start) {
        isLeaf = true;
      }
      if (strings[i].length > start) {
        int c = strings[i].codeUnitAt(start);
        if (chunk != c) {
          if (chunkStart != -1) {
            assert(result[chunk - Characters.$a] == null);
            result[chunk - Characters.$a] =
                computeKeywordStateTable(
                    start + 1, strings, chunkStart, i - chunkStart);
          }
          chunkStart = i;
          chunk = c;
        }
      }
    }
    if (chunkStart != -1) {
      assert(result[chunk - Characters.$a] == null);
      result[chunk - Characters.$a] =
        computeKeywordStateTable(start + 1, strings, chunkStart,
                                 offset + length - chunkStart);
    } else {
      assert(length == 1);
      return new LeafKeywordState(strings[offset]);
    }
    if (isLeaf) {
      return new ArrayKeywordState(result, strings[offset]);
    } else {
      return new ArrayKeywordState(result, null);
    }
  }
}

/**
 * A state with multiple outgoing transitions.
 */
class ArrayKeywordState extends KeywordState {
  final List<KeywordState> table;

  ArrayKeywordState(List<KeywordState> this.table, String syntax)
    : super((syntax == null) ? null : Keyword.keywords[syntax]);

  KeywordState next(int c) => table[c - Characters.$a];

  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.write("[");
    if (keyword != null) {
      sb.write("*");
      sb.write(keyword);
      sb.write(" ");
    }
    List<KeywordState> foo = table;
    for (int i = 0; i < foo.length; i++) {
      if (foo[i] != null) {
        sb.write("${new String.fromCharCodes([i + Characters.$a])}: "
                 "${foo[i]}; ");
      }
    }
    sb.write("]");
    return sb.toString();
  }
}

/**
 * A state that has no outgoing transitions.
 */
class LeafKeywordState extends KeywordState {
  LeafKeywordState(String syntax) : super(Keyword.keywords[syntax]);

  KeywordState next(int c) => null;

  String toString() => keyword.syntax;
}
