Skip to content

Commit c99c670

Browse files
authored
Update 736-parse-lisp-expression.js
1 parent 2d991c0 commit c99c670

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

736-parse-lisp-expression.js

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,89 @@ const e = (x, v = []) =>
3131
),
3232
}[x[0]]()),
3333
}[typeof x]())
34+
35+
// another
36+
37+
/**
38+
* @param {string} expression
39+
* @return {number}
40+
*/
41+
const evaluate = function (expression) {
42+
const tokens = tokenizer(expression)
43+
let i = 0
44+
function exec(scope) {
45+
let value = null
46+
const next = tokens[i++]
47+
if (next === '(') {
48+
scope = enter(scope)
49+
switch (tokens[i++]) {
50+
case 'add':
51+
const a = exec(scope)
52+
const b = exec(scope)
53+
value = a + b
54+
break
55+
case 'mult':
56+
const x = exec(scope)
57+
const y = exec(scope)
58+
value = x * y
59+
break
60+
case 'let':
61+
while (tokens[i] !== '(' && tokens[i + 1] !== ')') {
62+
scope.variables[tokens[i++]] = exec(scope)
63+
}
64+
value = exec(scope)
65+
break
66+
}
67+
scope = exit(scope)
68+
i++
69+
} else if (isNumber(next)) {
70+
value = Number(next)
71+
} else {
72+
// Find variable in current scope otherwise go to parent
73+
let t = scope
74+
while (t) {
75+
if (next in t.variables) {
76+
value = t.variables[next]
77+
break
78+
}
79+
t = t.parent
80+
}
81+
}
82+
return value
83+
}
84+
return exec(newScope())
85+
}
86+
function tokenizer(expression) {
87+
const tokens = []
88+
let token = ''
89+
for (const c of expression) {
90+
if (c === '(' || c === ')') {
91+
if (token) tokens.push(token)
92+
tokens.push(c)
93+
token = ''
94+
} else if (c === ' ') {
95+
if (token) tokens.push(token)
96+
token = ''
97+
} else {
98+
token += c
99+
}
100+
}
101+
if (token) {
102+
tokens.push(token)
103+
}
104+
return tokens
105+
}
106+
function isNumber(n) {
107+
return !isNaN(n)
108+
}
109+
function newScope() {
110+
return { parent: null, variables: {} }
111+
}
112+
function enter(scope) {
113+
const next = newScope()
114+
next.parent = scope
115+
return next
116+
}
117+
function exit(scope) {
118+
return scope.parent
119+
}

0 commit comments

Comments
 (0)