From a6435368aa0c6436ecd3dcbc97d0c7a362640974 Mon Sep 17 00:00:00 2001 From: Joshua Bemenderfer Date: Sun, 13 Nov 2022 16:12:57 -0500 Subject: [PATCH] More complete support for arrays and collections. --- docs/experiments/parser.js | 141 ++++++++++++++++++++++++++++++++----- 1 file changed, 124 insertions(+), 17 deletions(-) diff --git a/docs/experiments/parser.js b/docs/experiments/parser.js index 3f3d642..c5998e7 100644 --- a/docs/experiments/parser.js +++ b/docs/experiments/parser.js @@ -16,7 +16,13 @@ root object title string options options options2 options - subsection section + subsection + type section + collate collection + list array + - string + collection collection + section section ` const schema = { @@ -39,6 +45,12 @@ const schema = { parameter1: 'number', parameter2: 'string' } + }, + advList: { + type: 'array', + values: { + section: 'section' + } } }, root: { @@ -49,6 +61,24 @@ const schema = { options2: 'options', subsection: { type: 'section', + // Allows a particular repeated key to collect itself under a multi-value root as an array. + collate: 'collection' + }, + list: { + // Defines an array where all entries must conform to specific types. No other keys are permitted. + // Ex: [ value, value ] + type: 'array', + values: { + '-': 'string' + } + }, + collection: { + // Defines an array where all entries must conform to specific types. They will be segregated by key. No other keys are permitted. + // Ex: [ {key: value }, { key: value }] + type: 'collection', + values: { + section: 'section' + } } } } @@ -68,7 +98,16 @@ const lines = [ `subsection 2`, ` position 2`, ` 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.` + ` Ea dolore in aliquip fugiat anim adipisicing amet aute tempor et deserunt est duis sint.`, + `list`, + ` - item 1`, + ` - item 2`, + `collection`, + ` section`, + ` lorem ipsum 1`, + ` section`, + ` lorem ipsum 2` + ] @@ -79,31 +118,103 @@ const typeHandlers = { number (doc) { return +doc.tail().slice(1) }, - object (doc, handlers, definition) { + object (doc, handlers, definition, level) { + level = level != null ? level : doc.level() + 1 definition = lookup(definition) const object = {} - - for (const [key, child] of Object.entries(definition.values)) { - addHandler(handlers, doc.level() + 1, key, child, (key, value) => { - object[key] = value + for (let [key, child] of Object.entries(definition.values)) { + child = lookup(child) + addHandler(handlers, level, key, child, (key, value) => { + if (child.collate === 'array') { + if (!object[key]) object[key] = [] + object[key].push(value) + return + } else if (child.collate === 'collection') { + if (!object[key]) object[key] = [] + object[key].push({ [key]: value }) + return + } else { + object[key] = value + } }) } if (definition.tail) { - object[definition.tail] = typeHandlers[definition.values[definition.tail]](doc, handlers) + const tailKey = definition.tail + const tailType = definition.values[tailKey] + object[tailKey] = typeHandlers[tailType](doc, handlers) } if (definition.text) { const textKey = definition.text + const textType = definition.values[textKey] object[textKey] = '' - addHandler(handlers, doc.level() + 1, '', definition.values[textKey], (key, value) => { + addHandler(handlers, level, '', textType, (key, value) => { object[textKey] += object[textKey] ? `\n${doc.line()}` : doc.line() }) } return object - } + }, + array (doc, handlers, definition, level) { + level = level != null ? level : doc.level() + 1 + definition = lookup(definition) + + const array = [] + for (let [key, child] of Object.entries(definition.values)) { + child = lookup(child) + addHandler(handlers, level, key, child, (key, value) => { + array.push(value) + }) + } + + // if (definition.tail) { + // const tailKey = definition.tail + // const tailType = definition.values[tailKey] + // object[tailKey] = typeHandlers[tailType](doc, handlers) + // } + + // if (definition.text) { + // const textKey = definition.text + // const textType = definition.values[textKey] + // object[textKey] = '' + // addHandler(handlers, level, '', textType, (key, value) => { + // object[textKey] += object[textKey] ? `\n${doc.line()}` : doc.line() + // }) + // } + + return array + }, + collection (doc, handlers, definition, level) { + level = level != null ? level : doc.level() + 1 + definition = lookup(definition) + + const collection = [] + for (let [key, child] of Object.entries(definition.values)) { + child = lookup(child) + addHandler(handlers, level, key, child, (key, value) => { + collection.push({ [key]: value }) + }) + } + + // if (definition.tail) { + // const tailKey = definition.tail + // const tailType = definition.values[tailKey] + // object[tailKey] = typeHandlers[tailType](doc, handlers) + // } + + // if (definition.text) { + // const textKey = definition.text + // const textType = definition.values[textKey] + // object[textKey] = '' + // addHandler(handlers, level, '', textType, (key, value) => { + // object[textKey] += object[textKey] ? `\n${doc.line()}` : doc.line() + // }) + // } + + return collection + }, } function lookup (definition) { @@ -136,26 +247,22 @@ async function main() { registerTypes(typeHandlers, schema.types) - const root = {} - - for (const [key, child] of Object.entries(schema.root.values)) { - addHandler(handlers, 0, key, child, (k, v) => (root[k] = v)) - } + const root = typeHandlers.object(doc, handlers, schema.root, 0) let ended = false - let lastLevel = 0 while (!ended) { ended = await doc.next() if (ended) break; const level = doc.level() handlers.length = level + 1 - const unmatchedHandler = handlers[level].find(h => h.key === '') + 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 + break } if (!matched && unmatchedHandler) { const { resolve, definition, handler } = unmatchedHandler