|  | // 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 { | 
|  | public void reportAmbiguity( | 
|  | Parser recognizer, | 
|  | DFA dfa, | 
|  | int startIndex, | 
|  | int stopIndex, | 
|  | boolean exact, | 
|  | BitSet ambigAlts, | 
|  | ATNConfigSet configs) {} | 
|  |  | 
|  | public void reportAttemptingFullContext( | 
|  | Parser recognizer, | 
|  | DFA dfa, | 
|  | int startIndex, | 
|  | int stopIndex, | 
|  | BitSet conflictingAlts, | 
|  | ATNConfigSet configs) {} | 
|  |  | 
|  | public void reportContextSensitivity( | 
|  | Parser recognizer, | 
|  | DFA dfa, | 
|  | int startIndex, | 
|  | int stopIndex, | 
|  | int prediction, | 
|  | ATNConfigSet configs) {} | 
|  |  | 
|  | public void syntaxError( | 
|  | Recognizer<?,?> recognizer, | 
|  | Object offendingSymbol, | 
|  | int line, | 
|  | int charPositionInLine, | 
|  | String msg, | 
|  | RecognitionException e) { | 
|  | if (!DartParser.errorHasOccurred) DartParser.prepareForErrors(); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// 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."); | 
|  | } | 
|  | } | 
|  | } | 
|  | } |