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

import java.io.*;
import java.util.*;
import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.dfa.*;
import org.antlr.v4.runtime.atn.*;

class ParsingResult {
  public int numberOfFileArguments;
  public int numberOfFailures;
}

class DartErrorListener implements ANTLRErrorListener {
  @Override
  public void reportAmbiguity(
      Parser recognizer,
      DFA dfa,
      int startIndex,
      int stopIndex,
      boolean exact,
      BitSet ambigAlts,
      ATNConfigSet configs) {}

  @Override
  public void reportAttemptingFullContext(
      Parser recognizer,
      DFA dfa,
      int startIndex,
      int stopIndex,
      BitSet conflictingAlts,
      ATNConfigSet configs) {}

  @Override
  public void reportContextSensitivity(
      Parser recognizer,
      DFA dfa,
      int startIndex,
      int stopIndex,
      int prediction,
      ATNConfigSet configs) {}

  @Override
  public void syntaxError(Recognizer<?, ?> recognizer,
                          Object offendingSymbol,
                          int line,
                          int charPositionInLine,
                          String msg,
                          RecognitionException e) {
    DartParser.errorHasOccurred = true;
    if (!DartParser.errorHeaderHasBeenPrinted) {
        System.err.println("Syntax error in " + DartParser.filePath + ":");
        DartParser.errorHeaderHasBeenPrinted = true;
    }
    System.err.println("line " + line + ":" + charPositionInLine + " " + msg);
  }
}

/// Class for `main` which will parse files given as command line arguments.
public class SpecParser {
  private static void normalExit() {
    // Terminate with exit code indicating normal termination.
    System.exit(0);
  }

  private static void compileTimeErrorExit() {
    // Terminate with exit code indicating a parse error.
    System.exit(245);
  }

  private static void helpAndExit() {
    System.err.println("Expected arguments: [--verbose] <file>...");
    normalExit();
  }

  /// Receive command lines from standard input and produce feedback about
  /// the outcome on standard output and standard error, as expected by
  /// tools/test.py when running with `--batch`.
  public static void runAsBatch() throws IOException, RecognitionException {
    ParsingResult result = new ParsingResult();
    long startTime = System.currentTimeMillis();
    InputStreamReader input = new InputStreamReader(System.in);
    BufferedReader bufferedInput = new BufferedReader(input);
    String cmdLine;

    System.out.println(">>> BATCH START");
    while ((cmdLine = bufferedInput.readLine()) != null) {
      if (cmdLine.length() == 0) {
        System.out.println(
            ">>> BATCH END (" +
            (result.numberOfFileArguments - result.numberOfFailures) +
            "/" + result.numberOfFileArguments + ") " +
            (System.currentTimeMillis() - startTime) + "ms");
        if (result.numberOfFailures > 0) compileTimeErrorExit();
        normalExit();
      }

      String[] lineArgs = cmdLine.split("\\s+");
      result = parseFiles(lineArgs);
      // Write stderr end token and flush.
      System.err.println(">>> EOF STDERR");
      String resultPassString =
          result.numberOfFailures == 0 ? "PASS" : "PARSE_FAIL";
      System.out.println(">>> TEST " + resultPassString + " " +
          (System.currentTimeMillis() - startTime) + "ms");
      startTime = System.currentTimeMillis();
    }
  }

  /// From [arguments], obey the flags ("--<flag_name>", "-<any>") if known and
  /// ignore them if unknown; treat the remaining [arguments] as file paths and
  /// parse each of them. Return a [ParsingResult] specifying how many files
  /// were parsed, and how many of them failed to parse.
  private static ParsingResult parseFiles(String[] arguments)
      throws IOException, RecognitionException {
    ParsingResult result = new ParsingResult();
    boolean verbose = false;

    result.numberOfFileArguments = arguments.length;
    for (int i = 0; i < arguments.length; i++) {
      String filePath = arguments[i];
      if (filePath.startsWith("-")) {
          result.numberOfFileArguments--;
          if (result.numberOfFileArguments == 0) return result;
          if (filePath.equals("--verbose")) verbose = true;
          if (filePath.equals("--batch")) runAsBatch();
          // Ignore all other flags.
          continue;
      }
      if (verbose) System.err.println("Parsing file: " + filePath);
      DartLexer lexer = new DartLexer(CharStreams.fromFileName(filePath));
      DartParser parser = new DartParser(new CommonTokenStream(lexer));
      ANTLRErrorListener errorListener = new DartErrorListener();
      lexer.addErrorListener(errorListener);
      parser.addErrorListener(errorListener);
      if (!parser.parseLibrary(filePath)) result.numberOfFailures++;
    }
    return result;
  }

  public static void main(String[] args) throws Exception {
    if (args.length == 0) helpAndExit();
    ParsingResult result = parseFiles(args);

    if (result.numberOfFileArguments == 0) {
      helpAndExit();
    } else if (result.numberOfFileArguments == 1) {
      if (result.numberOfFailures > 0) {
        System.err.println("Parsing failed");
        compileTimeErrorExit();
      } else {
        System.out.println("Parsing succeeded.");
      }
    } else {
      if (result.numberOfFailures > 0) {
        System.err.println(
            "Parsed " + result.numberOfFileArguments + " files, " +
            result.numberOfFailures + " failed.");
        compileTimeErrorExit();
      } else {
        System.out.println("Parsed " + result.numberOfFileArguments +
            " files successfully.");
      }
    }
  }
}
