Files
sdk/pkg/front_end/test/parser_test_parser_creator.dart
T
Jens Johansen 3660b9ecc7 [parser] New syntax for null aware index (2nd try)
This reverts commit bc4893a3b3.

The previous attempt failed because when we check if something is a
conditional expression we used a rewriter that didn't actually rewrite.
This further down the line (still checking if we can parse the expression)
results in errors occurring (that wouldn't have occurred if the rewrite
had happened) and the conclusion was thus that it wasn't a conditional
expression and we parsed it as a null-aware index operator (which gave
errors because it wasn't).

This 2nd try solves it by having a rewriter that actually rewrites,
but then allows to undo the rewrites after we're done parsing.

Change-Id: Ide3c0d6a870d4dc18b6d9475b0227d93c733dc7f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/136624
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
2020-02-26 13:31:52 +00:00

269 lines
8.8 KiB
Dart

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