Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Side by Side Diff: pkg/front_end/lib/src/fasta/parser/parser.dart

Issue 3001993002: improve fasta export directive recovery (Closed)
Patch Set: rebase Created 3 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/compiler/lib/src/parser/element_listener.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library fasta.parser.parser; 5 library fasta.parser.parser;
6 6
7 import '../fasta_codes.dart' show Code, Message, Template; 7 import '../fasta_codes.dart' show Code, Message, Template;
8 8
9 import '../fasta_codes.dart' as fasta; 9 import '../fasta_codes.dart' as fasta;
10 10
11 import '../scanner.dart' show ErrorToken, Token; 11 import '../scanner.dart' show ErrorToken, Token;
12 12
13 import '../scanner/recover.dart' show closeBraceFor, skipToEof; 13 import '../scanner/recover.dart' show closeBraceFor, skipToEof;
14 14
15 import '../../scanner/token.dart' 15 import '../../scanner/token.dart'
16 show 16 show
17 ASSIGNMENT_PRECEDENCE, 17 ASSIGNMENT_PRECEDENCE,
18 BeginToken, 18 BeginToken,
19 CASCADE_PRECEDENCE, 19 CASCADE_PRECEDENCE,
20 EQUALITY_PRECEDENCE, 20 EQUALITY_PRECEDENCE,
21 POSTFIX_PRECEDENCE, 21 POSTFIX_PRECEDENCE,
22 RELATIONAL_PRECEDENCE, 22 RELATIONAL_PRECEDENCE,
23 SyntheticStringToken,
24 SyntheticToken,
23 TokenType; 25 TokenType;
24 26
25 import '../scanner/token.dart' show isUserDefinableOperator; 27 import '../scanner/token.dart' show isUserDefinableOperator;
26 28
27 import '../scanner/token_constants.dart' 29 import '../scanner/token_constants.dart'
28 show 30 show
29 COMMA_TOKEN, 31 COMMA_TOKEN,
30 DOUBLE_TOKEN, 32 DOUBLE_TOKEN,
31 EOF_TOKEN, 33 EOF_TOKEN,
32 EQ_TOKEN, 34 EQ_TOKEN,
(...skipping 28 matching lines...) Expand all
61 FormalParameterKind, 63 FormalParameterKind,
62 isMandatoryFormalParameterKind, 64 isMandatoryFormalParameterKind,
63 isOptionalPositionalFormalParameterKind; 65 isOptionalPositionalFormalParameterKind;
64 66
65 import 'identifier_context.dart' show IdentifierContext; 67 import 'identifier_context.dart' show IdentifierContext;
66 68
67 import 'listener.dart' show Listener; 69 import 'listener.dart' show Listener;
68 70
69 import 'member_kind.dart' show MemberKind; 71 import 'member_kind.dart' show MemberKind;
70 72
73 import 'token_stream_rewriter.dart';
74
71 import 'type_continuation.dart' 75 import 'type_continuation.dart'
72 show TypeContinuation, typeContiunationFromFormalParameterKind; 76 show TypeContinuation, typeContiunationFromFormalParameterKind;
73 77
74 import 'util.dart' show closeBraceTokenFor, optional; 78 import 'util.dart' show closeBraceTokenFor, optional;
75 79
76 /// An event generating parser of Dart programs. This parser expects all tokens 80 /// An event generating parser of Dart programs. This parser expects all tokens
77 /// in a linked list (aka a token stream). 81 /// in a linked list (aka a token stream).
78 /// 82 ///
79 /// The class [Scanner] is used to generate a token stream. See the file 83 /// The class [Scanner] is used to generate a token stream. See the file
80 /// [scanner.dart](../scanner.dart). 84 /// [scanner.dart](../scanner.dart).
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 205
202 Uri get uri => listener.uri; 206 Uri get uri => listener.uri;
203 207
204 bool mayParseFunctionExpressions = true; 208 bool mayParseFunctionExpressions = true;
205 209
206 /// Represents parser state: what asynchronous syntax is allowed in the 210 /// Represents parser state: what asynchronous syntax is allowed in the
207 /// function being currently parsed. In rare situations, this can be set by 211 /// function being currently parsed. In rare situations, this can be set by
208 /// external clients, for example, to parse an expression outside a function. 212 /// external clients, for example, to parse an expression outside a function.
209 AsyncModifier asyncState = AsyncModifier.Sync; 213 AsyncModifier asyncState = AsyncModifier.Sync;
210 214
215 /// The first token in the parse stream and used during parser recovery.
216 /// This is automatically set by the [parseUnit] method,
217 /// but must be manually set when any other parse method is called.
218 /// If not set, then the parser will call [handleUnrecoverableError]
219 /// rather than rewriting the token stream
220 /// and calling [handleRecoverableError].
221 Token firstToken;
222
223 /// A rewriter for inserting synthetic tokens.
224 /// Access using [rewriter] for lazy initialization.
225 TokenStreamRewriter cachedRewriter;
226
227 TokenStreamRewriter get rewriter {
228 assert(firstToken != null, 'firstToken must be set for parser recovery');
229 cachedRewriter ??= new TokenStreamRewriter(firstToken);
230 return cachedRewriter;
231 }
232
211 Parser(this.listener); 233 Parser(this.listener);
212 234
213 bool get inGenerator { 235 bool get inGenerator {
214 return asyncState == AsyncModifier.AsyncStar || 236 return asyncState == AsyncModifier.AsyncStar ||
215 asyncState == AsyncModifier.SyncStar; 237 asyncState == AsyncModifier.SyncStar;
216 } 238 }
217 239
218 bool get inAsync { 240 bool get inAsync {
219 return asyncState == AsyncModifier.Async || 241 return asyncState == AsyncModifier.Async ||
220 asyncState == AsyncModifier.AsyncStar; 242 asyncState == AsyncModifier.AsyncStar;
221 } 243 }
222 244
223 bool get inPlainSync => asyncState == AsyncModifier.Sync; 245 bool get inPlainSync => asyncState == AsyncModifier.Sync;
224 246
225 Token parseUnit(Token token) { 247 Token parseUnit(Token token) {
248 firstToken = token;
226 listener.beginCompilationUnit(token); 249 listener.beginCompilationUnit(token);
227 int count = 0; 250 int count = 0;
228 while (!identical(token.kind, EOF_TOKEN)) { 251 while (!identical(token.kind, EOF_TOKEN)) {
229 token = parseTopLevelDeclaration(token); 252 token = parseTopLevelDeclaration(token);
230 count++; 253 count++;
231 } 254 }
232 listener.endCompilationUnit(count, token); 255 listener.endCompilationUnit(count, token);
256 // Clear fields that could lead to memory leak.
257 firstToken = null;
258 cachedRewriter = null;
233 return token; 259 return token;
234 } 260 }
235 261
236 Token parseTopLevelDeclaration(Token token) { 262 Token parseTopLevelDeclaration(Token token) {
237 token = _parseTopLevelDeclaration(token); 263 token = _parseTopLevelDeclaration(token);
238 listener.endTopLevelDeclaration(token); 264 listener.endTopLevelDeclaration(token);
239 return token; 265 return token;
240 } 266 }
241 267
242 Token _parseTopLevelDeclaration(Token token) { 268 Token _parseTopLevelDeclaration(Token token) {
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 } 375 }
350 listener.endDottedName(count, firstIdentifier); 376 listener.endDottedName(count, firstIdentifier);
351 return token; 377 return token;
352 } 378 }
353 379
354 /// export uri conditional-uris* combinator* ';' 380 /// export uri conditional-uris* combinator* ';'
355 Token parseExport(Token token) { 381 Token parseExport(Token token) {
356 Token exportKeyword = token; 382 Token exportKeyword = token;
357 listener.beginExport(exportKeyword); 383 listener.beginExport(exportKeyword);
358 assert(optional('export', token)); 384 assert(optional('export', token));
359 token = parseLiteralStringOrRecoverExpression(token.next); 385 token = ensureParseLiteralString(token.next);
360 token = parseConditionalUris(token); 386 token = parseConditionalUris(token);
361 token = parseCombinators(token); 387 token = parseCombinators(token);
362 Token semicolon = token; 388 Token semicolon = ensureSemicolon(token);
363 token = expect(';', token);
364 listener.endExport(exportKeyword, semicolon); 389 listener.endExport(exportKeyword, semicolon);
365 return token; 390 return semicolon.next;
366 } 391 }
367 392
368 Token parseCombinators(Token token) { 393 Token parseCombinators(Token token) {
369 listener.beginCombinators(token); 394 listener.beginCombinators(token);
370 int count = 0; 395 int count = 0;
371 while (true) { 396 while (true) {
372 String value = token.stringValue; 397 String value = token.stringValue;
373 if (identical('hide', value)) { 398 if (identical('hide', value)) {
374 token = parseHide(token); 399 token = parseHide(token);
375 } else if (identical('show', value)) { 400 } else if (identical('show', value)) {
(...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after
902 reportRecoverableError(token, fasta.messageYieldAsIdentifier); 927 reportRecoverableError(token, fasta.messageYieldAsIdentifier);
903 } else if (optional('async', token)) { 928 } else if (optional('async', token)) {
904 reportRecoverableError(token, fasta.messageAsyncAsIdentifier); 929 reportRecoverableError(token, fasta.messageAsyncAsIdentifier);
905 } 930 }
906 } 931 }
907 listener.handleIdentifier(token, context); 932 listener.handleIdentifier(token, context);
908 return token.next; 933 return token.next;
909 } 934 }
910 935
911 Token expect(String string, Token token) { 936 Token expect(String string, Token token) {
937 // TODO(danrubel) update all uses of expect(';'...) to ensureSemicolon
938 // then add assert(!identical(';', string));
912 if (!identical(string, token.stringValue)) { 939 if (!identical(string, token.stringValue)) {
913 return reportUnrecoverableError( 940 return reportUnrecoverableError(
914 token, fasta.templateExpectedButGot.withArguments(string)) 941 token, fasta.templateExpectedButGot.withArguments(string))
915 .next; 942 .next;
916 } 943 }
917 return token.next; 944 return token.next;
918 } 945 }
919 946
920 Token parseTypeVariable(Token token) { 947 Token parseTypeVariable(Token token) {
921 listener.beginTypeVariable(token); 948 listener.beginTypeVariable(token);
(...skipping 998 matching lines...) Expand 10 before | Expand all | Expand 10 after
1920 listener.beginInitializer(token); 1947 listener.beginInitializer(token);
1921 if (optional('assert', token)) { 1948 if (optional('assert', token)) {
1922 token = parseAssert(token, Assert.Initializer); 1949 token = parseAssert(token, Assert.Initializer);
1923 } else { 1950 } else {
1924 token = parseExpression(token); 1951 token = parseExpression(token);
1925 } 1952 }
1926 listener.endInitializer(token); 1953 listener.endInitializer(token);
1927 return token; 1954 return token;
1928 } 1955 }
1929 1956
1957 Token ensureParseLiteralString(Token token) {
1958 if (!identical(token.kind, STRING_TOKEN)) {
1959 Message message = fasta.templateExpectedString.withArguments(token);
1960 Token newToken =
1961 new SyntheticStringToken(TokenType.STRING, '""', token.charOffset, 0);
1962 token = rewriteAndRecover(token, message, newToken);
1963 }
1964 return parseLiteralString(token);
1965 }
1966
1967 Token ensureSemicolon(Token token) {
1968 // TODO(danrubel): Once all expect(';'...) call sites have been converted
1969 // to use this method, remove similar semicolon recovery code
1970 // from the handleError method in element_listener.dart.
1971 if (optional(';', token)) return token;
1972 Message message = fasta.templateExpectedButGot.withArguments(';');
1973 Token newToken = new SyntheticToken(TokenType.SEMICOLON, token.charOffset);
1974 return rewriteAndRecover(token, message, newToken);
1975 }
1976
1977 Token rewriteAndRecover(Token token, Message message, Token newToken) {
1978 if (firstToken == null) return reportUnrecoverableError(token, message);
1979 reportRecoverableError(token, message);
1980 token = rewriter.insertTokenBefore(newToken, token);
1981 return token;
1982 }
1983
1930 Token parseLiteralStringOrRecoverExpression(Token token) { 1984 Token parseLiteralStringOrRecoverExpression(Token token) {
1931 if (identical(token.kind, STRING_TOKEN)) { 1985 if (identical(token.kind, STRING_TOKEN)) {
1932 return parseLiteralString(token); 1986 return parseLiteralString(token);
1933 } else if (token is ErrorToken) { 1987 } else if (token is ErrorToken) {
1934 return reportErrorToken(token, false); 1988 return reportErrorToken(token, false);
1935 } else { 1989 } else {
1936 reportRecoverableErrorWithToken(token, fasta.templateExpectedString); 1990 reportRecoverableErrorWithToken(token, fasta.templateExpectedString);
1937 return parseRecoverExpression( 1991 return parseRecoverExpression(
1938 token, fasta.templateExpectedString.withArguments(token)); 1992 token, fasta.templateExpectedString.withArguments(token));
1939 } 1993 }
(...skipping 2143 matching lines...) Expand 10 before | Expand all | Expand 10 after
4083 } 4137 }
4084 4138
4085 Token reportUnexpectedToken(Token token) { 4139 Token reportUnexpectedToken(Token token) {
4086 return reportUnrecoverableErrorWithToken( 4140 return reportUnrecoverableErrorWithToken(
4087 token, fasta.templateUnexpectedToken); 4141 token, fasta.templateUnexpectedToken);
4088 } 4142 }
4089 } 4143 }
4090 4144
4091 // TODO(ahe): Remove when analyzer supports generalized function syntax. 4145 // TODO(ahe): Remove when analyzer supports generalized function syntax.
4092 typedef _MessageWithArgument<T> = Message Function(T); 4146 typedef _MessageWithArgument<T> = Message Function(T);
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/parser/element_listener.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698