Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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.quote; | 5 library fasta.quote; |
| 6 | 6 |
| 7 import 'errors.dart' show inputError, internalError; | 7 import 'errors.dart' show inputError, internalError; |
| 8 | 8 |
| 9 import 'scanner/characters.dart' | 9 import 'scanner/characters.dart' |
| 10 show | 10 show |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 51 if (first.startsWith("r'")) return Quote.RawSingle; | 51 if (first.startsWith("r'")) return Quote.RawSingle; |
| 52 return internalError("Unexpected string literal: $first"); | 52 return internalError("Unexpected string literal: $first"); |
| 53 } | 53 } |
| 54 | 54 |
| 55 // Note: based on [StringValidator.quotingFromString] | 55 // Note: based on [StringValidator.quotingFromString] |
| 56 // (pkg/compiler/lib/src/string_validator.dart). | 56 // (pkg/compiler/lib/src/string_validator.dart). |
| 57 int lengthOfOptionalWhitespacePrefix(String first, int start) { | 57 int lengthOfOptionalWhitespacePrefix(String first, int start) { |
| 58 List<int> codeUnits = first.codeUnits; | 58 List<int> codeUnits = first.codeUnits; |
| 59 for (int i = start; i < codeUnits.length; i++) { | 59 for (int i = start; i < codeUnits.length; i++) { |
| 60 int code = codeUnits[i]; | 60 int code = codeUnits[i]; |
| 61 if (code == $BACKSLASH) { | 61 if (code == $BACKSLASH) { |
|
Lasse Reichstein Nielsen
2017/04/28 06:34:28
I REALLY think we should disallow quoting leading
ahe
2017/04/28 07:39:00
Acknowledged.
| |
| 62 i++; | 62 i++; |
| 63 if (i < codeUnits.length) { | 63 if (i < codeUnits.length) { |
| 64 code = codeUnits[i]; | 64 code = codeUnits[i]; |
| 65 } else { | 65 } else { |
| 66 break; | 66 break; |
| 67 } | 67 } |
| 68 } | 68 } |
| 69 if (code == $TAB || code == $SPACE) continue; | 69 if (code == $TAB || code == $SPACE) continue; |
| 70 if (code == $CR) { | 70 if (code == $CR) { |
| 71 if (i + 1 < codeUnits.length && codeUnits[i] == $LF) { | 71 if (i + 1 < codeUnits.length && codeUnits[i + 1] == $LF) { |
| 72 i++; | 72 i++; |
| 73 } | 73 } |
| 74 return i + 1; | 74 return i + 1; |
| 75 } | 75 } |
| 76 if (code == $LF) { | 76 if (code == $LF) { |
| 77 return i + 1; | 77 return i + 1; |
| 78 } | 78 } |
| 79 break; // Not a white-space character. | 79 break; // Not a white-space character. |
| 80 } | 80 } |
| 81 return start; | 81 return start; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 133 return unescape( | 133 return unescape( |
| 134 string.substring(firstQuoteLength(string, quote), | 134 string.substring(firstQuoteLength(string, quote), |
| 135 string.length - lastQuoteLength(quote)), | 135 string.length - lastQuoteLength(quote)), |
| 136 quote); | 136 quote); |
| 137 } | 137 } |
| 138 | 138 |
| 139 String unescape(String string, Quote quote) { | 139 String unescape(String string, Quote quote) { |
| 140 switch (quote) { | 140 switch (quote) { |
| 141 case Quote.Single: | 141 case Quote.Single: |
| 142 case Quote.Double: | 142 case Quote.Double: |
| 143 return !string.contains("\\") | |
| 144 ? string | |
| 145 : unescapeCodeUnits(string.codeUnits, false); | |
| 146 | |
| 143 case Quote.MultiLineSingle: | 147 case Quote.MultiLineSingle: |
| 144 case Quote.MultiLineDouble: | 148 case Quote.MultiLineDouble: |
| 145 break; | 149 return !string.contains("\\") && !string.contains("\r") |
| 150 ? string | |
| 151 : unescapeCodeUnits(string.codeUnits, false); | |
| 146 | 152 |
| 147 case Quote.RawSingle: | 153 case Quote.RawSingle: |
| 148 case Quote.RawDouble: | 154 case Quote.RawDouble: |
| 155 return string; | |
| 156 | |
| 149 case Quote.RawMultiLineSingle: | 157 case Quote.RawMultiLineSingle: |
| 150 case Quote.RawMultiLineDouble: | 158 case Quote.RawMultiLineDouble: |
| 151 return string; | 159 return !string.contains("\r") |
| 160 ? string | |
| 161 : unescapeCodeUnits(string.codeUnits, true); | |
| 152 } | 162 } |
| 153 return !string.contains("\\") ? string : unescapeCodeUnits(string.codeUnits); | |
| 154 } | 163 } |
| 155 | 164 |
| 156 const String incompleteSequence = "Incomplete escape sequence."; | 165 const String incompleteSequence = "Incomplete escape sequence."; |
| 157 | 166 |
| 158 const String invalidCharacter = "Invalid character in escape sequence."; | 167 const String invalidCharacter = "Invalid character in escape sequence."; |
| 159 | 168 |
| 160 const String invalidCodePoint = "Invalid code point."; | 169 const String invalidCodePoint = "Invalid code point."; |
| 161 | 170 |
| 162 // Note: based on | 171 // Note: based on |
| 163 // [StringValidator.validateString](pkg/compiler/lib/src/string_validator.dart). | 172 // [StringValidator.validateString](pkg/compiler/lib/src/string_validator.dart). |
| 164 String unescapeCodeUnits(List<int> codeUnits) { | 173 String unescapeCodeUnits(List<int> codeUnits, bool isRaw) { |
| 165 // Can't use Uint8List or Uint16List here, the code units may be larger. | 174 // Can't use Uint8List or Uint16List here, the code units may be larger. |
| 166 List<int> result = new List<int>(codeUnits.length); | 175 List<int> result = new List<int>(codeUnits.length); |
| 167 int resultOffset = 0; | 176 int resultOffset = 0; |
| 168 error(int offset, String message) { | 177 error(int offset, String message) { |
| 169 inputError(null, null, message); | 178 inputError(null, null, message); |
| 170 } | 179 } |
| 171 | 180 |
| 172 for (int i = 0; i < codeUnits.length; i++) { | 181 for (int i = 0; i < codeUnits.length; i++) { |
| 173 int code = codeUnits[i]; | 182 int code = codeUnits[i]; |
| 174 if (code == $BACKSLASH) { | 183 if (code == $CR) { |
| 184 if (i + 1 < codeUnits.length && codeUnits[i + 1] == $LF) { | |
| 185 i++; | |
| 186 } | |
| 187 code = $LF; | |
| 188 } else if (!isRaw && code == $BACKSLASH) { | |
| 175 if (codeUnits.length == ++i) return error(i, incompleteSequence); | 189 if (codeUnits.length == ++i) return error(i, incompleteSequence); |
| 176 code = codeUnits[i]; | 190 code = codeUnits[i]; |
| 177 | 191 |
| 178 /// `\n` for newline, equivalent to `\x0A`. | 192 /// `\n` for newline, equivalent to `\x0A`. |
| 179 /// `\r` for carriage return, equivalent to `\x0D`. | 193 /// `\r` for carriage return, equivalent to `\x0D`. |
| 180 /// `\f` for form feed, equivalent to `\x0C`. | 194 /// `\f` for form feed, equivalent to `\x0C`. |
| 181 /// `\b` for backspace, equivalent to `\x08`. | 195 /// `\b` for backspace, equivalent to `\x08`. |
| 182 /// `\t` for tab, equivalent to `\x09`. | 196 /// `\t` for tab, equivalent to `\x09`. |
| 183 /// `\v` for vertical tab, equivalent to `\x0B`. | 197 /// `\v` for vertical tab, equivalent to `\x0B`. |
| 184 /// `\xXX` for hex escape. | 198 /// `\xXX` for hex escape. |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 230 } | 244 } |
| 231 } else { | 245 } else { |
| 232 // Nothing, escaped character is passed through; | 246 // Nothing, escaped character is passed through; |
| 233 } | 247 } |
| 234 if (code > 0x10FFFF) return error(i, invalidCodePoint); | 248 if (code > 0x10FFFF) return error(i, invalidCodePoint); |
| 235 } | 249 } |
| 236 result[resultOffset++] = code; | 250 result[resultOffset++] = code; |
| 237 } | 251 } |
| 238 return new String.fromCharCodes(result, 0, resultOffset); | 252 return new String.fromCharCodes(result, 0, resultOffset); |
| 239 } | 253 } |
| OLD | NEW |