// 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.scanner.array_based;

import '../io/source_file.dart' show
    SourceFile;
import '../tokens/keyword.dart' show
    Keyword;
import '../tokens/precedence.dart' show
    PrecedenceInfo;
import '../tokens/precedence_constants.dart' as Precedence show
    COMMENT_INFO,
    EOF_INFO;
import '../tokens/token.dart' show
    BeginGroupToken,
    ErrorToken,
    KeywordToken,
    SymbolToken,
    Token;
import '../tokens/token_constants.dart' as Tokens show
    LT_TOKEN,
    OPEN_CURLY_BRACKET_TOKEN,
    STRING_INTERPOLATION_TOKEN;
import '../util/characters.dart' show
    $LF,
    $STX;
import '../util/util.dart' show
    Link;

import 'scanner.dart' show
    AbstractScanner;

abstract class ArrayBasedScanner extends AbstractScanner {
  ArrayBasedScanner(SourceFile file, bool includeComments)
      : super(file, includeComments);

  /**
   * The stack of open groups, e.g [: { ... ( .. :]
   * Each BeginGroupToken has a pointer to the token where the group
   * ends. This field is set when scanning the end group token.
   */
  Link<BeginGroupToken> groupingStack = const Link<BeginGroupToken>();

  /**
   * Appends a fixed token whose kind and content is determined by [info].
   * Appends an *operator* token from [info].
   *
   * An operator token represent operators like ':', '.', ';', '&&', '==', '--',
   * '=>', etc.
   */
  void appendPrecedenceToken(PrecedenceInfo info) {
    tail.next = new SymbolToken(info, tokenStart);
    tail = tail.next;
  }

  /**
   * Appends a fixed token based on whether the current char is [choice] or not.
   * If the current char is [choice] a fixed token whose kind and content
   * is determined by [yes] is appended, otherwise a fixed token whose kind
   * and content is determined by [no] is appended.
   */
  int select(int choice, PrecedenceInfo yes, PrecedenceInfo no) {
    int next = advance();
    if (identical(next, choice)) {
      appendPrecedenceToken(yes);
      return advance();
    } else {
      appendPrecedenceToken(no);
      return next;
    }
  }

  /**
   * Appends a keyword token whose kind is determined by [keyword].
   */
  void appendKeywordToken(Keyword keyword) {
    String syntax = keyword.syntax;
    // Type parameters and arguments cannot contain 'this' or 'super'.
    if (identical(syntax, 'this') || identical(syntax, 'super')) {
      discardOpenLt();
    }
    tail.next = new KeywordToken(keyword, tokenStart);
    tail = tail.next;
  }

  void appendEofToken() {
    beginToken();
    discardOpenLt();
    while (!groupingStack.isEmpty) {
      unmatchedBeginGroup(groupingStack.head);
      groupingStack = groupingStack.tail;
    }
    tail.next = new SymbolToken(Precedence.EOF_INFO, tokenStart);
    tail = tail.next;
    // EOF points to itself so there's always infinite look-ahead.
    tail.next = tail;
  }

  /**
   * Notifies scanning a whitespace character. Note that [appendWhiteSpace] is
   * not always invoked for [$SPACE] characters.
   *
   * This method is used by the scanners to track line breaks and create the
   * [lineStarts] map.
   */
  void appendWhiteSpace(int next) {
    if (next == $LF && file != null) {
      lineStarts.add(stringOffset + 1); // +1, the line starts after the $LF.
    }
  }

  /**
   * Notifies on [$LF] characters in multi-line comments or strings.
   *
   * This method is used by the scanners to track line breaks and create the
   * [lineStarts] map.
   */
  void lineFeedInMultiline() {
    if (file != null) {
      lineStarts.add(stringOffset + 1);
    }
  }

  /**
   * Appends a token that begins a new group, represented by [value].
   * Group begin tokens are '{', '(', '[' and '${'.
   */
  void appendBeginGroup(PrecedenceInfo info) {
    Token token = new BeginGroupToken(info, tokenStart);
    tail.next = token;
    tail = tail.next;

    // { (  [ ${ cannot appear inside a type parameters / arguments.
    if (!identical(info.kind, Tokens.LT_TOKEN)) discardOpenLt();
    groupingStack = groupingStack.prepend(token);
  }

