(multiline: boolean)
| 278 | } |
| 279 | |
| 280 | private parseBasicString(multiline: boolean): string { |
| 281 | this.expect("\"") |
| 282 | if (multiline) { |
| 283 | this.expect("\"") |
| 284 | this.expect("\"") |
| 285 | if (this.peek() === "\n") this.advance() |
| 286 | } |
| 287 | let output = "" |
| 288 | while (!this.done) { |
| 289 | if (multiline && this.input.startsWith("\"\"\"", this.index)) { |
| 290 | this.advance(3) |
| 291 | return output |
| 292 | } |
| 293 | const character = this.peek() |
| 294 | if (!multiline && character === "\"") { |
| 295 | this.advance() |
| 296 | return output |
| 297 | } |
| 298 | if (!multiline && (character === "\n" || character === "\r")) { |
| 299 | this.fail("Basic strings cannot contain newlines") |
| 300 | } |
| 301 | if (character !== "\\") { |
| 302 | output += character |
| 303 | this.advance() |
| 304 | continue |
| 305 | } |
| 306 | |
| 307 | this.advance() |
| 308 | if (multiline && /[ \t\r\n]/.test(this.peek())) { |
| 309 | while (/[ \t]/.test(this.peek())) this.advance() |
| 310 | if (this.peek() !== "\n" && this.peek() !== "\r") { |
| 311 | this.fail("Invalid multiline string continuation") |
| 312 | } |
| 313 | while (/[ \t\r\n]/.test(this.peek())) this.advance() |
| 314 | continue |
| 315 | } |
| 316 | const escape = this.peek() |
| 317 | this.advance() |
| 318 | const escapes: Record<string, string> = { |
| 319 | b: "\b", |
| 320 | t: "\t", |
| 321 | n: "\n", |
| 322 | f: "\f", |
| 323 | r: "\r", |
| 324 | "\"": "\"", |
| 325 | "\\": "\\" |
| 326 | } |
| 327 | if (hasOwn.call(escapes, escape)) { |
| 328 | output += escapes[escape] |
| 329 | } else if (escape === "u" || escape === "U") { |
| 330 | const length = escape === "u" ? 4 : 8 |
| 331 | const hex = this.input.slice(this.index, this.index + length) |
| 332 | if (!new RegExp(`^[0-9A-Fa-f]{${length}}$`).test(hex)) { |
| 333 | this.fail("Invalid unicode escape") |
| 334 | } |
| 335 | output += String.fromCodePoint(Number.parseInt(hex, 16)) |
| 336 | this.advance(length) |
| 337 | } else { |
no test coverage detected