diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart index b70d6111c30..f70a0283666 100644 --- a/pkg/front_end/lib/src/fasta/parser/parser.dart +++ b/pkg/front_end/lib/src/fasta/parser/parser.dart @@ -770,8 +770,7 @@ class Parser { next.setNext(leftParen); leftParen = openParen; } - token = leftParen; - token = parseDottedName(token); + token = parseDottedName(leftParen); Token next = token.next; Token equalitySign; if (optional('==', next)) { diff --git a/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart b/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart index 8f7100baecd..5d8487aae1d 100644 --- a/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart +++ b/pkg/front_end/lib/src/fasta/scanner/array_based_scanner.dart @@ -361,7 +361,7 @@ abstract class ArrayBasedScanner extends AbstractScanner { // v // EOF TokenType type = closeBraceInfoFor(begin); - appendToken(new SyntheticToken(type, tokenStart)); + appendToken(new SyntheticToken(type, tokenStart)..beforeSynthetic = tail); begin.endGroup = tail; appendErrorToken(new UnmatchedToken(begin)); } diff --git a/pkg/front_end/lib/src/scanner/token.dart b/pkg/front_end/lib/src/scanner/token.dart index 4e858ff24e9..530b6f06415 100644 --- a/pkg/front_end/lib/src/scanner/token.dart +++ b/pkg/front_end/lib/src/scanner/token.dart @@ -492,6 +492,14 @@ class SimpleToken implements Token { @override int get charEnd => end; + @override + Token get beforeSynthetic => null; + + @override + set beforeSynthetic(Token previous) { + // ignored + } + @override int get end => offset + length; @@ -581,6 +589,7 @@ class SimpleToken implements Token { Token setNext(Token token) { next = token; token.previous = this; + token.beforeSynthetic = this; return token; } @@ -711,6 +720,12 @@ class SyntheticStringToken extends StringToken { class SyntheticToken extends SimpleToken { SyntheticToken(TokenType type, int offset) : super(type, offset); + @override + Token beforeSynthetic; + + @override + bool get isSynthetic => true; + @override int get length => 0; @@ -757,6 +772,18 @@ abstract class Token implements SyntacticEntity { */ int get charEnd; + /** + * The token before this synthetic token, + * or `null` if this is not a synthetic `)`, `]`, `}`, or `>` token. + */ + Token get beforeSynthetic; + + /** + * Set token before this synthetic `)`, `]`, `}`, or `>` token, + * and ignored otherwise. + */ + set beforeSynthetic(Token previous); + @override int get end; diff --git a/pkg/front_end/test/scanner_fasta_test.dart b/pkg/front_end/test/scanner_fasta_test.dart index 0000f0cafc2..2d01af99f3b 100644 --- a/pkg/front_end/test/scanner_fasta_test.dart +++ b/pkg/front_end/test/scanner_fasta_test.dart @@ -727,7 +727,18 @@ class ScannerTest_Fasta_Direct extends ScannerTest_Fasta_Base { @override Token scan(String source) { - return createScanner(source, includeComments: true).tokenize(); + final Token first = createScanner(source, includeComments: true).tokenize(); + Token token = first; + while (!token.isEof) { + Token next = token.next; + expect(token.next, next); + expect(next.previous, token); + if (next.isSynthetic && [')', ']', '}'].contains(next.lexeme)) { + expect(next.beforeSynthetic, token); + } + token = next; + } + return first; } void test_linestarts() {