const OP = require('./op.js'); function TokenStream(input){ var pos = 0; function peek(){ return (pos < input.length) ? input[pos] : null; } function next(){ if (pos < input.length){ let v = input[pos]; pos += 1; return v; } return null; } function line(){ return (pos < input.length) ? input[pos].line : -1; } function col(){ return (pos < input.length) ? input[pos].col : -1; } function eol(){ return (pos < input.length - 1) ? (input[pos].line !== input[pos+1].line) : true; } function eof(){ return (pos >= input.length); } function die(msg){ throw new Error(msg + " Line: " + input[pos].line + ", Col: " + input[pos].col); } return { peek: peek, next: next, line: line, col: col, eof, eof, die: die }; } var stream = null; function isTokenType(type, val){ let t = stream.peek(); if (t !== null && t.type === type){ if (!val || t.val === val) return true; } return false; } function isPunc(ch){ return isTokenType("punc", ch); } function isOpCode(ch){ return isTokenType("opcode", ch); } function isLabel(ch){ return isTokenType("label", ch); } function isDirective(ch){ return isTokenType("directive", ch); } function isOp(ch){ return isTokenType("op", ch); } function skipPunc(ch){ if (isPunc(ch)){ stream.next(); } else { stream.die("Unexpected punctuation '" + ch + "'."); } } parseDelimited(s,e,d,parser){ let toEOL = (s === null || e === null); let a = []; let first = true; if (!toEOL){skipPunc(s);} while (!stream.eof() && ((!toEOL && isPunc(e)) || (toEOL && !stream.eol()))){ if (first){ first = false; } else {skipPunk(d);} a.push(parser()); } if (!toEOL){skipPunc(e);} return a; } parseOpCode(){ let val = stream.next(); let mode = 0; // Guess between absolute and zero page. let args = []; // TODO: Finish figuring out how to get the argument list! if (isOp("#")){ stream.next(); mode = 1; // Immediate } else if (isPunc("(")){ mode = 2; // Indirect // TODO: Use parseDelimited() } return { type: "opcode", val: val, args: args, mode: mode }; } parseAtom(){ if (isPunc("(")){ stream.next(); let exp = parseExpression(); if (isPunc(")")){ stream.next(); return exp; } } else if (isOpCode()){ return parseOpCode(); } } parse(tokens){ let p = { type: "prog", expressions: []; }; stream = TokenStream(tokens); while (!stream.eof()){ p.expressions.push(parseExpression()); } stream = null; return p; } module.exports = Object.freeze({ parse: parse });