@gulujs/toml
Version:
TOML parser and serializer
88 lines (87 loc) • 3.23 kB
JavaScript
import { RE_ARRAY_TABLE_KEY, RE_FIRST_CHARACTER, RE_KEY, RE_TABLE_KEY } from './constants.js';
import { tryGetValue } from './types/index.js';
import { TableObject } from '../table-object/index.js';
import { SYNTAX_ERROR_MESSAGE } from '../errors/index.js';
import { DatetimeConverter, FloatConverter, IntegerConverter } from '../converter/index.js';
export class Parser {
constructor(source, options) {
this.source = source;
this.converters = {
integer: options?.integerConverter || new IntegerConverter(),
float: options?.floatConverter || new FloatConverter(),
datetime: options?.datetimeConverter || new DatetimeConverter()
};
this.obj = new TableObject(options);
}
parse() {
while (this.source.next()) {
if (this.source.line === '') {
break;
}
RE_FIRST_CHARACTER.lastIndex = 0;
const matches = RE_FIRST_CHARACTER.exec(this.source.line);
if (!matches) {
throw new SyntaxError(SYNTAX_ERROR_MESSAGE(this.source, 0));
}
if (matches[1]) {
this.handleKeyValue();
continue;
}
if (matches[2]) {
this.handleTable(RE_FIRST_CHARACTER.lastIndex);
continue;
}
if (matches[3]) {
this.handleTableArray(RE_FIRST_CHARACTER.lastIndex);
continue;
}
if (matches[4]) {
this.handleComment();
continue;
}
if (this.obj.enableTableComment) {
this.obj.clearComments();
}
}
return this.obj.root;
}
handleKeyValue() {
const key = this.source.getKey(0, RE_KEY);
if (!key) {
throw new SyntaxError(SYNTAX_ERROR_MESSAGE(this.source, 0));
}
const valueResult = tryGetValue(this.source, key.nextIndex, this.converters);
if (valueResult === null) {
throw new SyntaxError(SYNTAX_ERROR_MESSAGE(this.source, key.nextIndex));
}
this.source.assertWhitespaceOrComment(valueResult.nextIndex);
this.obj.set(key.path, valueResult.value);
}
handleTable(start) {
const key = this.source.getKey(start, RE_TABLE_KEY);
if (!key) {
throw new SyntaxError(SYNTAX_ERROR_MESSAGE(this.source, start));
}
this.source.assertWhitespaceOrComment(key.nextIndex);
this.obj.switchTable(key.path);
}
handleTableArray(start) {
const key = this.source.getKey(start, RE_ARRAY_TABLE_KEY);
if (!key) {
throw new SyntaxError(SYNTAX_ERROR_MESSAGE(this.source, start));
}
this.source.assertWhitespaceOrComment(key.nextIndex);
this.obj.switchArrayOfTables(key.path);
}
handleComment() {
const comment = this.source.assertWhitespaceOrComment(0);
if (this.obj.enableTableComment) {
if (typeof comment === 'undefined') {
this.obj.clearComments();
}
else {
this.obj.addComment(comment);
}
}
}
}