You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bf.ts 2.2KB

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