@v4fire/core
Version:
V4Fire core library
151 lines (108 loc) • 3.06 kB
text/typescript
/*!
* 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;