UNPKG

@v4fire/core

Version:
151 lines (108 loc) 3.06 kB
/*! * V4Fire Core * https://github.com/V4Fire/Core * * Released under the MIT license * https://github.com/V4Fire/Core/blob/master/LICENSE */ import type Parser from 'core/json/stream/parser'; import { parserStates, parserStateTypes, parserExpected, MAX_PATTERN_SIZE, PARSING_COMPLETE } from 'core/json/stream/parser/const'; import type { Token, ParentParserState } from 'core/json/stream/parser/interface'; /** * Parses the buffer for a value, generates a sequence of tokens, and sets the next expected value */ export function* value(this: Parser): Generator<Token> { this.patterns.value1.lastIndex = this.index; this.matched = this.patterns.value1.exec(this.buffer); if (this.matched == null) { if (this.index + MAX_PATTERN_SIZE < this.buffer.length) { if (this.index < this.buffer.length) { throw new SyntaxError("Can't parse the input: expected a value"); } throw new SyntaxError('The parser has expected a value'); } return PARSING_COMPLETE; } this.value = this.matched[0]; switch (this.value) { case '"': yield {name: 'startString'}; this.expected = parserStateTypes.STRING; break; case '{': yield {name: 'startObject'}; this.stack.push(this.parent); this.parent = parserStateTypes.OBJECT; this.expected = parserStateTypes.KEY1; break; case '[': yield {name: 'startArray'}; this.stack.push(this.parent); this.parent = parserStateTypes.ARRAY; this.expected = parserStateTypes.VALUE1; break; case ']': if (this.expected !== parserStateTypes.VALUE1) { throw new SyntaxError("Parser cannot parse input: unexpected token ']'"); } if (this.isOpenNumber) { yield {name: 'endNumber'}; yield {name: 'numberValue', value: this.accumulator}; this.isOpenNumber = false; this.accumulator = ''; } yield {name: 'endArray'}; this.parent = <ParentParserState>this.stack.pop(); this.expected = parserExpected[this.parent]; break; case '-': this.isOpenNumber = true; yield {name: 'startNumber'}; yield {name: 'numberChunk', value: '-'}; this.accumulator = '-'; this.expected = parserStateTypes.NUMBER_START; break; case '0': this.isOpenNumber = true; yield {name: 'startNumber'}; yield {name: 'numberChunk', value: '0'}; this.accumulator = '0'; this.expected = parserStateTypes.NUMBER_FRACTION; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': this.isOpenNumber = true; yield {name: 'startNumber'}; yield {name: 'numberChunk', value: this.value}; this.accumulator = this.value; this.expected = parserStateTypes.NUMBER_DIGIT; break; case 'true': case 'false': case 'null': yield { name: `${this.value}Value`, value: Object.parse(this.value) }; this.expected = parserExpected[this.parent]; break; default: // Do nothing; } this.index += this.value.length; } parserStates[parserStateTypes.VALUE] = value; parserStates[parserStateTypes.VALUE1] = value;