@@ -6,162 +6,48 @@ library fasta.scanner.recover;
66
77import '../../scanner/token.dart' show TokenType;
88
9- import '../fasta_codes.dart'
10- show
11- Code,
12- codeAsciiControlCharacter,
13- codeEncoding,
14- codeExpectedHexDigit,
15- codeMissingExponent,
16- codeNonAsciiIdentifier,
17- codeNonAsciiWhitespace,
18- codeUnexpectedDollarInString,
19- codeUnmatchedToken,
20- codeUnterminatedComment,
21- codeUnterminatedString;
22-
239import '../../scanner/token.dart' show Token;
2410
2511import 'token.dart' show StringToken;
2612
27- import 'error_token.dart' show NonAsciiIdentifierToken, ErrorToken;
13+ import 'error_token.dart' show ErrorToken;
2814
2915/// Recover from errors in [tokens] . The original sources are provided as
3016/// [bytes] . [lineStarts] are the beginning character offsets of lines, and
3117/// must be updated if recovery is performed rewriting the original source
3218/// code.
3319Token scannerRecovery (List <int > bytes, Token tokens, List <int > lineStarts) {
34- // See [Parser.reportErrorToken](../parser/src/parser.dart) for how
35- // it currently handles lexical errors. In addition, notice how the parser
36- // calls [handleInvalidExpression], [handleInvalidFunctionBody], and
37- // [handleInvalidTypeReference] to allow the listener to recover its internal
38- // state. See [package:compiler/src/parser/element_listener.dart] for an
39- // example of how these events are used.
40- //
41- // In addition, the scanner will attempt a bit of recovery when braces don't
42- // match up during brace grouping. For more details on brace grouping see
43- // [AbstractScanner.discardBeginGroupUntil] and
44- // [AbstractScanner.unmatchedBeginGroup].
45-
46- /// Tokens with errors.
47- ErrorToken error;
48-
49- /// Used for appending to [error] .
50- ErrorToken errorTail;
51-
52- /// Tokens without errors.
53- Token good;
54-
55- /// Used for appending to [good] .
56- Token goodTail;
57-
58- recoverIdentifier (NonAsciiIdentifierToken first) {
59- throw "Internal error: Identifier error token should have been prepended" ;
60- }
20+ // Sanity check that all error tokens are prepended.
6121
62- recoverExponent () {
63- throw "Internal error: Exponent error token should have been prepended" ;
64- }
65-
66- recoverString () {
67- throw "Internal error: String error token should have been prepended" ;
68- }
69-
70- recoverHexDigit () {
71- throw "Internal error: Hex digit error token should have been prepended" ;
72- }
73-
74- recoverStringInterpolation () {
75- throw "Internal error: Interpolation error token should have been prepended" ;
76- }
22+ // TODO(danrubel): Remove this in a while after the dust has settled.
7723
78- recoverComment () {
79- throw "Internal error: Comment error token should have been prepended" ;
80- }
81-
82- recoverUnmatched () {
83- // TODO(ahe): Try to use top-level keywords (such as `class`, `typedef`,
84- // and `enum`) and indentation to recover.
85- throw "Internal error: Unmatched error token should have been prepended" ;
86- }
87-
88- // All unmatched error tokens should have been prepended
89- Token current = tokens;
90- while (current is ErrorToken ) {
91- if (errorTail == null ) {
92- error = current;
93- }
94- errorTail = current;
95- current = current.next;
24+ // Skip over prepended error tokens
25+ var token = tokens;
26+ while (token is ErrorToken ) {
27+ token = token.next;
9628 }
9729
98- for (; ! current.isEof; current = current.next) {
99- while (current is ErrorToken ) {
100- ErrorToken first = current;
101- Token next = current;
102- do {
103- current = next;
104- if (errorTail == null ) {
105- error = next;
106- } else {
107- errorTail.setNext (next);
108- }
109- errorTail = next;
110- next = next.next;
111- } while (next is ErrorToken && first.errorCode == next.errorCode);
112-
113- Code code = first.errorCode;
114- if (code == codeEncoding ||
115- code == codeNonAsciiWhitespace ||
116- code == codeAsciiControlCharacter) {
117- current = errorTail.next;
118- } else if (code == codeNonAsciiIdentifier) {
119- current = recoverIdentifier (first);
120- assert (current.next != null );
121- } else if (code == codeMissingExponent) {
122- current = recoverExponent ();
123- assert (current.next != null );
124- } else if (code == codeUnterminatedString) {
125- current = recoverString ();
126- assert (current.next != null );
127- } else if (code == codeExpectedHexDigit) {
128- current = recoverHexDigit ();
129- assert (current.next != null );
130- } else if (code == codeUnexpectedDollarInString) {
131- current = recoverStringInterpolation ();
132- assert (current.next != null );
133- } else if (code == codeUnterminatedComment) {
134- current = recoverComment ();
135- assert (current.next != null );
136- } else if (code == codeUnmatchedToken) {
137- current = recoverUnmatched ();
138- assert (current.next != null );
139- } else {
140- current = errorTail.next;
30+ // Assert no error tokens in the remaining tokens
31+ while (! token.isEof) {
32+ if (token is ErrorToken ) {
33+ for (int count = 0 ; count < 3 ; ++ count) {
34+ var previous = token.previous;
35+ if (previous.isEof) break ;
36+ token = previous;
14137 }
38+ var msg = new StringBuffer (
39+ "Internal error: All error tokens should have been prepended:" );
40+ for (int count = 0 ; count < 7 ; ++ count) {
41+ if (token.isEof) break ;
42+ msg.write (' ${token .runtimeType },' );
43+ token = token.next;
44+ }
45+ throw msg.toString ();
14246 }
143- if (goodTail == null ) {
144- good = current;
145- } else {
146- goodTail.setNext (current);
147- }
148- goodTail = current;
47+ token = token.next;
14948 }
15049
151- if (error == null ) {
152- // All of the errors are in the scanner's error list.
153- return tokens;
154- }
155- new Token .eof (- 1 ).setNext (error);
156- Token tail;
157- if (good != null ) {
158- errorTail.setNext (good);
159- tail = goodTail;
160- } else {
161- tail = errorTail;
162- }
163- if (! tail.isEof) tail.setNext (new Token .eof (tail.end));
164- return error;
50+ return tokens;
16551}
16652
16753Token synthesizeToken (int charOffset, String value, TokenType type) {
0 commit comments