Browse Source

Initial commit

master
Dylan Baker 1 year ago
commit
072f6f8a9a
5 changed files with 314 additions and 0 deletions
  1. 82
    0
      ruby/bf.rb
  2. 74
    0
      typescript/bf.ts
  3. 79
    0
      typescript/package-lock.json
  4. 17
    0
      typescript/package.json
  5. 62
    0
      typescript/tsconfig.json

+ 82
- 0
ruby/bf.rb View File

@@ -0,0 +1,82 @@
1
+def scan(source)
2
+  source
3
+    .chars
4
+    .filter { |c| "+-<>[].,".include?(c) }
5
+    .map(&:to_sym)
6
+end
7
+
8
+def parse(tokens)
9
+  position = 0
10
+  tree = Array.new
11
+
12
+  parse_node = Proc.new do |token|
13
+    case token
14
+    when :+, :-, :>, :<, :'.', :'.', :','
15
+      position += 1
16
+      token
17
+    when :"["
18
+      position += 1
19
+      body = Array.new
20
+
21
+      while position < tokens.size && tokens[position] != :"]"
22
+        body << parse_node.call(tokens[position])
23
+      end
24
+
25
+      raise "Unexpected EOF; expected ]" if position == tokens.size
26
+      position += 1 if tokens[position] == :"]"
27
+
28
+      body
29
+    else
30
+      raise "Unrecognized token #{token}"
31
+    end
32
+  end
33
+
34
+  while position < tokens.size
35
+    tree << parse_node.call(tokens[position])
36
+  end
37
+
38
+  tree
39
+end
40
+
41
+def interpret(tree)
42
+  stack = Array.new(100) { 0 }
43
+  position = 0
44
+  pointer = 0
45
+
46
+  interpret_node = Proc.new do |node|
47
+    case node
48
+    when :+
49
+      stack[pointer] += 1
50
+    when :-
51
+      stack[pointer] -= 1
52
+    when :>
53
+      raise "Out of bounds" if pointer >= 30_000
54
+      pointer += 1
55
+    when :<
56
+      raise "Below zero" if pointer <= 0
57
+      pointer -= 1
58
+    when :'.'
59
+      STDOUT.write stack[pointer].chr
60
+    when :','
61
+      char = STDIN.getc
62
+      stack[pointer] = char.ord
63
+    when Array
64
+
65
+      while stack[pointer] > 0
66
+        node.each { |subnode| interpret_node.call(subnode) }
67
+      end
68
+
69
+    else
70
+      raise "Unexpected node #{node}"
71
+    end
72
+  end
73
+
74
+  while position < tree.length
75
+    interpret_node.call(tree[position])
76
+    position += 1
77
+  end
78
+
79
+  STDOUT.print("\n")
80
+end
81
+
82
+interpret(parse(scan(ARGV.first))).inspect

+ 74
- 0
typescript/bf.ts View File

@@ -0,0 +1,74 @@
1
+type BFError = string;
2
+type Token = string;
3
+type Node = string | NodeArray;
4
+interface NodeArray extends Array<Node> {}
5
+
6
+const error = (message: BFError) => {
7
+  console.error(message);
8
+  process.exit(1);
9
+};
10
+
11
+const scan = (source: string): Token[] => {
12
+  return source.split('').filter((c) => "+-<>[].,".includes(c));
13
+};
14
+
15
+const parse = (tokens: Token[]): Node[] | undefined => {
16
+  let position = 0;
17
+  let tree: Node[] = [];
18
+  const parseNode = (token: string): Node | undefined => {
19
+    if ("+-<>.,".includes(token)) {
20
+      position++;
21
+      return token;
22
+    } else if (token === '[') {
23
+      position++;
24
+      const body: Node[] = [];
25
+      while (position < tokens.length && tokens[position] !== ']') {
26
+        const subnode = parseNode(tokens[position]);
27
+        if (subnode) body.push(subnode);
28
+      }
29
+      if (tokens[position] === ']') { position++; }
30
+      else if (position === tokens.length) { error('Expected ], got EOF'); }
31
+      return body;
32
+    } else {
33
+      error(`Unrecognized token ${token}`);
34
+    }
35
+  };
36
+  while (position < tokens.length) {
37
+    const node = parseNode(tokens[position]);
38
+    if (node) tree.push(node);
39
+  }
40
+  return tree;
41
+};
42
+
43
+const interpret = (tree: Node[]) => {
44
+  let position = 0;
45
+  let pointer = 0;
46
+  let stack = Array.from({ length: 30_000 }, () => 0);
47
+
48
+  const interpretNode = (node: Node) => {
49
+    switch (node) {
50
+      case '+': stack[pointer]++;                                          break;
51
+      case '-': stack[pointer]--;                                          break;
52
+      case '>': pointer++;                                                 break;
53
+      case '<': pointer--;                                                 break;
54
+      case '.': process.stdout.write(stack[pointer].toString());           break;
55
+      case ',': throw('Unimplemented');
56
+      default:
57
+        while (stack[pointer] > 0) {
58
+          let subposition = 0;
59
+          while (subposition < node.length) {
60
+            console.log(subposition);
61
+            interpretNode(node[subposition]);
62
+            subposition++;
63
+          }
64
+        }
65
+    }
66
+    position++;
67
+  };
68
+
69
+
70
+  while (position < tree.length) interpretNode(tree[position]);
71
+};
72
+
73
+const tree = parse(scan(process.argv[2]));
74
+if (tree) interpret(tree);

+ 79
- 0
typescript/package-lock.json View File

