140 lines
3.5 KiB
JavaScript
140 lines
3.5 KiB
JavaScript
import { SYMBOLS, parse, isScope, isMacro, getTail, getText, getUnmatched, isCollection } from './core.js'
|
|
|
|
const schemaTCE = `
|
|
macros
|
|
primitive match number string
|
|
section
|
|
pos number tail
|
|
content string unmatched
|
|
position number
|
|
options
|
|
parameter1 number
|
|
parameter2 string
|
|
literal unmatched string
|
|
unmatched primitive
|
|
|
|
root
|
|
title string
|
|
options options collection
|
|
subsection section
|
|
list
|
|
- string array
|
|
collection
|
|
section collection
|
|
collection2
|
|
unmatched collection
|
|
`
|
|
|
|
function head(line) {
|
|
return line.split(' ')[0]
|
|
}
|
|
|
|
function tail(line) {
|
|
return line.split(' ').slice(1).join(' ')
|
|
}
|
|
|
|
function chain(...macroNames) {
|
|
return (args) => {
|
|
for (const macroName of macroNames) {
|
|
if (args.macros[macroName]) args.entry = args.macros[macroName](args)
|
|
}
|
|
return args.entry
|
|
}
|
|
}
|
|
|
|
const schema = {
|
|
macros: {
|
|
tail({ entry }) {
|
|
return [head(entry[0]), tail(entry[0])]
|
|
},
|
|
string({ entry }) {
|
|
return [entry[0], entry[1].toString()]
|
|
},
|
|
number({ entry }) {
|
|
const num = +entry[1]
|
|
if (isNaN(num) || entry[1] === '') return entry
|
|
return [entry[0], num]
|
|
},
|
|
primitive(args) {
|
|
const num = macros.number(args)
|
|
return num !== undefined ? num : macros.string(args)
|
|
},
|
|
scope({ addScope, head, tail, entry }, definition) {
|
|
return addScope({ definition, head, tail, entry })
|
|
},
|
|
section: isScope({
|
|
[SYMBOLS.TAIL]: getTail('pos', isMacro('number')),
|
|
[SYMBOLS.UNMATCHED]: getText('content', isMacro('string')),
|
|
position: isMacro('number')
|
|
}),
|
|
options: isScope({
|
|
parameter1: isMacro('number'),
|
|
parameter2: isMacro('string'),
|
|
unmatched: isMacro('string'),
|
|
[SYMBOLS.UNMATCHED]: getUnmatched(isMacro('any')),
|
|
}),
|
|
any(args) {
|
|
const macro = args.macros[args.head]
|
|
if (macro) return macro(args)
|
|
const numResult = args.macros.number(args)
|
|
if (numResult !== undefined) return numResult
|
|
args.tail = args.entry
|
|
return args.macros.string(args)
|
|
},
|
|
},
|
|
root: {
|
|
// Move tail into value position and cast it to string.
|
|
title: chain('tail', 'string'),
|
|
// options: isMacro('options'),
|
|
// subsection: isMacro('section'),
|
|
// list: isScope({
|
|
// '-': isMacro('string')
|
|
// }),
|
|
// collection: isScope({
|
|
// section: isCollection(isMacro('section'))
|
|
// }),
|
|
// collection2: isScope({
|
|
// [SYMBOLS.UNMATCHED]: getUnmatched(isMacro('any'))
|
|
// })
|
|
}
|
|
}
|
|
|
|
|
|
const lines = [
|
|
`title Example`,
|
|
`options`,
|
|
` parameter1 30`,
|
|
` parameter2 Enim eu id anim minim reprehenderit nostrud eu amet deserunt ea ut do cupidatat ea.`,
|
|
`options`,
|
|
` parameter1 0`,
|
|
` parameter2 Esse incididunt et est adipisicing eiusmod aliqua enim ea aliqua id enim.`,
|
|
`subsection`,
|
|
` position 1`,
|
|
` 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.`,
|
|
` 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`,
|
|
`collection2`,
|
|
` section`,
|
|
` position 3`,
|
|
` Laborum aute anim occaecat occaecat pariatur tempor proident magna sit magna non non.`,
|
|
` list`,
|
|
` 1`,
|
|
` 2`
|
|
]
|
|
|
|
async function main() {
|
|
console.dir(await parse(lines, schema), { depth: null })
|
|
}
|
|
|
|
main()
|