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

import 'package:_fe_analyzer_shared/src/parser/parser.dart' as fasta;
import 'package:_fe_analyzer_shared/src/parser/type_info.dart' as fasta;
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:analyzer/source/source.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart'
    show ExperimentalFeaturesStatus;
import 'package:analyzer/src/dart/ast/ast.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/fasta/ast_builder.dart';

export 'package:analyzer/src/dart/error/syntactic_errors.dart';

/// A parser used to parse tokens into an AST structure.
class Parser {
  late Token currentToken;

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

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

  Parser(
    Source source,
    DiagnosticListener diagnosticListener, {
    required FeatureSet featureSet,
    bool allowNativeClause = true,
    required LibraryLanguageVersion languageVersion,
    required LineInfo lineInfo,
  }) : astBuilder = AstBuilder(
         DiagnosticReporter(diagnosticListener, source),
         source.uri,
         true,
         featureSet,
         languageVersion,
         lineInfo,
       ) {
    fastaParser = fasta.Parser(
      astBuilder,
      experimentalFeatures: ExperimentalFeaturesStatus(featureSet),
    );
    astBuilder.parser = fastaParser;
    astBuilder.allowNativeClause = allowNativeClause;
  }

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

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

  /// 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);
  }

  Expression parseAdditiveExpression() => parseExpression2();

  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];
  }

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

  Expression parseBitwiseAndExpression() => parseExpression2();

  Expression parseBitwiseOrExpression() => parseExpression2();

  Expression parseBitwiseXorExpression() => parseExpression2();

  CompilationUnitImpl parseCompilationUnit(Token token) {
    currentToken = token;
    return parseCompilationUnit2();
  }

  CompilationUnitImpl parseCompilationUnit2() {
    currentToken = fastaParser.parseUnit(currentToken);
    return astBuilder.pop() as CompilationUnitImpl;
  }

  Expression parseConditionalExpression() => parseExpression2();

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

  Expression parseConstExpression() => parseExpression2();

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

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

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

  Expression parseEqualityExpression() => parseExpression2();

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

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

  Expression parseExpressionWithoutCascade() => parseExpression2();

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

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

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

  Expression parseLogicalAndExpression() => parseExpression2();

  Expression parseLogicalOrExpression() => parseExpression2();

  Expression parseMultiplicativeExpression() => parseExpression2();

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

  Expression parsePostfixExpression() => parseExpression2();

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

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

  Expression parseRelationalExpression() => parseExpression2();

  Expression parseRethrowExpression() => parseExpression2();

  Expression parseShiftExpression() => parseExpression2();

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

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

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

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

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

  Expression parseThrowExpression() => parseExpression2();

  Expression parseThrowExpressionWithoutCascade() => parseExpression2();

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

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

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

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

  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];
  }

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

  Expression parseUnaryExpression() => parseExpression2();
}
