-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.js
70 lines (68 loc) · 1.8 KB
/
parser.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
60
61
62
63
64
65
66
67
68
69
70
const parser = module.exports = function parser (start = '(', end = ')') {
return { parse, serialize }
/**
* Parse a string with nested parentheses into a tree of parened-terms
* in: "hello (feyn) (ben (esquire);you)"
* out: [ 'hello ', [ 'feyn' ], ' ', [ 'ben ', [ 'esquire' ], ';you' ] ]
*/
function parse (str) {
const tree = []
const stack = []
let term = ''
let cur = tree
const log = (where) => {
// console.log(where, { cur, term, stack, tree, stack })
}
const startNode = () => {
log('prestart')
if (!cur) cur = []
if (term) cur.push(term)
stack.push(cur)
cur = []
term = ''
log('endstart')
}
const endNode = () => {
log('preend')
cur.push(term)
const last = cur
cur = stack.pop()
if (cur) cur.push(last)
term = ''
log('endend')
}
for (let char of str) {
switch (char) {
case start:
startNode()
break
case end:
endNode()
break
default:
term += char
continue
}
}
if (term && !tree.length) tree.push(term)
return tree
}
/**
* Serialize tree back to string
* in: [ 'hello ', [ 'feyn' ], ' ', [ 'ben ', [ 'esquire' ], ';you' ] ]
* out: "hello (feyn) (ben (esquire);you)"
*/
function serialize (tree, depth = 0) {
if (typeof tree === 'undefined') throw new Error('tree should not be undefined')
if (typeof tree === 'string') return tree
const inner = tree.map(l => serialize(l, true)).join('')
if (depth > 0) return ['(', inner, ')'].join('')
return inner
}
}
if (require.main === module) {
const { parse, serialize } = parser('(', ')')
const parsed = parse(process.argv[2])
console.log(parsed)
console.log(serialize(parsed))
}