UNPKG

brainfuck2wasm

Version:

Binaryen based compiler from brainfuck to WebAssembly (Wasm).

78 lines (63 loc) 1.75 kB
export default class Parser { constructor() { this.cmdMap = new Map(); this.cmdMap.set(43, '+'); this.cmdMap.set(45, '-'); this.cmdMap.set(62, '>'); this.cmdMap.set(60, '<'); this.cmdMap.set(46, '.'); this.cmdMap.set(44, ','); this.cmdMap.set(91, '['); this.cmdMap.set(93, ']'); this.cmdMap.set(35, '#'); } parse(input) { this.input = input; this.index = 0; this.ast = [{ kind: 'root', children: [] }]; while (!this.eof()) { this.parseCommand(); } const root = this.ast.pop(); if (root.kind !== 'root') throw new SyntaxError('unmatched ['); return root; } parseCommand() { let code; if (!this.isWhitespace(code = this.input[this.index++].charCodeAt())) { const kind = this.commandFor(code); const cmd = { kind }; const branch = this.ast[this.ast.length - 1]; if (kind === '[') { cmd.kind = 'loop'; cmd.children = []; branch.children.push(cmd); this.ast.push(cmd); } else if (kind === ']') { if (this.ast.pop().kind !== 'loop') throw new SyntaxError('unmatched ]'); } else { let eliminated = false; if (branch.children.length && kind !== '.' && kind !== ',') { const last = branch.children[branch.children.length - 1]; if (last.kind === kind) { last.amount++; eliminated = true; } } if (!eliminated) { cmd.amount = 1; branch.children.push(cmd); } } } } commandFor(code) { return this.cmdMap.get(code); } isWhitespace(code) { return !this.cmdMap.has(code); } eof() { return this.index >= this.input.length; } }