Skip to content

Instantly share code, notes, and snippets.

@Gerjo
Created January 5, 2015 09:41
Show Gist options
  • Save Gerjo/de5951d4c6b8f78dca64 to your computer and use it in GitHub Desktop.
Save Gerjo/de5951d4c6b8f78dca64 to your computer and use it in GitHub Desktop.
Parser.prototype.interpret = function(input, offset, depth, parent, linenumber) {
depth = depth || 0;
offset = offset || 0;
parent = parent || null;
var PAREN_START = '(';
var PAREN_END = ')';
var CHAIN = '.';
var COMMA = ',';
var ALIAS = '=';
var NEWLINE = '\n';
var params = [];
var startIndex = false;
var aliasName = false;
var r = null;
if(depth > 100) {
throw new Error("infinite");
}
//console.log("raw", input.substr(offset));
for(var i = offset; i < input.length; ++i) {
var chr = input.charAt(i);
if(chr === NEWLINE) {
++linenumber;
}
//console.log(char);
if(chr === PAREN_START) {
if(startIndex === false) {
startIndex = i;
} else {
r = this.interpret(input, i, depth + 1, null, linenumber);
i = r.offset;
linenumber = r.linenumber;
params.push(r.instruction);
}
} else if(chr === PAREN_END || i === input.length-1) {
if(startIndex !== false) {
var trimOffset = (chr === PAREN_END) ? 1:0;
var func = this.backtraceFunction(input, startIndex);
var raw = input.substr(startIndex + 1, i - startIndex - trimOffset);
// NB: only this "root-like" instruction receives an alias. The
// execute method of an instruction will know what do with it.
var instruction = new Instruction(func, raw, params, linenumber);
instruction.alias = aliasName;
if(parent) {
parent.neighbours.push(instruction);
}
var next = input.charAt(i + 1);
if(next === CHAIN) {
r = this.interpret(input, i + 1, depth + 1, null, linenumber);
// There may not be a sensible chain. EG: the user is
// still typing.
if(r.instruction) {
instruction.chain.push(r.instruction);
}
linenumber = r.linenumber;
i = r.offset;
}
aliasName = false;
startIndex = false;
params = [];
// The root node can contain multiple statements.
if(depth === 0) {
continue;
}
return pair(i, instruction, linenumber);
} else {
// The only error message available :o
//console.log("Malformed code. Found and 'end paren' without a 'start paren'.");
//console.log(startIndex, input.substr(startIndex + 1, i - startIndex - 1));
// Crashing on an error is so 1996.
continue;
}
} else if(chr === ALIAS) {
aliasName = this.backtraceAlias(input, i);
// Removed startIndex check. fixes the loading of of 'p' in 'point(p.add(10))'
// May have broken other things. Added this back near the end of this block.
} else if(chr === CHAIN/* && startIndex === false*/) {
var varName = this.backtraceVariable(input, i);
// This is not a variable chain, but a normal chain.
if(varName === "") {
continue;
}
var instruction = new Instruction('load', varName, null, linenumber);
//console.log("ld instruction for:" + varName);
// Special case for: i = a.intersection(b) at root:
if(startIndex === false) {
instruction.alias = aliasName;
aliasName = false;
// Perhaps do more here?
}
var regex = /^([a-zA-Z]{1,1})$/;
if(! input.charAt(i + 1).match(regex)) {
// Fake chain. EG: the user entered a string that has a period in it.
continue;
}
r = this.interpret(input, i + 1, depth + 1, null, linenumber);
linenumber = r.linenumber;
if(r.instruction) {
instruction.chain.push(r.instruction);
}
i = r.offset;
//console.log(parent, instruction);
// Special root case, I think. Perhaps depth === 0? dunno.
if(startIndex === false) {
parent.neighbours.push(instruction);
} else {
// fixes 'a.add(-10)' in segment(10, 10, a.add(-10)).
params.push(instruction);
}
}
}
return pair(input.length, null, linenumber);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment