mirror of
https://github.com/Noratrieb/brainfuck.git
synced 2026-01-14 13:35:00 +01:00
javascript
This commit is contained in:
parent
a52cbda492
commit
54b5c9b1f8
7 changed files with 186 additions and 54 deletions
2
js/.gitignore
vendored
Normal file
2
js/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
.idea
|
||||
4
js/.prettierrc.json
Normal file
4
js/.prettierrc.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"singleQuote": true,
|
||||
"printWidth": 100
|
||||
}
|
||||
2
js/fizzbuzz.bf
vendored
Normal file
2
js/fizzbuzz.bf
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
++[-].
|
||||
10
js/package.json
Normal file
10
js/package.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "brainfuck",
|
||||
"version": "1.0.0",
|
||||
"main": "src/index.js",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"prettier": "^2.6.2"
|
||||
}
|
||||
}
|
||||
110
js/src/index.js
Normal file
110
js/src/index.js
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
import fs from 'fs/promises';
|
||||
|
||||
function lex(string) {
|
||||
const tokens = [];
|
||||
|
||||
for (let i = 0; i < string.length; i++) {
|
||||
const char = string[i];
|
||||
if (['+', '-', '>', '<', '.', ',', '[', ']'].includes(char)) {
|
||||
tokens.push({
|
||||
char,
|
||||
span: i
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
function ParseError(message, span) {
|
||||
this.message = message;
|
||||
this.span = span;
|
||||
}
|
||||
|
||||
function Parser(tokens) {
|
||||
this.tokens = tokens;
|
||||
this.position = 0;
|
||||
}
|
||||
|
||||
Parser.prototype.next = function() {
|
||||
const token = this.tokens[this.position];
|
||||
this.position++;
|
||||
return token;
|
||||
};
|
||||
|
||||
Parser.prototype.parse = function(isLoop) {
|
||||
const body = [];
|
||||
let nextToken;
|
||||
while ((nextToken = this.next()) !== undefined) {
|
||||
switch (nextToken.char) {
|
||||
case '[': {
|
||||
const loopBody = this.parse(true);
|
||||
body.push(loopBody);
|
||||
break;
|
||||
}
|
||||
case ']': {
|
||||
if (isLoop) {
|
||||
return body;
|
||||
} else {
|
||||
throw new ParseError('No matching `[` found', nextToken.span);
|
||||
}
|
||||
}
|
||||
default: {
|
||||
body.push(nextToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isLoop) {
|
||||
throw new ParseError('No matching `]` found', this.tokens[this.tokens.length - 1].span);
|
||||
} else {
|
||||
return body;
|
||||
}
|
||||
};
|
||||
|
||||
function reportError(source, message, span) {
|
||||
let lineIdx = 0;
|
||||
let lastNewlineIdx = 0;
|
||||
for (let i = 0; i < source.length; i++) {
|
||||
const char = source[i];
|
||||
if (i === span) {
|
||||
break;
|
||||
}
|
||||
if (char === '\n') {
|
||||
lineIdx++;
|
||||
lastNewlineIdx = i;
|
||||
}
|
||||
}
|
||||
|
||||
const lines = source.split('\n');
|
||||
const line = lines[lineIdx];
|
||||
const lineNumber = String(lineIdx + 1);
|
||||
|
||||
const linePrefix = `${lineNumber} | `;
|
||||
const lineSpan = span - lastNewlineIdx;
|
||||
|
||||
console.error(`error: ${message}`);
|
||||
console.error(`${linePrefix}${line}`);
|
||||
console.error(`${' '.repeat(linePrefix.length)}${'-'.repeat(lineSpan)}^`);
|
||||
}
|
||||
|
||||
const file = process.argv[2];
|
||||
|
||||
if (!file) {
|
||||
console.error('Usage: [filename]');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const source = await fs.readFile(file, 'utf-8');
|
||||
const tokens = lex(source);
|
||||
|
||||
const parser = new Parser(tokens);
|
||||
try {
|
||||
const ast = parser.parse(false);
|
||||
console.log(ast);
|
||||
} catch (parseError) {
|
||||
if (!(parseError instanceof ParseError)) {
|
||||
throw parseError;
|
||||
}
|
||||
reportError(source, parseError.message, parseError.span);
|
||||
}
|
||||
8
js/yarn.lock
Normal file
8
js/yarn.lock
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
prettier@^2.6.2:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.2.tgz#e26d71a18a74c3d0f0597f55f01fb6c06c206032"
|
||||
integrity sha512-PkUpF+qoXTqhOeWL9fu7As8LXsIUZ1WYaJiY/a7McAQzxjk82OF0tibkFXVCDImZtWxbvojFjerkiLb0/q8mew==
|
||||
Loading…
Add table
Add a link
Reference in a new issue