| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 897 reportRecoverableError(token, fasta.messageYieldAsIdentifier); | 922 reportRecoverableError(token, fasta.messageYieldAsIdentifier); |
| 898 } else if (optional('async', token)) { | 923 } else if (optional('async', token)) { |
| 899 reportRecoverableError(token, fasta.messageAsyncAsIdentifier); | 924 reportRecoverableError(token, fasta.messageAsyncAsIdentifier); |
| 900 } | 925 } |
| 901 } | 926 } |
| 902 listener.handleIdentifier(token, context); | 927 listener.handleIdentifier(token, context); |
| 903 return token.next; | 928 return token.next; |
| 904 } | 929 } |
| 905 | 930 |
| 906 Token expect(String string, Token token) { | 931 Token expect(String string, Token token) { |
| 932 // TODO(danrubel) update all uses of expect(';'...) to ensureSemicolon |
| 933 // then add assert(!identical(';', string)); |
| 907 if (!identical(string, token.stringValue)) { | 934 if (!identical(string, token.stringValue)) { |
| 908 return reportUnrecoverableError( | 935 return reportUnrecoverableError( |
| 909 token, fasta.templateExpectedButGot.withArguments(string)) | 936 token, fasta.templateExpectedButGot.withArguments(string)) |
| 910 .next; | 937 .next; |
| 911 } | 938 } |
| 912 return token.next; | 939 return token.next; |
| 913 } | 940 } |
| 914 | 941 |
| 915 Token parseTypeVariable(Token token) { | 942 Token parseTypeVariable(Token token) { |
| 916 listener.beginTypeVariable(token); | 943 listener.beginTypeVariable(token); |
| (...skipping 998 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1915 listener.beginInitializer(token); | 1942 listener.beginInitializer(token); |
| 1916 if (optional('assert', token)) { | 1943 if (optional('assert', token)) { |
| 1917 token = parseAssert(token, Assert.Initializer); | 1944 token = parseAssert(token, Assert.Initializer); |
| 1918 } else { | 1945 } else { |
| 1919 token = parseExpression(token); | 1946 token = parseExpression(token); |
| 1920 } | 1947 } |
| 1921 listener.endInitializer(token); | 1948 listener.endInitializer(token); |
| 1922 return token; | 1949 return token; |
| 1923 } | 1950 } |
| 1924 | 1951 |
| 1952 Token ensureParseLiteralString(Token token) { |
| 1953 if (!identical(token.kind, STRING_TOKEN)) { |
| 1954 Message message = fasta.templateExpectedString.withArguments(token); |
| 1955 Token newToken = |
| 1956 new SyntheticStringToken(TokenType.STRING, '""', token.charOffset, 0); |
| 1957 token = rewriteAndRecover(token, message, newToken); |
| 1958 } |
| 1959 return parseLiteralString(token); |
| 1960 } |
| 1961 |
| 1962 Token ensureSemicolon(Token token) { |
| 1963 // TODO(danrubel): Once all expect(';'...) call sites have been converted |
| 1964 // to use this method, remove similar semicolon recovery code |
| 1965 // from the handleError method in element_listener.dart. |
| 1966 if (optional(';', token)) return token; |
| 1967 Message message = fasta.templateExpectedButGot.withArguments(';'); |
| 1968 Token newToken = new SyntheticToken(TokenType.SEMICOLON, token.charOffset); |
| 1969 return rewriteAndRecover(token, message, newToken); |
| 1970 } |
| 1971 |
| 1972 Token rewriteAndRecover(Token token, Message message, Token newToken) { |
| 1973 if (firstToken == null) return reportUnrecoverableError(token, message); |
| 1974 reportRecoverableError(token, message); |
| 1975 token = rewriter.insertTokenBefore(newToken, token); |
| 1976 return token; |
| 1977 } |
| 1978 |
| 1925 Token parseLiteralStringOrRecoverExpression(Token token) { | 1979 Token parseLiteralStringOrRecoverExpression(Token token) { |
| 1926 if (identical(token.kind, STRING_TOKEN)) { | 1980 if (identical(token.kind, STRING_TOKEN)) { |
| 1927 return parseLiteralString(token); | 1981 return parseLiteralString(token); |
| 1928 } else if (token is ErrorToken) { | 1982 } else if (token is ErrorToken) { |
| 1929 return reportErrorToken(token, false); | 1983 return reportErrorToken(token, false); |
| 1930 } else { | 1984 } else { |
| 1931 reportRecoverableErrorWithToken(token, fasta.templateExpectedString); | 1985 reportRecoverableErrorWithToken(token, fasta.templateExpectedString); |
| 1932 return parseRecoverExpression( | 1986 return parseRecoverExpression( |
| 1933 token, fasta.templateExpectedString.withArguments(token)); | 1987 token, fasta.templateExpectedString.withArguments(token)); |
| 1934 } | 1988 } |
| (...skipping 2130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4065 } | 4119 } |
| 4066 | 4120 |
| 4067 Token reportUnexpectedToken(Token token) { | 4121 Token reportUnexpectedToken(Token token) { |
| 4068 return reportUnrecoverableErrorWithToken( | 4122 return reportUnrecoverableErrorWithToken( |
| 4069 token, fasta.templateUnexpectedToken); | 4123 token, fasta.templateUnexpectedToken); |
| 4070 } | 4124 } |
| 4071 } | 4125 } |
| 4072 | 4126 |
| 4073 // TODO(ahe): Remove when analyzer supports generalized function syntax. | 4127 // TODO(ahe): Remove when analyzer supports generalized function syntax. |
| 4074 typedef _MessageWithArgument<T> = Message Function(T); | 4128 typedef _MessageWithArgument<T> = Message Function(T); |
| OLD | NEW |