// 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.string_scanner;

import '../../scanner/token.dart' show TokenType;

import 'array_based_scanner.dart' show ArrayBasedScanner;

import 'token.dart' show CommentToken, DartDocToken, StringToken;

/**
 * Scanner that reads from a String and creates tokens that points to
 * substrings.
 */
class StringScanner extends ArrayBasedScanner {
  /** The file content. */
  String string;

  /** The current offset in [string]. */
  int scanOffset = -1;

  StringScanner(String string,
      {bool includeComments: false,
      bool scanGenericMethodComments: false,
      bool scanLazyAssignmentOperators: false})
      : string = ensureZeroTermination(string),
        super(includeComments, scanGenericMethodComments,
            scanLazyAssignmentOperators);

  static String ensureZeroTermination(String string) {
    return (string.isEmpty || string.codeUnitAt(string.length - 1) != 0)
        // TODO(lry): abort instead of copying the array, or warn?
        ? string + '\x00'
        : string;
  }

  int advance() => string.codeUnitAt(++scanOffset);
  int peek() => string.codeUnitAt(scanOffset + 1);

  int get stringOffset => scanOffset;

  int currentAsUnicode(int next) => next;

  void handleUnicode(int startScanOffset) {}

  @override
  StringToken createSubstringToken(TokenType type, int start, bool asciiOnly,
      [int extraOffset = 0]) {
    return new StringToken.fromSubstring(
        type, string, start, scanOffset + extraOffset, tokenStart,
        canonicalize: true, precedingComments: comments);
  }

  @override
  CommentToken createCommentToken(TokenType type, int start, bool asciiOnly,
      [int extraOffset = 0]) {
    return new CommentToken.fromSubstring(
        type, string, start, scanOffset + extraOffset, tokenStart,
        canonicalize: true);
  }

  @override
  DartDocToken createDartDocToken(TokenType type, int start, bool asciiOnly,
      [int extraOffset = 0]) {
    return new DartDocToken.fromSubstring(
        type, string, start, scanOffset + extraOffset, tokenStart,
        canonicalize: true);
  }

  bool atEndOfFile() => scanOffset >= string.length - 1;
}

/**
 * Scanner that creates tokens for a part of a larger [String], where the part
 * starts at the [baseOffset].
 */
class SubStringScanner extends StringScanner {
  final int baseOffset;

  SubStringScanner(this.baseOffset, String string,
      {bool includeComments: false})
      : super(string, includeComments: includeComments);

  @override
  void beginToken() {
    tokenStart = baseOffset + stringOffset;
  }
}
