Skip to content

Instantly share code, notes, and snippets.

@tlrobinson
Forked from 140bytes/LICENSE.txt
Created October 3, 2011 16:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tlrobinson/1259489 to your computer and use it in GitHub Desktop.
Save tlrobinson/1259489 to your computer and use it in GitHub Desktop.
Prefix notation calculator interpreter

Prefix notation calculator interpreter

This is a very simple prefix notation calculator implementation in JavaScript, for the purpose of demonstrating a simple lexer, parser, compiler, and interpreter for my JSConf.eu talk, "JavaScript Compilers for Fun and Profit".

They're available packaged together here:

mini-calc-golfed.js contains each component JS-golfed down to < 140 bytes.

And individually as 140byt.es forks here:

function(node) {
if (Array.isArray(node)) {
// first element is the function, rest are the arguments
var fn = interpret(node[0]);
var args = node.slice(1).map(interpret);
return fn.apply(null, args);
} else if (typeof node === "number") {
// number literal
return node;
} else {
// lookup symbols in the environment object
return environment[node];
}
}
function(n){if(Array.isArray(n)){n=n.map(i);return n[0].apply(null,n.slice(1))}else{return typeofn=="number"?n:e[n]}}
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 Tom Robinson <http://tlrobinson.net/>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "theNameOfYourLibWhichMustBeAValidCamelCasedJavaScriptIdentifier",
"description": "This should be a short description of your entry.",
"keywords": [
"five",
"descriptive",
"keywords",
"or",
"fewer"
]
}
<!DOCTYPE html>
<title>Prefix notation calculator interpreter</title>
<script>
function repl(c,t,h,r){h=[t||""];while(s=prompt(h.slice(-10).join("\n"))){try{r=(c||eval)(s)}catch(e){r=e}h.push(""+r)}}
// lexer
function l(s){return s.match(/\(|\)|\d+(\.\d+)?|\w+|[+*\/-]/g).map(function(t){return /^\d/.test(t)?parseFloat(t):t})}
// parser
function p(a,b,c){c=[];a.shift();while(b=a.shift()){if(b=="("){a.unshift(b);c.push(p(a))}else if(b==")"){return c}else{c.push(b)}}}
// interpreter
function i(n){if(Array.isArray(n)){n=n.map(i);return n[0].apply(null,n.slice(1))}else{return typeofn=="number"?n:e[n]}}
repl(function(s) { return i(p(l(s))); }, "Prefix notation calculator interpreter, e.x. '(+ 1 (* 2 3))'")
</script>
@tsaniel
Copy link

tsaniel commented Oct 5, 2011

function(n){return Array.isArray(n)?(n=n.map(i))[0].apply(null,n.slice(1)):+n===n?n:e[n]}

Those are tricks from https://github.com/jed/140bytes/wiki/Byte-saving-techniques

@mirhmousavi
Copy link

why this statement wont work?
(+ (* (- 264 0) 2) 1)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment