| 541 | } |
| 542 | |
| 543 | private readStringLiteral(hasLeftSpacing: boolean): Token { |
| 544 | let value = ''; |
| 545 | const literalMark = this.stream.char; |
| 546 | let state: 'string' | 'escape' | 'finish' = 'string'; |
| 547 | |
| 548 | const pos = this.stream.getPos(); |
| 549 | this.stream.next(); |
| 550 | |
| 551 | while (state !== 'finish') { |
| 552 | switch (state) { |
| 553 | case 'string': { |
| 554 | if (this.stream.eof) { |
| 555 | throw new AiScriptUnexpectedEOFError(pos); |
| 556 | } |
| 557 | if (this.stream.char === '\\') { |
| 558 | this.stream.next(); |
| 559 | state = 'escape'; |
| 560 | break; |
| 561 | } |
| 562 | if (this.stream.char === literalMark) { |
| 563 | this.stream.next(); |
| 564 | state = 'finish'; |
| 565 | break; |
| 566 | } |
| 567 | value += this.stream.char; |
| 568 | this.stream.next(); |
| 569 | break; |
| 570 | } |
| 571 | case 'escape': { |
| 572 | if (this.stream.eof) { |
| 573 | throw new AiScriptUnexpectedEOFError(pos); |
| 574 | } |
| 575 | value += this.stream.char; |
| 576 | this.stream.next(); |
| 577 | state = 'string'; |
| 578 | break; |
| 579 | } |
| 580 | } |
| 581 | } |
| 582 | return TOKEN(TokenKind.StringLiteral, pos, { hasLeftSpacing, value }); |
| 583 | } |
| 584 | |
| 585 | private readTemplate(hasLeftSpacing: boolean): Token { |
| 586 | const elements: Token[] = []; |