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

part of analyzer.parser;

/// Proxy implementation of the analyzer parser, implemented in terms of the
/// Fasta parser.
abstract class ParserAdapter implements Parser {
  @override
  Token currentToken;

  /// The fasta parser being wrapped.
  final fasta.Parser fastaParser;

  /// The builder which creates the analyzer AST data structures
  /// based on the Fasta parser.
  final AstBuilder astBuilder;

  ParserAdapter(this.currentToken, ErrorReporter errorReporter, Uri fileUri,
      FeatureSet featureSet,
      {bool allowNativeClause = false})
      : fastaParser = fasta.Parser(null),
        astBuilder = AstBuilder(errorReporter, fileUri, true, featureSet) {
    fastaParser.listener = astBuilder;
    astBuilder.parser = fastaParser;
    astBuilder.allowNativeClause = allowNativeClause;
  }

  @override
  set allowNativeClause(bool value) {
    astBuilder.allowNativeClause = value;
  }

  @override
  bool get enableOptionalNewAndConst => false;

  @override
  set enableOptionalNewAndConst(bool enable) {}

  @override
  set enableSetLiterals(bool value) {
    // TODO(danrubel): Remove this method once the reference to this flag
    // has been removed from dartfmt.
  }

  @override
  set parseFunctionBodies(bool parseFunctionBodies) {
    astBuilder.parseFunctionBodies = parseFunctionBodies;
  }

  @override
  set parseGenericMethods(_) {}

  /// Append the given token to the end of the token stream,
  /// and update the token's offset.
  void appendToken(Token token, Token newToken) {
    while (!token.next.isEof) {
      token = token.next;
    }
    newToken
      ..offset = token.end
      ..setNext(token.next);
    token.setNext(newToken);
  }

  @override
  Expression parseAdditiveExpression() => parseExpression2();

  @override
  Annotation parseAnnotation() {
    currentToken = fastaParser
        .parseMetadata(fastaParser.syntheticPreviousToken(currentToken))
        .next;
    return astBuilder.pop() as Annotation;
  }

  @override
  Expression parseArgument() {
    currentToken = SimpleToken(TokenType.OPEN_PAREN, 0)..setNext(currentToken);
    appendToken(currentToken, SimpleToken(TokenType.CLOSE_PAREN, 0));
    currentToken = fastaParser
        .parseArguments(fastaParser.syntheticPreviousToken(currentToken))
        .next;
    var invocation = astBuilder.pop() as MethodInvocation;
    return invocation.argumentList.arguments[0];
  }

  @override
  ArgumentList parseArgumentList() {
    currentToken = fastaParser
        .parseArguments(fastaParser.syntheticPreviousToken(currentToken))
        .next;
    var result = astBuilder.pop();
    return result is MethodInvocation
        ? result.argumentList
        : result as ArgumentList;
  }

  @override
  Expression parseAssignableExpression(bool primaryAllowed) =>
      parseExpression2();

  @override
  Expression parseBitwiseAndExpression() => parseExpression2();

  @override
  Expression parseBitwiseOrExpression() => parseExpression2();

  @override
  Expression parseBitwiseXorExpression() => parseExpression2();

  @override
  ClassMember parseClassMember(String className) {
    astBuilder.classDeclaration = astFactory.classDeclaration(
      null,
      null,
      null,
      Token(Keyword.CLASS, 0),
      astFactory.simpleIdentifier(
          fasta.StringToken.fromString(TokenType.IDENTIFIER, className, 6)),
      null,
      null,
      null,
      null,
      null /* leftBracket */,
      <ClassMember>[],
      null /* rightBracket */,
    ) as ClassDeclarationImpl;
    // TODO(danrubel): disambiguate between class and mixin
    currentToken = fastaParser.parseClassMember(currentToken, className);
    //currentToken = fastaParser.parseMixinMember(currentToken);
    ClassDeclaration declaration = astBuilder.classDeclaration;
    astBuilder.classDeclaration = null;
    return declaration.members.isNotEmpty ? declaration.members[0] : null;
  }

  @override
  List<Combinator> parseCombinators() {
    currentToken = fastaParser
        .parseCombinatorStar(fastaParser.syntheticPreviousToken(currentToken))
        .next;
    return astBuilder.pop() as List<Combinator>;
  }

  @override
  CompilationUnit parseCompilationUnit(Token token) {
    currentToken = token;
    return parseCompilationUnit2();
  }

  @override
  CompilationUnit parseCompilationUnit2() {
    currentToken = fastaParser.parseUnit(currentToken);
    return astBuilder.pop() as CompilationUnit;
  }

  @override
  Expression parseConditionalExpression() => parseExpression2();

  @override
  Configuration parseConfiguration() {
    currentToken = fastaParser
        .parseConditionalUri(fastaParser.syntheticPreviousToken(currentToken))
        .next;
    return astBuilder.pop() as Configuration;
  }

  @override
  Expression parseConstExpression() => parseExpression2();

  @override
  CompilationUnit parseDirectives(Token token) {
    currentToken = token;
    return parseDirectives2();
  }

  @override
  CompilationUnit parseDirectives2() {
    currentToken = fastaParser.parseDirectives(currentToken);
    return astBuilder.pop() as CompilationUnit;
  }

  @override
  DottedName parseDottedName() {
    currentToken = fastaParser
        .parseDottedName(fastaParser.syntheticPreviousToken(currentToken))
        .next;
    return astBuilder.pop() as DottedName;
  }

  @override
  Expression parseEqualityExpression() => parseExpression2();

  @override
  Expression parseExpression(Token token) {
    currentToken = token;
    return parseExpression2();
  }

  @override
  Expression parseExpression2() {
    currentToken = fastaParser
        .parseExpression(fastaParser.syntheticPreviousToken(currentToken))
        .next;
    return astBuilder.pop() as Expression;
  }

  @override
  Expression parseExpressionWithoutCascade() => parseExpression2();

  @override
  FormalParameterList parseFormalParameterList({bool inFunctionType = false}) {
    currentToken = fastaParser
        .parseFormalParametersRequiredOpt(
            fastaParser.syntheticPreviousToken(currentToken),
            inFunctionType
                ? fasta.MemberKind.GeneralizedFunctionType
                : fasta.MemberKind.NonStaticMethod)
        .next;
    return astBuilder.pop() as FormalParameterList;
  }

  @override
  FunctionBody parseFunctionBody(
      bool mayBeEmpty, ParserErrorCode emptyErrorCode, bool inExpression) {
    currentToken = fastaParser.parseAsyncModifierOpt(
        fastaParser.syntheticPreviousToken(currentToken));
    currentToken =
        fastaParser.parseFunctionBody(currentToken, inExpression, mayBeEmpty);
    return astBuilder.pop() as FunctionBody;
  }

  @override
  FunctionExpression parseFunctionExpression() =>
      parseExpression2() as FunctionExpression;

  @override
  Expression parseLogicalAndExpression() => parseExpression2();

  @override
  Expression parseLogicalOrExpression() => parseExpression2();

  @override
  Expression parseMultiplicativeExpression() => parseExpression2();

  @override
  InstanceCreationExpression parseNewExpression() =>
      parseExpression2() as InstanceCreationExpression;

  @override
  Expression parsePostfixExpression() => parseExpression2();

  @override
  Identifier parsePrefixedIdentifier() => parseExpression2() as Identifier;

  @override
  Expression parsePrimaryExpression() {
    currentToken = fastaParser
        .parsePrimary(fastaParser.syntheticPreviousToken(currentToken),
            fasta.IdentifierContext.expression)
        .next;
    return astBuilder.pop() as Expression;
  }

  @override
  Expression parseRelationalExpression() => parseExpression2();

  @override
  Expression parseRethrowExpression() => parseExpression2();

  @override
  Expression parseShiftExpression() => parseExpression2();

  @override
  SimpleIdentifier parseSimpleIdentifier(
          {bool allowKeyword = false, bool isDeclaration = false}) =>
      parseExpression2() as SimpleIdentifier;

  @override
  Statement parseStatement(Token token) {
    currentToken = token;
    return parseStatement2();
  }

  @override
  Statement parseStatement2() {
    currentToken = fastaParser
        .parseStatement(fastaParser.syntheticPreviousToken(currentToken))
        .next;
    return astBuilder.pop() as Statement;
  }

  @override
  StringLiteral parseStringLiteral() => parseExpression2() as StringLiteral;

  @override
  SymbolLiteral parseSymbolLiteral() => parseExpression2() as SymbolLiteral;

  @override
  Expression parseThrowExpression() => parseExpression2();

  @override
  Expression parseThrowExpressionWithoutCascade() => parseExpression2();

  AnnotatedNode parseTopLevelDeclaration(bool isDirective) {
    currentToken = fastaParser.parseTopLevelDeclaration(currentToken);
    return (isDirective ? astBuilder.directives : astBuilder.declarations)
        .removeLast();
  }

  @override
  TypeAnnotation parseTypeAnnotation(bool inExpression) {
    Token previous = fastaParser.syntheticPreviousToken(currentToken);
    currentToken = fasta
        .computeType(previous, true, !inExpression)
        .parseType(previous, fastaParser)
        .next;
    return astBuilder.pop() as TypeAnnotation;
  }

  @override
  TypeArgumentList parseTypeArgumentList() {
    Token previous = fastaParser.syntheticPreviousToken(currentToken);
    currentToken = fasta
        .computeTypeParamOrArg(previous)
        .parseArguments(previous, fastaParser)
        .next;
    return astBuilder.pop() as TypeArgumentList;
  }

  @override
  TypeName parseTypeName(bool inExpression) {
    Token previous = fastaParser.syntheticPreviousToken(currentToken);
    currentToken = fasta
        .computeType(previous, true, !inExpression)
        .parseType(previous, fastaParser)
        .next;
    return astBuilder.pop() as TypeName;
  }

  @override
  TypeParameter parseTypeParameter() {
    currentToken = SyntheticBeginToken(TokenType.LT, 0)
      ..endGroup = SyntheticToken(TokenType.GT, 0)
      ..setNext(currentToken);
    appendToken(currentToken, currentToken.endGroup);
    TypeParameterList typeParams = parseTypeParameterList();
    return typeParams.typeParameters[0];
  }

  @override
  TypeParameterList parseTypeParameterList() {
    Token token = fastaParser.syntheticPreviousToken(currentToken);
    currentToken = fasta
        .computeTypeParamOrArg(token, true)
        .parseVariables(token, fastaParser)
        .next;
    return astBuilder.pop() as TypeParameterList;
  }

  @override
  Expression parseUnaryExpression() => parseExpression2();
}

/// Replacement parser based on Fasta.
class _Parser2 extends ParserAdapter {
  /// The source being parsed.
  @override
  final Source _source;

  @override
  bool enableUriInPartOf = true;

  factory _Parser2(
      Source source, AnalysisErrorListener errorListener, FeatureSet featureSet,
      {bool allowNativeClause = false}) {
    var errorReporter = ErrorReporter(
      errorListener,
      source,
      isNonNullableByDefault: featureSet.isEnabled(Feature.non_nullable),
    );
    return _Parser2._(source, errorReporter, source.uri, featureSet,
        allowNativeClause: allowNativeClause);
  }

  _Parser2._(this._source, ErrorReporter errorReporter, Uri fileUri,
      FeatureSet featureSet, {bool allowNativeClause = false})
      : super(null, errorReporter, fileUri, featureSet,
            allowNativeClause: allowNativeClause);

  @override
  dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
