|
|
|
|
|
|
|
|
|
|
|
const OP = require('./op.js'); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function TokenStream(input){ |
|
|
function TokenStream(input){ |
|
|
var pos = 0; |
|
|
var pos = 0; |
|
|
|
|
|
|
|
|
function peek(){ |
|
|
function peek(){ |
|
|
return input[pos]; |
|
|
|
|
|
|
|
|
return (pos < input.length) ? input[pos] : null; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function next(){ |
|
|
function next(){ |
|
|
let v = input[pos]; |
|
|
|
|
|
pos += 1; |
|
|
|
|
|
return v; |
|
|
|
|
|
|
|
|
if (pos < input.length){ |
|
|
|
|
|
let v = input[pos]; |
|
|
|
|
|
pos += 1; |
|
|
|
|
|
return v; |
|
|
|
|
|
} |
|
|
|
|
|
return null; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function line(){ |
|
|
function line(){ |
|
|
|
|
|
|
|
|
die: die |
|
|
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; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
var stream = null; |
|
|
|
|
|
|
|
|
function isPunc(ch){ |
|
|
|
|
|
return isTokenType("punk", ch); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function isOpCode(ch){ |
|
|
|
|
|
return isTokenType("opcode", ch); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
parseDirective(){ |
|
|
|
|
|
let d = stream.next(); |
|
|
|
|
|
let args = []; |
|
|
|
|
|
while (stream.peek().line === d.line){ |
|
|
|
|
|
let a = stream.next(); |
|
|
|
|
|
switch(a.type){ |
|
|
|
|
|
case "number": |
|
|
|
|
|
// TODO: Check if math ops are called. |
|
|
|
|
|
case "string": |
|
|
|
|
|
args.push(a); |
|
|
|
|
|
break; |
|
|
|
|
|
case "label": |
|
|
|
|
|
args.push({ |
|
|
|
|
|
type: "var", |
|
|
|
|
|
val: a.val, |
|
|
|
|
|
line: a.line, |
|
|
|
|
|
col: a.col |
|
|
|
|
|
}); |
|
|
|
|
|
break; |
|
|
|
|
|
case "punc": |
|
|
|
|
|
// Ignore punctuations! |
|
|
|
|
|
break; |
|
|
|
|
|
default: |
|
|
|
|
|
stream.die("Invalid token '" + a.type + "'."); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
function isLabel(ch){ |
|
|
|
|
|
return isTokenType("label", ch); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
return { |
|
|
|
|
|
type: 'directive', |
|
|
|
|
|
args: args, |
|
|
|
|
|
line: d.line, |
|
|
|
|
|
col: d.col |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
function isDirective(ch){ |
|
|
|
|
|
return isTokenType("directive", ch); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
parseExpression(){ |
|
|
|
|
|
o = stream.peek(); |
|
|
|
|
|
if (o.type === 'directive'){ |
|
|
|
|
|
return parseDirective(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
function isOp(ch){ |
|
|
|
|
|
return isTokenType("op", ch); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
parse(tokens){ |
|
|
parse(tokens){ |
|
|
let p = { |
|
|
let p = { |
|
|
type: "prog", |
|
|
type: "prog", |