Переглянути джерело

Parse coming along

master
Bryan Miller 5 роки тому
джерело
коміт
58201c6cf6
1 змінених файлів з 105 додано та 19 видалено
  1. +105
    -19
      src/MOS/6502/assembler/parser.js

+ 105
- 19
src/MOS/6502/assembler/parser.js Переглянути файл

} }


function eol(){ function eol(){
return (pos < input.length - 1) ? (input[pos].line !== input[pos+1].line) : true;
return (pos > 0) ? (input[pos-1].line !== input[pos].line) : true;
} }


function eof(){ function eof(){
next: next, next: next,
line: line, line: line,
col: col, col: col,
eol: eol,
eof, eof, eof, eof,
die: die die: die
}; };
} }




function skipDirective(ch){
if (!isDirective(ch))
stream.die("Unexpected directive '" + ch + "'.");
stream.next();
}


function parseDelimited(s,e,d,parser){ function parseDelimited(s,e,d,parser){
let toEOL = (s === null || e === null); let toEOL = (s === null || e === null);
let a = []; let a = [];
while (!stream.eof() && ((!toEOL && isPunc(e)) || (toEOL && !stream.eol()))){ while (!stream.eof() && ((!toEOL && isPunc(e)) || (toEOL && !stream.eol()))){
if (first){ if (first){
first = false; first = false;
} else {skipPunk(d);}
} else {skipPunc(d);}
a.push(parser()); a.push(parser());
} }
if (!toEOL){skipPunc(e);} if (!toEOL){skipPunc(e);}
} }


function parseByteDirective(){ function parseByteDirective(){
let line = stream.line();
let col = stream.col();
stream.next(); stream.next();
return { return {
type: "directive", type: "directive",
op: ".byte", op: ".byte",
args: parseDelimited(null, null, ",", parseExpression);
args: parseDelimited(null, null, ",", parseExpression),
line: line,
col: col
}
}


function parseElseIfDirective(){
skipDirective(".elseif");
let cond = parseExpression();
skipDirective(".then");
let then = parseBlock([".else", ".elif", ".endif"]);
let f = {
type: "directive",
op: "if",
cond: cond,
then: then
}
if (isDirective(".elif")){
f["else"] = parseElseIfDirective();
} else if (isDirective(".else")){
f["else"] = parseBlock([".endif"]);
} else if(!isDirective(".endif")){
stream.die("Expected '.endif' Directive.");
}
return f;
}


function parseIfDirective(){
skipDirective(".if");
let cond = parseExpression();
skipDirective(".then");
let then = parseExpression();
let f = {
type: "directive",
op: "if",
cond: cond,
then: then
};
if (isDirective(".elif")){
f["else"] = parseElseIfDirective();
} else if (isDirective(".else")){
f["else"] = parseBlock([".endif"]);
} }
skipDirective(".endif");
return f;
} }




function parseOpCode(){ function parseOpCode(){
let line = stream.line();
let col = stream.col();
let val = stream.next(); let val = stream.next();
let mode = 0; // Guess between absolute and zero page. let mode = 0; // Guess between absolute and zero page.
if (isOp("#")){ if (isOp("#")){
} }
return { return {
type: "opcode", type: "opcode",
val: val,
op: val,
args: parseDelimited(null, null, ",", parseExpression), args: parseDelimited(null, null, ",", parseExpression),
mode: mode
mode: mode,
line: line,
col: col
}; };
} }


} }
} else if (isOpCode()){ } else if (isOpCode()){
return parseOpCode(); return parseOpCode();
} else if (isDirective(".byte")){
} else if (isDirective(".if")){
return parseIfDirective();
} else if (isDirective(".bytes")){
return parseByteDirective(); return parseByteDirective();
} }


let tok = stream.next(); let tok = stream.next();
if (tok.type === "number" || tok.type === "string" || tok.type === "label") if (tok.type === "number" || tok.type === "string" || tok.type === "label")
return tok; return tok;
stream.die("Unexpected token " + tok);
stream.die("Unexpected token {type:" + tok.type + ", val:'" + tok.val + "'}.");
} }




function parseExpression(){ function parseExpression(){
maybeCall(function(){
return maybeBinary(parseAtom, 0);
return maybeCall(function(){
return maybeBinary(parseAtom(), 0);
}); });
} }


return { return {
type: "call", type: "call",
func: func, func: func,
args: parseDelimited("(", ")", ",", parseExpression);
args: parseDelimited("(", ")", ",", parseExpression)
}; };
} }


type: (tok.val === "=") ? "assign" : "binary", type: (tok.val === "=") ? "assign" : "binary",
op: tok.val, op: tok.val,
left: left, left: left,
right: maybeBinary(parseAtom(), cpres)
right: maybeBinary(parseAtom(), cpres),
line: tok.line,
col: tok.col
}, pres); }, pres);
} }
} }
return left; return left;
} }


function parse(tokens){
let p = {
type: "prog",
expressions: [];
};
stream = TokenStream(tokens);
function parseBlock(bed){
let exp = [];
let isBlockEnd = (t) => {
return (bed && t.type === 'directive' && bed.indexOf(t.val) >= 0);
}
while (!stream.eof()){ while (!stream.eof()){
if (isBlockEnd(stream.peek()))
break;
let e = parseExpression(); let e = parseExpression();
if (e.type === "label"){ if (e.type === "label"){
e = { e = {
type: "assign", type: "assign",
op: "=", op: "=",
left: e, left: e,
right: "*" // To designate "current program counter".
right: "*", // To designate "current program counter".
line: e.line,
col: e.col
} }
} }
p.expressions.push(e);
exp.push(e);
if (!stream.eol())
stream.die("Expected End of Line.");
} }
return exp;
}

function parseProg(ed){
let line = stream.line();
let col = stream.col();
return {
type: "prog",
expressions: parseBlock(),
line: line,
col: col
};
}

function parse(tokens){
stream = TokenStream(tokens);
let p = parseProg();
stream = null; stream = null;
return p; return p;
} }

Завантаження…
Відмінити
Зберегти