-
Notifications
You must be signed in to change notification settings - Fork 0
/
parse-template.js
59 lines (51 loc) · 1.68 KB
/
parse-template.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// welcome to the \[n]th circle of tarnation: escaping backslashes and brackets
const debug = require('debug')(__filename.replace(/.*\//, ''))
const templateSectionRE = /(?<literal>([^[])+)|\[(?<slot>.*?)\]/imguy
// const templateSectionRE = /(?<literal>[^[]+)|\[(?<slot>.*?)\]/imguy
function * parseTemplate (t) {
let m
let i = 0
while ((m = templateSectionRE.exec(t))) {
// //console.log('\n\nmatch', m)
const g = m.groups
if (g.literal) {
let value = g.literal
// value = value.replace(/(\\\[)/g, '[')
// value = value.replace(/(\\\\)/g, '\\')
debug('got literal: %o (%s)', value, value)
yield value
} else {
const parsed = parseSlot(g.slot)
parsed.count = i++
yield parsed
}
}
}
// an optional type, a required name, extra parms
const slotRE = /^\s*(?<optional>optional\s+)?((?<type>\w+)\s+)?(?<name>\w+)\s*(,(?<parms>.*))?$/i
function parseSlot (decl) {
const m = decl.match(slotRE)
if (!m) {
console.error('text=%o', decl)
throw new Error('bad slot declaration')
}
let type = m.groups.type
let name = m.groups.name
let optional = !!m.groups.optional
if (name === 'id' || name === 'subject') {
if (type === undefined) {
type = 'ref'
} else if (type !== 'ref') {
// console.error(m.groups)
throw new Error('field names "id" and "subject" must be type "ref"')
}
// console.log('****OK', m.groups, {type, name})
}
if (type === undefined) type = 'string'
// nicer to leave it out than set it to false, I think?
const out = { type, name }
if (optional) out.optional = true
// console.log('****MORE', {type, name})
return out
}
module.exports = { parseTemplate }