parser.js

/** @module parser */

import * as Tokenizer from "./tokenizer.js"
import Record from "./record.js"

/**
 * @param   {string} str
 * @returns {Object[]}
 */
function tokenize(str) {
	const tokens = Tokenizer.tokenize(str)
	const lines = []
	const line = []
	for(const [index, token] of tokens.entries()) {
		if(token.name !== "separator" && token.name !== "line feed") {
			line.push(token)
		}
		if(token.name === "line feed" || index === tokens.length - 1) {
			lines.push([ ...line ])
			line.splice(0, line.length)
		}
	}
	return lines
}

/**
 * @param   {string} 	 str
 * @returns {Record[]}
 */
function parse(str) {
	const lines = tokenize(str)
	const records = []

	const flatRecords = []

	for(const line of lines) {

		const level = parseInt(line[0].buffer)

		const record = new Record(line[1].buffer)

		if(line.length === 3) {
			record.value = line[2].buffer
		}

		flatRecords.push({ level, record })

	}

	for(const [index, flatRecord] of flatRecords.entries()) {
		if(flatRecord.level === 0) {
			records.push(flatRecord.record)
		} else {
			const parentFlatRecords = flatRecords.slice(0, index)
			parentFlatRecords.reverse()
			const parentFlatRecord = parentFlatRecords.find(flatRecord_ => flatRecord_.level === flatRecord.level - 1)
			if(parentFlatRecord) {
				parentFlatRecord.record.appendChild(flatRecord.record)
			}
		}
	}

	return records
}

export {
	tokenize,
	parse
}