@@ -0,0 +1,79 @@
1
+{
2
+  "name": "bf-ts",
3
+  "version": "1.0.0",
4
+  "lockfileVersion": 1,
5
+  "requires": true,
6
+  "dependencies": {
7
+    "@types/node": {
8
+      "version": "12.7.5",
9
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.5.tgz",
10
+      "integrity": "sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w==",
11
+      "dev": true
12
+    },
13
+    "arg": {
14
+      "version": "4.1.1",
15
+      "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.1.tgz",
16
+      "integrity": "sha512-SlmP3fEA88MBv0PypnXZ8ZfJhwmDeIE3SP71j37AiXQBXYosPV0x6uISAaHYSlSVhmHOVkomen0tbGk6Anlebw==",
17
+      "dev": true
18
+    },
19
+    "buffer-from": {
20
+      "version": "1.1.1",
21
+      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
22
+      "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
23
+      "dev": true
24
+    },
25
+    "diff": {
26
+      "version": "4.0.1",
27
+      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz",
28
+      "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==",
29
+      "dev": true
30
+    },
31
+    "make-error": {
32
+      "version": "1.3.5",
33
+      "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.5.tgz",
34
+      "integrity": "sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g==",
35
+      "dev": true
36
+    },
37
+    "source-map": {
38
+      "version": "0.6.1",
39
+      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
40
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
41
+      "dev": true
42
+    },
43
+    "source-map-support": {
44
+      "version": "0.5.13",
45
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
46
+      "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
47
+      "dev": true,
48
+      "requires": {
49
+        "buffer-from": "^1.0.0",
50
+        "source-map": "^0.6.0"
51
+      }
52
+    },
53
+    "ts-node": {
54
+      "version": "8.4.1",
55
+      "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.4.1.tgz",
56
+      "integrity": "sha512-5LpRN+mTiCs7lI5EtbXmF/HfMeCjzt7DH9CZwtkr6SywStrNQC723wG+aOWFiLNn7zT3kD/RnFqi3ZUfr4l5Qw==",
57
+      "dev": true,
58
+      "requires": {
59
+        "arg": "^4.1.0",
60
+        "diff": "^4.0.1",
61
+        "make-error": "^1.1.1",
62
+        "source-map-support": "^0.5.6",
63
+        "yn": "^3.0.0"
64
+      }
65
+    },
66
+    "typescript": {
67
+      "version": "3.6.3",
68
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.3.tgz",
69
+      "integrity": "sha512-N7bceJL1CtRQ2RiG0AQME13ksR7DiuQh/QehubYcghzv20tnh+MQnQIuJddTmsbqYj+dztchykemz0zFzlvdQw==",
70
+      "dev": true
71
+    },
72
+    "yn": {
73
+      "version": "3.1.1",
74
+      "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
75
+      "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
76
+      "dev": true
77
+    }
78
+  }
79
+}

+ 17
- 0
typescript/package.json View File

@@ -0,0 +1,17 @@
1
+{
2
+  "name": "bf-ts",
3
+  "version": "1.0.0",
4
+  "description": "",
5
+  "main": "bf.ts",
6
+  "scripts": {
7
+    "node": "ts-node"
8
+  },
9
+  "keywords": [],
10
+  "author": "Dylan Baker <dylan@simulacrum.party>",
11
+  "license": "MIT",
12
+  "devDependencies": {
13
+    "@types/node": "^12.7.5",
14
+    "ts-node": "^8.4.1",
15
+    "typescript": "^3.6.3"
16
+  }
17
+}

+ 62
- 0
typescript/tsconfig.json View File

@@ -0,0 +1,62 @@
1
+{
2
+  "compilerOptions": {
3
+    /* Basic Options */
4
+    "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
5
+    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
6
+    "lib": ["ES2018"],                             /* Specify library files to be included in the compilation. */
7
+    // "allowJs": true,                       /* Allow javascript files to be compiled. */
8
+    // "checkJs": true,                       /* Report errors in .js files. */
9
+    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
10
+    // "declaration": true,                   /* Generates corresponding '.d.ts' file. */
11
+    // "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
12
+    // "sourceMap": true,                     /* Generates corresponding '.map' file. */
13
+    // "outFile": "./",                       /* Concatenate and emit output to single file. */
14
+    // "outDir": "./",                        /* Redirect output structure to the directory. */
15
+    // "rootDir": "./",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
16
+    // "composite": true,                     /* Enable project compilation */
17
+    // "incremental": true,                   /* Enable incremental compilation */
18
+    // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
19
+    // "removeComments": true,                /* Do not emit comments to output. */
20
+    // "noEmit": true,                        /* Do not emit outputs. */
21
+    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
22
+    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
23
+    // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
24
+
25
+    /* Strict Type-Checking Options */
26
+    "strict": true,                           /* Enable all strict type-checking options. */
27
+    // "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
28
+    // "strictNullChecks": true,              /* Enable strict null checks. */
29
+    // "strictFunctionTypes": true,           /* Enable strict checking of function types. */
30
+    // "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
31
+    // "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
32
+    // "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
33
+    // "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */
34
+
35
+    /* Additional Checks */
36
+    // "noUnusedLocals": true,                /* Report errors on unused locals. */
37
+    // "noUnusedParameters": true,            /* Report errors on unused parameters. */
38
+    // "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
39
+    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */
40
+
41
+    /* Module Resolution Options */
42
+    // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
43
+    // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
44
+    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
45
+    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
46
+    // "typeRoots": [],                       /* List of folders to include type definitions from. */
47
+    // "types": [],                           /* Type declaration files to be included in compilation. */
48
+    // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
49
+    "esModuleInterop": true                   /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
50
+    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
51
+
52
+    /* Source Map Options */
53
+    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
54
+    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
55
+    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
56
+    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
57
+
58
+    /* Experimental Options */
59
+    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
60
+    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
61
+  }
62
+}

Loading…
Cancel
Save