Skip to content

Instantly share code, notes, and snippets.

@yortuc
Last active April 6, 2018 15:11
Show Gist options
  • Save yortuc/0669e379b90f62ef713d02e2f64d75df to your computer and use it in GitHub Desktop.
Save yortuc/0669e379b90f62ef713d02e2f64d75df to your computer and use it in GitHub Desktop.
Lisp Clone
const funs = {
sqrt: (val) => Math.sqrt(val),
sum: (a,b)=> a + b,
mul: (a,b) => a * b
}
class Exp {
constructor(fnName, params){
this.fnName = fnName
this.params = params
}
eval(){
// evaluate function parameters (call-by-val)
const paramVals = this.params.map(p=> typeof p === 'object' ? p.eval() : p)
return funs[this.fnName](...paramVals)
}
}
function run(str){
const tokens = lex(str)
const rootExp = ast(tokens)
console.log(rootExp)
console.log(rootExp.eval())
}
function lex(str){
const norm = str.replace(/\(/g, ' ')
.replace(/\)/g, ' ')
return norm.split(' ').filter(f=> f.length>0)
}
function ast(tokens){
let paramStack = []
tokens.reverse().forEach(t => {
if(funs[t]){
const exp = new Exp(t, [...paramStack.reverse()])
paramStack = [exp]
}
else{
const val = parseFloat(t) || t
paramStack.push(val)
}
})
return paramStack[0]
}
run(`sqrt(sum(2 mul(3 4)))`) // returns 3.7416573867739413
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment