| Index: dart/sdk/lib/_internal/compiler/implementation/scanner/array_based_scanner.dart
|
| diff --git a/dart/sdk/lib/_internal/compiler/implementation/scanner/array_based_scanner.dart b/dart/sdk/lib/_internal/compiler/implementation/scanner/array_based_scanner.dart
|
| index d1daab119fb905c1992a6497fec53f2f1c450dcd..8894cd50c3adf809dbda94d92f6da9ba7702031c 100644
|
| --- a/dart/sdk/lib/_internal/compiler/implementation/scanner/array_based_scanner.dart
|
| +++ b/dart/sdk/lib/_internal/compiler/implementation/scanner/array_based_scanner.dart
|
| @@ -72,15 +72,15 @@ abstract class ArrayBasedScanner extends AbstractScanner {
|
|
|
| void appendEofToken() {
|
| beginToken();
|
| - tail.next = new SymbolToken(EOF_INFO, tokenStart);
|
| - tail = tail.next;
|
| - // EOF points to itself so there's always infinite look-ahead.
|
| - tail.next = tail;
|
| discardOpenLt();
|
| while (!groupingStack.isEmpty) {
|
| unmatchedBeginGroup(groupingStack.head);
|
| groupingStack = groupingStack.tail;
|
| }
|
| + tail.next = new SymbolToken(EOF_INFO, tokenStart);
|
| + tail = tail.next;
|
| + // EOF points to itself so there's always infinite look-ahead.
|
| + tail.next = tail;
|
| }
|
|
|
| /**
|
| @@ -129,33 +129,47 @@ abstract class ArrayBasedScanner extends AbstractScanner {
|
| */
|
| int appendEndGroup(PrecedenceInfo info, int openKind) {
|
| assert(!identical(openKind, LT_TOKEN)); // openKind is < for > and >>
|
| + discardBeginGroupUntil(openKind);
|
| appendPrecedenceToken(info);
|
| - // Don't report unmatched errors for <; it is also the less-than operator.
|
| - discardOpenLt();
|
| + Token close = tail;
|
| if (groupingStack.isEmpty) {
|
| return advance();
|
| }
|
| BeginGroupToken begin = groupingStack.head;
|
| if (!identical(begin.kind, openKind)) {
|
| - if (!identical(openKind, OPEN_CURLY_BRACKET_TOKEN) ||
|
| - !identical(begin.kind, STRING_INTERPOLATION_TOKEN)) {
|
| - // Not ending string interpolation.
|
| - unmatchedBeginGroup(begin);
|
| - return advance();
|
| - }
|
| + assert(begin.kind == STRING_INTERPOLATION_TOKEN &&
|
| + openKind == OPEN_CURLY_BRACKET_TOKEN);
|
| // We're ending an interpolated expression.
|
| - begin.endGroup = tail;
|
| + begin.endGroup = close;
|
| groupingStack = groupingStack.tail;
|
| // Using "start-of-text" to signal that we're back in string
|
| // scanning mode.
|
| return $STX;
|
| }
|
| - begin.endGroup = tail;
|
| + begin.endGroup = close;
|
| groupingStack = groupingStack.tail;
|
| return advance();
|
| }
|
|
|
| /**
|
| + * Discards begin group tokens until a match with [openKind] is found.
|
| + * This recovers nicely from from a situation like "{[}".
|
| + */
|
| + void discardBeginGroupUntil(int openKind) {
|
| + while (!groupingStack.isEmpty) {
|
| + // Don't report unmatched errors for <; it is also the less-than operator.
|
| + discardOpenLt();
|
| + if (groupingStack.isEmpty) return;
|
| + BeginGroupToken begin = groupingStack.head;
|
| + if (openKind == begin.kind) return;
|
| + if (openKind == OPEN_CURLY_BRACKET_TOKEN &&
|
| + begin.kind == STRING_INTERPOLATION_TOKEN) return;
|
| + unmatchedBeginGroup(begin);
|
| + groupingStack = groupingStack.tail;
|
| + }
|
| + }
|
| +
|
| + /**
|
| * Appends a token for '>'.
|
| * This method does not issue unmatched errors, because > is also the
|
| * greater-than operator. It does not necessarily have to close a group.
|
|
|