// Copyright (c) 2017, 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 dart_scanner.error_token;

import '../../scanner/token.dart' show BeginToken, SimpleToken, TokenType;

import '../fasta_codes.dart'
    show
        Code,
        Message,
        messageEncoding,
        templateAsciiControlCharacter,
        templateNonAsciiIdentifier,
        templateNonAsciiWhitespace,
        templateUnmatchedToken,
        templateUnsupportedOperator,
        templateUnterminatedString;

import '../scanner.dart' show Token, unicodeReplacementCharacter;

import '../scanner/recover.dart' show closeBraceFor, closeQuoteFor;

ErrorToken buildUnexpectedCharacterToken(int character, int charOffset) {
  if (character < 0x1f) {
    return new AsciiControlCharacterToken(character, charOffset);
  }
  switch (character) {
    case unicodeReplacementCharacter:
      return new EncodingErrorToken(charOffset);

    /// See [General Punctuation]
    /// (http://www.unicode.org/charts/PDF/U2000.pdf).
    case 0x00A0: // No-break space.
    case 0x1680: // Ogham space mark.
    case 0x180E: // Mongolian vowel separator.
    case 0x2000: // En quad.
    case 0x2001: // Em quad.
    case 0x2002: // En space.
    case 0x2003: // Em space.
    case 0x2004: // Three-per-em space.
    case 0x2005: // Four-per-em space.
    case 0x2006: // Six-per-em space.
    case 0x2007: // Figure space.
    case 0x2008: // Punctuation space.
    case 0x2009: // Thin space.
    case 0x200A: // Hair space.
    case 0x200B: // Zero width space.
    case 0x2028: // Line separator.
    case 0x2029: // Paragraph separator.
    case 0x202F: // Narrow no-break space.
    case 0x205F: // Medium mathematical space.
    case 0x3000: // Ideographic space.
    case 0xFEFF: // Zero width no-break space.
      return new NonAsciiWhitespaceToken(character, charOffset);

    default:
      return new NonAsciiIdentifierToken(character, charOffset);
  }
}

/// Common superclass for all error tokens.
///
/// It's considered an implementation error to access [lexeme] of an
/// [ErrorToken].
abstract class ErrorToken extends SimpleToken {
  ErrorToken(int offset) : super(TokenType.BAD_INPUT, offset, null);

  /// This is a token that wraps around an error message. Return 1
  /// instead of the size of the length of the error message.
  @override
  int get length => 1;

  String get lexeme {
    String errorMsg = assertionMessage.message;

    // Attempt to include the location which is calling the parser
    // in an effort to debug https://github.com/dart-lang/sdk/issues/37528
    RegExp pattern = new RegExp('^#[0-9]* *Parser');
    List<String> traceLines = StackTrace.current.toString().split('\n');
    for (int index = traceLines.length - 2; index >= 0; --index) {
      String line = traceLines[index];
      if (line.startsWith(pattern)) {
        errorMsg = '$errorMsg - ${traceLines[index + 1]}';
        break;
      }
    }

    throw errorMsg;
  }

  Message get assertionMessage;

  Code<dynamic> get errorCode => assertionMessage.code;

  int get character => null;

  String get start => null;

  int get endOffset => null;

  BeginToken get begin => null;

  @override
  Token copy() {
    throw 'unsupported operation';
  }
}

/// Represents an encoding error.
class EncodingErrorToken extends ErrorToken {
  EncodingErrorToken(int charOffset) : super(charOffset);

  String toString() => "EncodingErrorToken()";

  Message get assertionMessage => messageEncoding;
}

/// Represents a non-ASCII character outside a string or comment.
class NonAsciiIdentifierToken extends ErrorToken {
  final int character;

  NonAsciiIdentifierToken(this.character, int charOffset) : super(charOffset);

  String toString() => "NonAsciiIdentifierToken($character)";

  Message get assertionMessage => templateNonAsciiIdentifier.withArguments(
      new String.fromCharCodes([character]), character);
}

/// Represents a non-ASCII whitespace outside a string or comment.
class NonAsciiWhitespaceToken extends ErrorToken {
  final int character;

  NonAsciiWhitespaceToken(this.character, int charOffset) : super(charOffset);

  String toString() => "NonAsciiWhitespaceToken($character)";

  Message get assertionMessage =>
      templateNonAsciiWhitespace.withArguments(character);
}

/// Represents an ASCII control character outside a string or comment.
class AsciiControlCharacterToken extends ErrorToken {
  final int character;

  AsciiControlCharacterToken(this.character, int charOffset)
      : super(charOffset);

  String toString() => "AsciiControlCharacterToken($character)";

  Message get assertionMessage =>
      templateAsciiControlCharacter.withArguments(character);
}

/// Denotes an operator that is not supported in the Dart language.
class UnsupportedOperator extends ErrorToken {
  Token token;

  UnsupportedOperator(this.token, int charOffset) : super(charOffset);

  @override
  Message get assertionMessage =>
      templateUnsupportedOperator.withArguments(token);

  @override
  String toString() => "UnsupportedOperator(${token.lexeme})";
}

/// Represents an unterminated string.
class UnterminatedString extends ErrorToken {
  final String start;
  final int endOffset;

  UnterminatedString(this.start, int charOffset, this.endOffset)
      : super(charOffset);

  String toString() => "UnterminatedString($start)";

  int get charCount => endOffset - charOffset;

  int get length => charCount;

  Message get assertionMessage =>
      templateUnterminatedString.withArguments(start, closeQuoteFor(start));
}

/// Represents an unterminated token.
class UnterminatedToken extends ErrorToken {
  final Message assertionMessage;
  final int endOffset;

  UnterminatedToken(this.assertionMessage, int charOffset, this.endOffset)
      : super(charOffset);

  String toString() => "UnterminatedToken(${assertionMessage.code.name})";

  int get charCount => endOffset - charOffset;
}

/// Represents an open brace without a matching close brace.
///
/// In this case, brace means any of `(`, `{`, `[`, and `<`, parenthesis, curly
/// brace, square brace, and angle brace, respectively.
class UnmatchedToken extends ErrorToken {
  final BeginToken begin;

  UnmatchedToken(BeginToken begin)
      : this.begin = begin,
        super(begin.charOffset);

  String toString() => "UnmatchedToken(${begin.lexeme})";

  Message get assertionMessage =>
      templateUnmatchedToken.withArguments(closeBraceFor(begin.lexeme), begin);
}
