import { TemplateToken } from "." import { MappingToken } from "./mapping-token" import { SequenceToken } from "./sequence-token" import { TokenType } from "./types" export class TraversalState { private readonly _token: TemplateToken private index = -1 private isKey = false public readonly parent: TraversalState | undefined public current: TemplateToken | undefined public currentKey: TemplateToken | undefined public constructor(parent: TraversalState | undefined, token: TemplateToken) { this.parent = parent this._token = token this.current = token } public moveNext(omitKeys: boolean): boolean { switch (this._token.templateTokenType) { case TokenType.Sequence: { const sequence = this._token as SequenceToken if (++this.index < sequence.count) { this.current = sequence.get(this.index) return true } this.current = undefined return false } case TokenType.Mapping: { const mapping = this._token as MappingToken // Already returned the key, now return the value if (this.isKey) { this.isKey = false this.currentKey = this.current this.current = mapping.get(this.index).value return true } // Move next if (++this.index < mapping.count) { // Skip the key, return the value if (omitKeys) { this.isKey = false this.currentKey = mapping.get(this.index).key this.current = mapping.get(this.index).value return true } // Return the key this.isKey = true this.currentKey = undefined this.current = mapping.get(this.index).key return true } this.currentKey = undefined this.current = undefined return false } default: throw new Error( `Unexpected token type '${this._token.templateTokenType}' when traversing state` ) } } }