| OLD | NEW |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 licenset hat can be found in the LICENSE file. | 3 // BSD-style licenset hat can be found in the LICENSE file. |
| 4 | 4 |
| 5 library fasta.scanner.recover; | 5 library fasta.scanner.recover; |
| 6 | 6 |
| 7 import 'token.dart' show | 7 import 'token.dart' show |
| 8 StringToken, | 8 StringToken, |
| 9 Token; | 9 Token; |
| 10 | 10 |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 106 beforeGoodTail = null; | 106 beforeGoodTail = null; |
| 107 } else { | 107 } else { |
| 108 goodTail = beforeGoodTail; | 108 goodTail = beforeGoodTail; |
| 109 } | 109 } |
| 110 } | 110 } |
| 111 if (append) { | 111 if (append) { |
| 112 codeUnits.addAll(next.value.codeUnits); | 112 codeUnits.addAll(next.value.codeUnits); |
| 113 next = next.next; | 113 next = next.next; |
| 114 } | 114 } |
| 115 String value = new String.fromCharCodes(codeUnits); | 115 String value = new String.fromCharCodes(codeUnits); |
| 116 Token recovered = synthesizeToken( | 116 return synthesizeToken(charOffset, value, Precedence.IDENTIFIER_INFO) |
| 117 charOffset, value, Precedence.IDENTIFIER_INFO); | 117 ..next = next; |
| 118 recovered.next = next; | |
| 119 return recovered; | |
| 120 } | 118 } |
| 121 | 119 |
| 122 recoverExponent() { | 120 recoverExponent() { |
| 123 return synthesizeToken(errorTail.charOffset, "NaN", Precedence.DOUBLE_INFO); | 121 return synthesizeToken(errorTail.charOffset, "NaN", Precedence.DOUBLE_INFO) |
| 122 ..next = errorTail.next; |
| 124 } | 123 } |
| 125 | 124 |
| 126 recoverString() { | 125 recoverString() { |
| 127 // TODO(ahe): Improve this. | 126 // TODO(ahe): Improve this. |
| 128 return skipToEof(errorTail); | 127 return skipToEof(errorTail); |
| 129 } | 128 } |
| 130 | 129 |
| 131 recoverHexDigit() { | 130 recoverHexDigit() { |
| 132 return synthesizeToken(errorTail.charOffset, "-1", Precedence.INT_INFO); | 131 return synthesizeToken(errorTail.charOffset, "-1", Precedence.INT_INFO) |
| 132 ..next = errorTail.next; |
| 133 } | 133 } |
| 134 | 134 |
| 135 recoverStringInterpolation() { | 135 recoverStringInterpolation() { |
| 136 // TODO(ahe): Improve this. | 136 // TODO(ahe): Improve this. |
| 137 return skipToEof(errorTail); | 137 return skipToEof(errorTail); |
| 138 } | 138 } |
| 139 | 139 |
| 140 recoverComment() { | 140 recoverComment() { |
| 141 // TODO(ahe): Improve this. | 141 // TODO(ahe): Improve this. |
| 142 return skipToEof(errorTail); | 142 return skipToEof(errorTail); |
| 143 } | 143 } |
| 144 | 144 |
| 145 recoverUnmatched() { | 145 recoverUnmatched() { |
| 146 // TODO(ahe): Try to use top-level keywords (such as `class`, `typedef`, | 146 // TODO(ahe): Try to use top-level keywords (such as `class`, `typedef`, |
| 147 // and `enum`) and identation to recover. | 147 // and `enum`) and identation to recover. |
| 148 return errorTail; | 148 return errorTail.next; |
| 149 } | 149 } |
| 150 | 150 |
| 151 for (Token current = tokens; !current.isEof; current = current.next) { | 151 for (Token current = tokens; !current.isEof; current = current.next) { |
| 152 if (current is ErrorToken) { | 152 if (current is ErrorToken) { |
| 153 ErrorToken first = current; | 153 ErrorToken first = current; |
| 154 Token next = current; | 154 Token next = current; |
| 155 bool treatAsWhitespace = false; | 155 bool treatAsWhitespace = false; |
| 156 do { | 156 do { |
| 157 current = next; | 157 current = next; |
| 158 if (errorTail == null) { | 158 if (errorTail == null) { |
| 159 error = next; | 159 error = next; |
| 160 } else { | 160 } else { |
| 161 errorTail.next = next; | 161 errorTail.next = next; |
| 162 } | 162 } |
| 163 errorTail = next; | 163 errorTail = next; |
| 164 next = next.next; | 164 next = next.next; |
| 165 } while (next is ErrorToken && first.errorCode == next.errorCode); | 165 } while (next is ErrorToken && first.errorCode == next.errorCode); |
| 166 | 166 |
| 167 switch (first.errorCode) { | 167 switch (first.errorCode) { |
| 168 case ErrorKind.Encoding: | 168 case ErrorKind.Encoding: |
| 169 case ErrorKind.NonAsciiWhitespace: | 169 case ErrorKind.NonAsciiWhitespace: |
| 170 case ErrorKind.AsciiControlCharacter: | 170 case ErrorKind.AsciiControlCharacter: |
| 171 treatAsWhitespace = true; | 171 treatAsWhitespace = true; |
| 172 break; | 172 break; |
| 173 | 173 |
| 174 case ErrorKind.NonAsciiIdentifier: | 174 case ErrorKind.NonAsciiIdentifier: |
| 175 current = recoverIdentifier(first); | 175 current = recoverIdentifier(first); |
| 176 assert(current.next != null); |
| 176 break; | 177 break; |
| 177 | 178 |
| 178 case ErrorKind.MissingExponent: | 179 case ErrorKind.MissingExponent: |
| 179 current = recoverExponent(); | 180 current = recoverExponent(); |
| 181 assert(current.next != null); |
| 180 break; | 182 break; |
| 181 | 183 |
| 182 case ErrorKind.UnterminatedString: | 184 case ErrorKind.UnterminatedString: |
| 183 current = recoverString(); | 185 current = recoverString(); |
| 186 assert(current.next != null); |
| 184 break; | 187 break; |
| 185 | 188 |
| 186 case ErrorKind.ExpectedHexDigit: | 189 case ErrorKind.ExpectedHexDigit: |
| 187 current = recoverHexDigit(); | 190 current = recoverHexDigit(); |
| 191 assert(current.next != null); |
| 188 break; | 192 break; |
| 189 | 193 |
| 190 case ErrorKind.UnexpectedDollarInString: | 194 case ErrorKind.UnexpectedDollarInString: |
| 191 current = recoverStringInterpolation(); | 195 current = recoverStringInterpolation(); |
| 196 assert(current.next != null); |
| 192 break; | 197 break; |
| 193 | 198 |
| 194 case ErrorKind.UnterminatedComment: | 199 case ErrorKind.UnterminatedComment: |
| 195 current = recoverComment(); | 200 current = recoverComment(); |
| 201 assert(current.next != null); |
| 196 break; | 202 break; |
| 197 | 203 |
| 198 case ErrorKind.UnmatchedToken: | 204 case ErrorKind.UnmatchedToken: |
| 199 current = recoverUnmatched(); | 205 current = recoverUnmatched(); |
| 206 assert(current.next != null); |
| 200 break; | 207 break; |
| 201 | 208 |
| 202 case ErrorKind.UnterminatedToken: // TODO(ahe): Can this happen? | 209 case ErrorKind.UnterminatedToken: // TODO(ahe): Can this happen? |
| 203 default: | 210 default: |
| 204 treatAsWhitespace = true; | 211 treatAsWhitespace = true; |
| 205 break; | 212 break; |
| 206 } | 213 } |
| 207 if (treatAsWhitespace) continue; | 214 if (treatAsWhitespace) continue; |
| 208 } | 215 } |
| 209 if (goodTail == null) { | 216 if (goodTail == null) { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 232 | 239 |
| 233 String closeBraceFor(String openBrace) { | 240 String closeBraceFor(String openBrace) { |
| 234 return const { | 241 return const { |
| 235 '(': ')', | 242 '(': ')', |
| 236 '[': ']', | 243 '[': ']', |
| 237 '{': '}', | 244 '{': '}', |
| 238 '<': '>', | 245 '<': '>', |
| 239 r'${': '}', | 246 r'${': '}', |
| 240 }[openBrace]; | 247 }[openBrace]; |
| 241 } | 248 } |
| OLD | NEW |