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.rb 1.5KB

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