Skip to content

Instantly share code, notes, and snippets.

@Strikeskids
Created February 13, 2014 04:01
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 Strikeskids/8969526 to your computer and use it in GitHub Desktop.
Save Strikeskids/8969526 to your computer and use it in GitHub Desktop.
var ops = {
'+': [1, 'AD', function(a,b) { return a+b; }],
'-': [1, 'SU', function(a,b) { return a-b; }],
'*': [2, 'MU', function(a,b) { return a*b; }],
'/': [2, 'DI', function(a,b) { return a/b; }]
};
var Compiler = function() {
};
Compiler.prototype.compile = function (program) {
return this.pass3(this.pass2(this.pass1(program)));
};
Compiler.prototype.tokenize = function (program) {
// Turn a program string into an array of tokens. Each token
// is either '[', ']', '(', ')', '+', '-', '*', '/', a variable
// name or a number (as a string)
var regex = /\s*([-+*\/\(\)\[\]]|[A-Za-z]+|\d+)\s*/g, ret = [], cur;
while (cur = regex.exec(program)) {
ret.push(isNaN(cur[1]) ? cur[1] : cur[1] | 0);
}
return ret;
};
Compiler.prototype.pass1 = function (program) {
var tokens = this.tokenize(program), i, argNames = [], token, finished = [], opstack = [], cur;
var pop = this.pop = this.pop || function() {
var ret = opstack.pop(), a, b;
if (ops.hasOwnProperty(ret)) {
b = finished.pop();
a = finished.pop();
finished.push({
'op': ret,
'a': a,
'b': b
});
}
return ret;
};
if (tokens[0] !== '[') {
throw 'Invalid function';
}
for (i=1;i<tokens.length && tokens[i] !== ']';++i) {
argNames.push(tokens[i]);
}
for (i++;i<tokens.length;++i) {
token = tokens[i];
if (!isNaN(token)) {
finished.push({
'op': 'imm',
'n': token
});
} else if (token === '(') {
opstack.push(token);
} else if (token === ')') {
while (opstack[opstack.length-1] !== '(') {
pop();
}
opstack.pop();
} else if (ops.hasOwnProperty(token)) {
while (ops.hasOwnProperty(cur = opstack[opstack.length-1]) && ops[cur][0] >= ops[token][0]) {
pop();
}
opstack.push(token);
} else {
finished.push({
'op': 'arg',
'n': argNames.indexOf(token)
});
}
}
while (opstack.length) {
pop();
}
return finished.pop();
};
Compiler.prototype.pass2 = function (ast) {
var ret = ast, az, bz, ao, bo;
if (ast.n || ast.n === 0) {
return ast;
} else {
ret.a = this.pass2(ast.a);
ret.b = this.pass2(ast.b);
if (ret.a.op === 'imm' && ret.b.op === 'imm') {
return {
op: 'imm',
n: ops[ast.op][2](ret.a.n, ret.b.n)
};
} else {
if (ret.a.op === 'imm') {
if (ret.a.n === 0) az = true;
if (ret.a.n === 1) ao = true;
}
if (ret.b.op === 'imm') {
if (ret.b.n === 0) bz = true;
if (ret.b.n === 1) bo = true;
}
switch (ret.op) {
case '*':
if (bz || az) {
return {
op: 'imm',
n: 0
}
}
if (ao) return ret.b;
case '/':
if (az) {
return {
op: 'imm',
n: 0
}
}
if (bo) return ret.a;
break;
case '+':
if (az) return ret.b;
case '-':
if (bz) return ret.a;
break;
}
return ret;
}
}
};
Compiler.prototype.pass3 = function (ast) {
var stack = [], ass = [], cur, ss = 0;
stack[ss++] = ast;
while (ss) {
cur = stack[--ss];
if (typeof cur === 'string') {
if (ass.length && ass[ass.length-1] === 'PU') ass.length--;
else ass.push('PO');
ass.push('SW');
ass.push('PO');
ass.push(cur);
ass.push('PU');
} else if (cur.n || cur.n === 0) {
ass.push(cur.op.toUpperCase().substring(0,2)+' '+cur.n);
ass.push('PU');
} else {
stack[ss++] = ops[cur.op][1];
stack[ss++] = cur.b;
stack[ss++] = cur.a;
}
}
return ass;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment