|
- 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
- });
-
-
|