Skip to content

Instantly share code, notes, and snippets.

@scyclow
Last active January 3, 2016 19:20
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 scyclow/92aaf255d43185a9f0b2 to your computer and use it in GitHub Desktop.
Save scyclow/92aaf255d43185a9f0b2 to your computer and use it in GitHub Desktop.
const expressionStart = (token) => token[0] === '(';
const expressionEnd = (token) => token[token.length - 1] === ')';
function evaluate(token) {
let numbered = Number(token);
if (token === 'true') {
return true;
} else if (token === 'false') {
return false;
// if coercing the token into a number doesn't return NaN
} else if (numbered == token) {
return numbered;
} else {
return token;
}
}
function findExpressionSize(tokens) {
let parenCount = 1;
let ix = 1;
for (; parenCount; ix++) {
const token = tokens[ix];
if (expressionStart(token)) {
parenCount += token.match(/\(/g).length;
} else if (expressionEnd(token)) {
parenCount -= token.match(/\)/g).length;
}
}
return ix;
}
function parse(string) {
const output = [];
const expression = string.slice(1, -1);
const tokens = expression.split(' ');
for (let i = 0; i < tokens.length; i++) {
const token = tokens[i];
if (expressionStart(token)) {
// How many tokens ahead does the expression end in?
const expressionSize = findExpressionSize(tokens.slice(i));
const expressionSubset = tokens.slice(i, i + expressionSize).join(' ');
output.push( parse(expressionSubset) );
i += expressionSize - 1;
} else {
output.push( evaluate(token) );
}
}
return output;
}
// Pretend these exist in the JS standard library
const add = (...args) => args.reduce((acc, item) => acc + item);
const subtract = (...args) => args.reduce((acc, item) => acc - item);
const functionMap = {
'+': add,
'-': subtract,
'**': Math.pow,
max: Math.max,
min: Math.min
};
function interpret(expression) {
const fn = functionMap[expression[0]];
const args = expression.slice(1).map(arg => {
if (typeof arg === 'object') {
return interpret(arg);
} else {
return arg;
}
})
return fn(...args);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment