Initial work on collecting tail and text. Reorganizing for cleaner public API.

This commit is contained in:
Joshua Bemenderfer 2022-11-13 14:46:02 -05:00
parent e07e3a837c
commit 787b918b70

View File

@ -1,13 +1,33 @@
import { createLineData, useDocument } from '@terrace/core'
import { createStringReader } from '@terrace/core/readers/js-string'
const tceSchema = `
types
section object, text as content, tail as pos
content string
pos number
position number
options object
parameter1 number
parameter2 string
root object
title string
options options
options2 options
subsection section
`
const schema = {
types: {
subsection: {
section: {
type: 'object',
text: 'content',
tail: 'number',
tail: 'pos',
values: {
content: 'string',
pos: 'number',
position: {
type: 'number'
}
@ -28,8 +48,7 @@ const schema = {
options: 'options',
options2: 'options',
subsection: {
type: 'collection',
collection: 'subsection'
type: 'section',
}
}
}
@ -48,51 +67,49 @@ const lines = [
` Ea dolore in aliquip fugiat anim adipisicing amet aute tempor et deserunt est duis sint.`,
`subsection 2`,
` position 2`,
` Aute deserunt incididunt ad in sint adipisicing est officia velit pariatur ipsum deserunt quis nulla.`
` Aute deserunt incididunt ad in sint adipisicing est officia velit pariatur ipsum deserunt quis nulla.`,
` Ea dolore in aliquip fugiat anim adipisicing amet aute tempor et deserunt est duis sint.`
]
const typeHandlers = {
string (key, definition, add) {
return (doc, handlers) => {
if (doc.head() !== key) return
add(key, doc.tail().slice(1))
}
string (doc) {
return doc.tail().slice(1)
},
number (key, definition, add) {
return (doc, handlers) => {
if (doc.head() !== key) return
add(key, +doc.tail().slice(1))
}
number (doc) {
return +doc.tail().slice(1)
},
object (key, definition, add) {
definition = resolve(definition)
return (doc, handlers) => {
if (doc.head() !== key) return
const object = {}
add(key, object)
object (doc, handlers, definition) {
definition = lookup(definition)
for (const [key, child] of Object.entries(definition.values)) {
addHandler(handlers, doc.level() + 1, key, child, (key, value) => (object[key] = value))
}
}
},
collection (key, definition, add) {
return (doc, handlers) => {
if (doc.head() !== key) return
const collection = []
add(key, collection)
const object = {}
const child = resolve(definition.collection)
addHandler(handlers, doc.level() + 1, '*', child, (key, value) => ( collection.push(value) ))
for (const [key, child] of Object.entries(definition.values)) {
addHandler(handlers, doc.level() + 1, key, child, (key, value) => {
object[key] = value
})
}
if (definition.tail) {
object[definition.tail] = typeHandlers[definition.values[definition.tail]](doc, handlers)
}
if (definition.text) {
const textKey = definition.text
object[textKey] = ''
addHandler(handlers, doc.level() + 1, '', definition.values[textKey], (key, value) => {
object[textKey] += object[textKey] ? `\n${doc.line()}` : doc.line()
})
}
return object
}
}
function resolve (definition) {
function lookup (definition) {
const type = typeof definition === 'string' ? definition : definition.type
if (schema.types[type]) return schema.types[type]
else return definition
const resolvedDefinition = schema.types[type] || definition
return typeof definition === 'string' ? resolvedDefinition : Object.assign({}, definition, resolvedDefinition)
}
function registerTypes(typeHandlers, types) {
@ -102,22 +119,27 @@ function registerTypes(typeHandlers, types) {
}
}
function addHandler(handlers, level, key, definition, add) {
function addHandler(handlers, level, key, definition, resolve) {
const type = typeof definition === 'string' ? definition : definition.type
if (!handlers[level]) handlers[level] = []
handlers[level].push(typeHandlers[type](key, definition, add))
handlers[level].push({
key,
resolve,
definition,
handler: typeHandlers[type]
})
}
async function main() {
const doc = useDocument(createStringReader(lines))
const handlers = []
registerTypes(typeHandlers, schema.types)
const root = {}
for (const [key, child] of Object.entries(schema.root.values)) {
addHandler(handlers, 0, key, child, (key, value) => (root[key] = value))
addHandler(handlers, 0, key, child, (k, v) => (root[k] = v))
}
let ended = false
@ -128,8 +150,16 @@ async function main() {
const level = doc.level()
handlers.length = level + 1
for (const handler of handlers[level] || []) {
handler(doc, handlers)
const unmatchedHandler = handlers[level].find(h => h.key === '')
let matched = false
for (const { key, definition, resolve, handler } of handlers[level] || []) {
if (doc.head() !== key) continue;
resolve(doc.head(), handler(doc, handlers, definition))
matched = true
}
if (!matched && unmatchedHandler) {
const { resolve, definition, handler } = unmatchedHandler
resolve(doc.head(), handler(doc, handlers, definition))
}
}