(endToken: Kind, options?: { escape?: Kind[]; nestable?: [Kind, Kind][] }, yieldFinalClose?: boolean)
| 595 | } |
| 596 | |
| 597 | *takeUntil(endToken: Kind, options?: { escape?: Kind[]; nestable?: [Kind, Kind][] }, yieldFinalClose?: boolean): Iterable<Token> { |
| 598 | const nestable = options?.nestable || []; |
| 599 | const escape = options?.escape || []; |
| 600 | |
| 601 | processing: do { |
| 602 | switch (this.kind) { |
| 603 | case endToken: |
| 604 | // if we're nested, we need to return the end token, because it's significant to the consumer |
| 605 | if (yieldFinalClose) { |
| 606 | yield this.take(); |
| 607 | return; |
| 608 | } |
| 609 | |
| 610 | // we're done here, lose the last token and get out |
| 611 | this.take(); |
| 612 | return; |
| 613 | |
| 614 | case Kind.EndOfFile: |
| 615 | throw new Error('Unexpected end of tokens'); |
| 616 | } |
| 617 | |
| 618 | // check for escaped tokens |
| 619 | if (escape.includes(this.kind)) { |
| 620 | // pull through the escape token |
| 621 | // and the next token |
| 622 | yield this.take(); |
| 623 | yield this.take(); |
| 624 | continue; |
| 625 | } |
| 626 | |
| 627 | // check for nested tokens |
| 628 | for (const [open, close] of nestable as [Kind, Kind][]) { |
| 629 | if (this.kind === open) { |
| 630 | yield this.take(); // yield the open token |
| 631 | yield* this.takeUntil(close, options, true); |
| 632 | continue processing; |
| 633 | } |
| 634 | } |
| 635 | |
| 636 | // yield the current token |
| 637 | yield this.take(); |
| 638 | } while (true); |
| 639 | } |
| 640 | |
| 641 | takeWhitespace() { |
| 642 | while (!this.eof && this.isWhitespace) { |
no test coverage detected