Quellcode durchsuchen

More buildout of the parser

master
Bryan Miller vor 5 Jahren
Ursprung
Commit
4e64570f32
1 geänderte Dateien mit 78 neuen und 18 gelöschten Zeilen
  1. +78
    -18
      src/MOS/6502/assembler/parser.js

+ 78
- 18
src/MOS/6502/assembler/parser.js Datei anzeigen

@@ -1,5 +1,12 @@
const OP = require('./op.js');

const PRECEDENCE = {
"#": 0, // Precedence 0 should be ignored!
"=": 1,
"<":7, "<=":7, ">":7, ">=":7, "==":7, "!=":7,
"+": 10, "-": 10,
"*": 20, "/": 20
};

function TokenStream(input){
var pos = 0;
@@ -50,11 +57,7 @@ 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;
return (t && t.type === type && (!val || t.val === val) && t);
}

function isPunc(ch){
@@ -79,15 +82,13 @@ function isOp(ch){


function skipPunc(ch){
if (isPunc(ch)){
stream.next();
} else {
if (!isPunc(ch))
stream.die("Unexpected punctuation '" + ch + "'.");
}
stream.next();
}


parseDelimited(s,e,d,parser){
function parseDelimited(s,e,d,parser){
let toEOL = (s === null || e === null);
let a = [];
let first = true;
@@ -102,27 +103,34 @@ parseDelimited(s,e,d,parser){
return a;
}

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


parseOpCode(){
function 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,
args: parseDelimited(null, null, ",", parseExpression),
mode: mode
};
}

parseAtom(){
function parseAtom(){
if (isPunc("(")){
stream.next();
let exp = parseExpression();
@@ -132,18 +140,70 @@ parseAtom(){
}
} else if (isOpCode()){
return parseOpCode();
} else if (isDirective(".byte")){
return parseByteDirective();
}

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


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

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

function maybeCall(expr){
expr = expr();
return (isOp("(")) ? parseCall(expr) : expr;
}

function maybeBinary(left, pres){
let tok = isOp();
if (tok){
let cpres = PRECEDENCE[tok.val];
if (cpres > pres){
stream.next();
return maybeBinary({
type: (tok.val === "=") ? "assign" : "binary",
op: tok.val,
left: left,
right: maybeBinary(parseAtom(), cpres)
}, pres);
}
}
return left;
}

function parse(tokens){
let p = {
type: "prog",
expressions: [];
};
stream = TokenStream(tokens);
while (!stream.eof()){
p.expressions.push(parseExpression());
let e = parseExpression();
if (e.type === "label"){
e = {
type: "assign",
op: "=",
left: e,
right: "*" // To designate "current program counter".
}
}
p.expressions.push(e);
}
stream = null;
return p;

Laden…
Abbrechen
Speichern