import Tokenizer, { TokenizerOptions } from './tokenizer.ts'; import TokenParser, { StackElement, TokenParserOptions } from './tokenparser.ts'; import { JsonPrimitive, JsonKey, JsonStruct } from './utils/types.ts'; interface JSONParserOpts extends TokenizerOptions, TokenParserOptions {} export default class JSONParser { private tokenizer: Tokenizer; private tokenParser: TokenParser; constructor(opts: JSONParserOpts = {}) { this.tokenizer = new Tokenizer(opts); this.tokenParser = new TokenParser(opts); this.tokenizer.onToken = this.tokenParser.write.bind(this.tokenParser); this.tokenizer.onEnd = () => { if (!this.tokenParser.isEnded) this.tokenParser.end(); }; this.tokenParser.onError = this.tokenizer.error.bind(this.tokenizer); this.tokenParser.onEnd = () => { if (!this.tokenizer.isEnded) this.tokenizer.end(); }; } public get isEnded(): boolean { return this.tokenizer.isEnded && this.tokenParser.isEnded; } public write(input: Iterable | string): void { this.tokenizer.write(input); } public end(): void { this.tokenizer.end(); } public set onToken( cb: (token: number, value: JsonPrimitive, offset: number) => void ) { this.tokenizer.onToken = cb; } public set onValue( cb: ( value: JsonPrimitive | JsonStruct, key: JsonKey | undefined, parent: JsonStruct | undefined, stack: StackElement[] ) => void ) { this.tokenParser.onValue = cb; } public set onError(cb: (err: Error) => void) { this.tokenizer.onError = cb; } public set onEnd(cb: () => void) { this.tokenParser.onEnd = () => { if (!this.tokenizer.isEnded) this.tokenizer.end(); cb.call(this.tokenParser); }; } }