OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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.scanner.array_based_scanner; | 5 library fasta.scanner.array_based_scanner; |
6 | 6 |
7 import 'error_token.dart' show ErrorToken, UnmatchedToken; | 7 import 'error_token.dart' show ErrorToken, UnmatchedToken; |
8 | 8 |
9 import '../../scanner/token.dart' | 9 import '../../scanner/token.dart' |
10 show | 10 show |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 void discardOpenLt() { | 272 void discardOpenLt() { |
273 while (!groupingStack.isEmpty && | 273 while (!groupingStack.isEmpty && |
274 identical(groupingStack.head.kind, LT_TOKEN)) { | 274 identical(groupingStack.head.kind, LT_TOKEN)) { |
275 groupingStack = groupingStack.tail; | 275 groupingStack = groupingStack.tail; |
276 } | 276 } |
277 } | 277 } |
278 | 278 |
279 /** | 279 /** |
280 * This method is called to discard '${' from the "grouping" stack. | 280 * This method is called to discard '${' from the "grouping" stack. |
281 * | 281 * |
282 * This method is called when the scanner finds the end of a string | 282 * This method is called when the scanner finds an unterminated |
283 * or an unterminated string. | 283 * interpolation expression. |
284 */ | 284 */ |
285 void discardInterpolation() { | 285 void discardInterpolation() { |
286 if (groupingStack.isEmpty) return; | 286 while (!groupingStack.isEmpty) { |
287 BeginToken begin = groupingStack.head; | 287 BeginToken beginToken = groupingStack.head; |
288 if (begin.kind != STRING_INTERPOLATION_TOKEN) return; | 288 unmatchedBeginGroup(beginToken); |
289 unmatchedBeginGroup(begin); | 289 groupingStack = groupingStack.tail; |
290 groupingStack = groupingStack.tail; | 290 if (identical(beginToken.kind, STRING_INTERPOLATION_TOKEN)) break; |
| 291 } |
291 } | 292 } |
292 | 293 |
293 void unmatchedBeginGroup(BeginToken begin) { | 294 void unmatchedBeginGroup(BeginToken begin) { |
294 // We want to ensure that unmatched BeginTokens are reported as | 295 // We want to ensure that unmatched BeginTokens are reported as |
295 // errors. However, the diet parser assumes that groups are well-balanced | 296 // errors. However, the diet parser assumes that groups are well-balanced |
296 // and will never look at the endGroup token. This is a nice property that | 297 // and will never look at the endGroup token. This is a nice property that |
297 // allows us to skip quickly over correct code. By inserting an additional | 298 // allows us to skip quickly over correct code. By inserting an additional |
298 // synthetic token in the stream, we can keep ignoring endGroup tokens. | 299 // synthetic token in the stream, we can keep ignoring endGroup tokens. |
299 // | 300 // |
300 // [begin] --next--> [tail] | 301 // [begin] --next--> [tail] |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 // | | 335 // | |
335 // next | 336 // next |
336 // v | 337 // v |
337 // EOF | 338 // EOF |
338 TokenType type = closeBraceInfoFor(begin); | 339 TokenType type = closeBraceInfoFor(begin); |
339 appendToken(new SyntheticToken(type, tokenStart)); | 340 appendToken(new SyntheticToken(type, tokenStart)); |
340 begin.endGroup = tail; | 341 begin.endGroup = tail; |
341 appendErrorToken(new UnmatchedToken(begin)); | 342 appendErrorToken(new UnmatchedToken(begin)); |
342 } | 343 } |
343 } | 344 } |
OLD | NEW |