  /**
   * Appends a token that begins an end group, represented by [value].
   * It handles the group end tokens '}', ')' and ']'. The tokens '>' and
   * '>>' are handled separately bo [appendGt] and [appendGtGt].
   */
  int appendEndGroup(PrecedenceInfo info, int openKind) {
    assert(!identical(openKind, Tokens.LT_TOKEN)); // openKind is < for > and >>
    discardBeginGroupUntil(openKind);
    appendPrecedenceToken(info);
    Token close = tail;
    if (groupingStack.isEmpty) {
      return advance();
    }
    BeginGroupToken begin = groupingStack.head;
    if (!identical(begin.kind, openKind)) {
      assert(begin.kind == Tokens.STRING_INTERPOLATION_TOKEN &&
             openKind == Tokens.OPEN_CURLY_BRACKET_TOKEN);
      // We're ending an interpolated expression.
      begin.endGroup = close;
      groupingStack = groupingStack.tail;
      // Using "start-of-text" to signal that we're back in string
      // scanning mode.
      return $STX;
    }
    begin.endGroup = close;
    groupingStack = groupingStack.tail;
    return advance();
  }

  /**
   * Discards begin group tokens until a match with [openKind] is found.
   * This recovers nicely from from a situation like "{[}".
   */
  void discardBeginGroupUntil(int openKind) {
    while (!groupingStack.isEmpty) {
      // Don't report unmatched errors for <; it is also the less-than operator.
      discardOpenLt();
      if (groupingStack.isEmpty) return;
      BeginGroupToken begin = groupingStack.head;
      if (openKind == begin.kind) return;
      if (openKind == Tokens.OPEN_CURLY_BRACKET_TOKEN &&
          begin.kind == Tokens.STRING_INTERPOLATION_TOKEN) return;
      unmatchedBeginGroup(begin);
      groupingStack = groupingStack.tail;
    }
  }

  /**
   * Appends a token for '>'.
   * This method does not issue unmatched errors, because > is also the
   * greater-than operator. It does not necessarily have to close a group.
   */
  void appendGt(PrecedenceInfo info) {
    appendPrecedenceToken(info);
    if (groupingStack.isEmpty) return;
    if (identical(groupingStack.head.kind, Tokens.LT_TOKEN)) {
      groupingStack.head.endGroup = tail;
      groupingStack = groupingStack.tail;
    }
  }

  /**
   * Appends a token for '>>'.
   * This method does not issue unmatched errors, because >> is also the
   * shift operator. It does not necessarily have to close a group.
   */
  void appendGtGt(PrecedenceInfo info) {
    appendPrecedenceToken(info);
    if (groupingStack.isEmpty) return;
    if (identical(groupingStack.head.kind, Tokens.LT_TOKEN)) {
      // Don't assign endGroup: in "T<U<V>>", the '>>' token closes the outer
      // '<', the inner '<' is left without endGroup.
      groupingStack = groupingStack.tail;
    }
    if (groupingStack.isEmpty) return;
    if (identical(groupingStack.head.kind, Tokens.LT_TOKEN)) {
      groupingStack.head.endGroup = tail;
      groupingStack = groupingStack.tail;
    }
  }

  void appendComment(start, bool asciiOnly) {
    if (!includeComments) return;
    appendSubstringToken(Precedence.COMMENT_INFO, start, asciiOnly);
  }

  void appendErrorToken(ErrorToken token) {
    tail.next = token;
    tail = token;
  }

  /**
   * This method is called to discard '<' from the "grouping" stack.
   *
   * [PartialParser.skipExpression] relies on the fact that we do not
   * create groups for stuff like:
   * [:a = b < c, d = e > f:].
   *
   * In other words, this method is called when the scanner recognizes
   * something which cannot possibly be part of a type parameter/argument
   * list, like the '=' in the above example.
   */
  void discardOpenLt() {
    while (!groupingStack.isEmpty
        && identical(groupingStack.head.kind, Tokens.LT_TOKEN)) {
      groupingStack = groupingStack.tail;
    }
  }
}
