Skip to content

Instantly share code, notes, and snippets.

@PaulMaynard
Last active April 28, 2017 15:35
Show Gist options
  • Save PaulMaynard/09860ac0dfcfab7151d5 to your computer and use it in GitHub Desktop.
Save PaulMaynard/09860ac0dfcfab7151d5 to your computer and use it in GitHub Desktop.
Lambda calculus parser & compiler.
{
function compilejs(exp) {
if(exp.length == 1) {
return exp[0].replace(/[^a-zA-Z_$]/g, function(c) {
return "_$" + c.charCodeAt(0).toString(16) + "$_"
})
} else if(exp.length == 2) {
return compilejs(exp[0]) + "(" + compilejs(exp[1]) + ")"
} else if(exp.length == 3) {
return "(" + "function(" + compilejs(exp[1]) + ") {\n "
+ "return " + compilejs(exp[2]).trim().split('\n').map(function(l) {
return ' ' + l
}).join('\n')
+ "\n})"
}
}
function print(code) {
return code + '\n====>\n' + (function() {
try {
return eval(code)
} catch(e) {
return 'Error: ' + e
}
})()
}
// ----
function lambda(a, r) {
if(a.length == 1) {
return ['lambda', a[0], r]
} else {
return ['lambda', a[0], lambda(a.slice(1), r)]
}
}
}
prog
= f:exp space? a:exp { return print(compilejs([f, a])) }
/ e:exp { return print(compilejs(e)) }
exp
= var
/ call
/ func
/ lparen e:exp rparen { return e }
var
= n:(!lambda $[^\(\)λ\\\.])
{ return [n[1]] }
call
= lparen f:exp space? a:exp rparen { return [f, a] }
func
= lambda a:var+ dot r:exp
{
//alert(JSON.stringify(a))
return lambda(a, r)
}
lparen = "("
rparen = ")"
dot = '.'
space = ' '
lambda = ("lambda" / "λ" / "\\") { return "lambda" }
_ = [\r\n\t ]*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment