| // Copyright (c) 2019, 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 'dart:io'; |
| import 'dart:typed_data'; |
| |
| import 'package:_fe_analyzer_shared/src/parser/parser.dart'; |
| import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart'; |
| import 'package:_fe_analyzer_shared/src/parser/listener.dart'; |
| import 'package:_fe_analyzer_shared/src/parser/member_kind.dart'; |
| import 'package:_fe_analyzer_shared/src/scanner/utf8_bytes_scanner.dart'; |
| import 'package:_fe_analyzer_shared/src/scanner/token.dart'; |
| import 'package:dart_style/dart_style.dart' show DartFormatter; |
| |
| StringSink out; |
| |
| main(List<String> args) { |
| if (args.contains("--stdout")) { |
| out = stdout; |
| } else { |
| out = new StringBuffer(); |
| } |
| File f = new File.fromUri(Platform.script |
| .resolve("../../_fe_analyzer_shared/lib/src/parser/parser_impl.dart")); |
| List<int> rawBytes = f.readAsBytesSync(); |
| |
| Uint8List bytes = new Uint8List(rawBytes.length + 1); |
| bytes.setRange(0, rawBytes.length, rawBytes); |
| |
| Utf8BytesScanner scanner = new Utf8BytesScanner(bytes, includeComments: true); |
| Token firstToken = scanner.tokenize(); |
| |
| out.write(r""" |
| // Copyright (c) 2019, 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/assert.dart'; |
| import 'package:_fe_analyzer_shared/src/parser/block_kind.dart'; |
| import 'package:_fe_analyzer_shared/src/parser/declaration_kind.dart'; |
| import 'package:_fe_analyzer_shared/src/parser/directive_context.dart'; |
| import 'package:_fe_analyzer_shared/src/parser/formal_parameter_kind.dart'; |
| import 'package:_fe_analyzer_shared/src/parser/identifier_context.dart'; |
| import 'package:_fe_analyzer_shared/src/parser/listener.dart' show Listener; |
| import 'package:_fe_analyzer_shared/src/parser/member_kind.dart'; |
| import 'package:_fe_analyzer_shared/src/parser/parser.dart' show Parser; |
| import 'package:_fe_analyzer_shared/src/parser/token_stream_rewriter.dart'; |
| import 'package:_fe_analyzer_shared/src/parser/type_info.dart'; |
| import 'package:_fe_analyzer_shared/src/scanner/scanner.dart'; |
| import 'package:_fe_analyzer_shared/src/scanner/token.dart'; |
| import 'package:front_end/src/fasta/fasta_codes.dart'; |
| |
| // THIS FILE IS AUTO GENERATED BY 'test/parser_test_parser_creator.dart' |
| // Run e.g. |
| /* |
| out/ReleaseX64/dart \ |
| pkg/front_end/test/parser_test_parser_creator.dart \ |
| > pkg/front_end/test/parser_test_parser.dart |
| */ |
| |
| class TestParser extends Parser { |
| int indent = 0; |
| StringBuffer sb = new StringBuffer(); |
| final bool trace; |
| |
| TestParser(Listener listener, this.trace) : super(listener); |
| |
| String createTrace() { |
| List<String> traceLines = StackTrace.current.toString().split("\n"); |
| for (int i = 0; i < traceLines.length; i++) { |
| // Find first one that's not any of the denylisted ones. |
| String line = traceLines[i]; |
| if (line.contains("parser_test_listener.dart:") || |
| line.contains("parser_suite.dart:") || |
| line.contains("parser_test_parser.dart:") || |
| line == "<asynchronous suspension>") continue; |
| return line.substring(line.indexOf("(") + 1, line.lastIndexOf(")")); |
| } |
| return "N/A"; |
| } |
| |
| void doPrint(String s) { |
| String traceString = ""; |
| if (trace) traceString = " (${createTrace()})"; |
| sb.writeln((" " * indent) + s + traceString); |
| } |
| """); |
| |
| ParserCreatorListener listener = new ParserCreatorListener(); |
| ClassMemberParser parser = new ClassMemberParser(listener); |
| parser.parseUnit(firstToken); |
| |
| out.writeln("}"); |
| |
| if (out is StringBuffer) { |
| String text = new DartFormatter().format("$out"); |
| if (args.isNotEmpty) { |
| new File(args.first).writeAsStringSync(text); |
| } else { |
| stdout.write(text); |
| } |
| } |
| } |
| |
| class ParserCreatorListener extends Listener { |
| bool insideParserClass = false; |
| String currentMethodName; |
| List<String> parameters = <String>[]; |
| List<String> parametersNamed = <String>[]; |
| |
| void beginClassDeclaration(Token begin, Token abstractToken, Token name) { |
| if (name.lexeme == "Parser") insideParserClass = true; |
| } |
| |
| void endClassDeclaration(Token beginToken, Token endToken) { |
| insideParserClass = false; |
| } |
| |
| void beginMethod(Token externalToken, Token staticToken, Token covariantToken, |
| Token varFinalOrConst, Token getOrSet, Token name) { |
| currentMethodName = name.lexeme; |
| } |
| |
| void endClassConstructor(Token getOrSet, Token beginToken, Token beginParam, |
| Token beginInitializers, Token endToken) { |
| parameters.clear(); |
| parametersNamed.clear(); |
| currentMethodName = null; |
| } |
| |
| void endClassMethod(Token getOrSet, Token beginToken, Token beginParam, |
| Token beginInitializers, Token endToken) { |
| if (insideParserClass && !currentMethodName.startsWith("_")) { |
| Token token = beginToken; |
| Token latestToken; |
| out.write(" "); |
| while (true) { |
| if (troubleParameterTokens.containsKey(token)) { |
| if (latestToken != null && latestToken.charEnd < token.charOffset) { |
| out.write(" "); |
| } |
| out.write("dynamic"); |
| token = troubleParameterTokens[token]; |
| } |
| if (latestToken != null && latestToken.charEnd < token.charOffset) { |
| out.write(" "); |
| } |
| if (token is SimpleToken && token.type == TokenType.FUNCTION) { |
| // Don't write out the '=>'. |
| out.write("{"); |
| break; |
| } |
| out.write(token.lexeme); |
| if (token is BeginToken && |
| token.type == TokenType.OPEN_CURLY_BRACKET && |
| (beginParam == null || |
| beginParam.endGroup == endToken || |
| token.charOffset > beginParam.endGroup.charOffset)) { |
| break; |
| } |
| if (token == endToken) { |
| throw token.runtimeType; |
| } |
| latestToken = token; |
| token = token.next; |
| } |
| |
| out.write("\n "); |
| out.write("doPrint('$currentMethodName("); |
| String separator = ""; |
| for (int i = 0; i < parameters.length; i++) { |
| out.write(separator); |
| out.write(r"' '$"); |
| out.write(parameters[i]); |
| separator = ", "; |
| } |
| for (int i = 0; i < parametersNamed.length; i++) { |
| out.write(separator); |
| out.write("' '"); |
| out.write(parametersNamed[i]); |
| out.write(r": $"); |
| out.write(parametersNamed[i]); |
| separator = ", "; |
| } |
| out.write(")');\n "); |
| |
| out.write("indent++;\n "); |
| out.write("var result = super.$currentMethodName"); |
| if (getOrSet != null && getOrSet.lexeme == "get") { |
| // no parens |
| out.write(";\n "); |
| } else { |
| out.write("("); |
| String separator = ""; |
| for (int i = 0; i < parameters.length; i++) { |
| out.write(separator); |
| out.write(parameters[i]); |
| separator = ", "; |
| } |
| for (int i = 0; i < parametersNamed.length; i++) { |
| out.write(separator); |
| out.write(parametersNamed[i]); |
| out.write(": "); |
| out.write(parametersNamed[i]); |
| separator = ", "; |
| } |
| out.write(");\n "); |
| } |
| out.write("indent--;\n "); |
| out.write("return result;\n "); |
| out.write("}"); |
| out.write("\n\n"); |
| } |
| parameters.clear(); |
| parametersNamed.clear(); |
| currentMethodName = null; |
| } |
| |
| int formalParametersNestLevel = 0; |
| void beginFormalParameters(Token token, MemberKind kind) { |
| formalParametersNestLevel++; |
| } |
| |
| void endFormalParameters( |
| int count, Token beginToken, Token endToken, MemberKind kind) { |
| formalParametersNestLevel--; |
| } |
| |
| Token currentFormalParameterToken; |
| |
| void beginFormalParameter(Token token, MemberKind kind, Token requiredToken, |
| Token covariantToken, Token varFinalOrConst) { |
| if (formalParametersNestLevel == 1) { |
| currentFormalParameterToken = token; |
| } |
| } |
| |
| Map<Token, Token> troubleParameterTokens = {}; |
| |
| void handleIdentifier(Token token, IdentifierContext context) { |
| if (formalParametersNestLevel > 0 && token.lexeme.startsWith("_")) { |
| troubleParameterTokens[currentFormalParameterToken] = null; |
| } |
| } |
| |
| void endFormalParameter( |
| Token thisKeyword, |
| Token periodAfterThis, |
| Token nameToken, |
| Token initializerStart, |
| Token initializerEnd, |
| FormalParameterKind kind, |
| MemberKind memberKind) { |
| if (formalParametersNestLevel != 1) { |
| return; |
| } |
| if (troubleParameterTokens.containsKey(currentFormalParameterToken)) { |
| troubleParameterTokens[currentFormalParameterToken] = nameToken; |
| } |
| currentFormalParameterToken = null; |
| if (kind == FormalParameterKind.optionalNamed) { |
| parametersNamed.add(nameToken.lexeme); |
| } else { |
| parameters.add(nameToken.lexeme); |
| } |
| } |
| } |