/lib/r-fxxk.rb

https://github.com/masarakki/r-fxxk · Ruby · 109 lines · 98 code · 10 blank · 1 comment · 8 complexity · 7829020398d0b5121e37f8d1d15fece5 MD5 · raw file

  1. class Brainfuck
  2. def initialize(options = {})
  3. self.class.default_mapping.each do |key, default|
  4. operations[key] = options.has_key?(key) ? options[key] : default
  5. end
  6. end
  7. def self.bf_mapping
  8. @bf_operations ||= {nxt: '>', prv: '<', inc: '+', dec: '-', put: '.', get: ',', opn: '[', cls: ']' }
  9. end
  10. def self.default_mapping
  11. @default_mapping ||= bf_mapping.clone
  12. end
  13. def operations
  14. @operations ||= {}
  15. end
  16. default_mapping.keys.each do |op|
  17. define_method(op) do
  18. instance_variable_get(:@operations)[op]
  19. end
  20. end
  21. def compile(src)
  22. Brainfuck.new.translate(self, src)
  23. end
  24. def translate(other, src)
  25. other = other.new if other.kind_of?(Class)
  26. cur = 0
  27. inv = other.operations.invert
  28. reg = Regexp.compile "(#{other.operations.values.map{|v| Regexp.quote(v) }.join('|')})"
  29. dst = ''
  30. while matches = reg.match(src, cur)
  31. op = inv[matches[1]]
  32. dst += operations[op]
  33. cur = src.index(reg, cur) + matches[1].length
  34. end
  35. dst
  36. end
  37. def hello_world
  38. translate(Brainfuck, '>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-]<.>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>++++++++[<++++>-]<+.[-]++++++++++.')
  39. end
  40. def fuck(src)
  41. src = compile(src)
  42. ptr = 0
  43. cur = 0
  44. cell = Array.new(3000) { 0 }
  45. output = []
  46. inv = self.class.bf_mapping.invert
  47. reg = Regexp.compile "(#{self.class.bf_mapping.values.map{|v| Regexp.quote(v) }.join('|')})"
  48. while matches = reg.match(src, cur)
  49. next_cur = nil
  50. case inv[matches[1]]
  51. when :nxt
  52. ptr += 1
  53. when :prv
  54. ptr -= 1
  55. when :inc
  56. cell[ptr] += 1
  57. when :dec
  58. cell[ptr] -= 1
  59. when :put
  60. output << cell[ptr].chr
  61. when :get
  62. when :opn
  63. if cell[ptr] == 0
  64. open_count = 1
  65. buf_cur = cur
  66. while open_count > 0
  67. open_count.times do
  68. next_cur = src.index(self.class.bf_mapping[:cls], buf_cur)
  69. open_count = src[buf_cur+1..next_cur].count(self.class.bf_mapping[:opn])
  70. buf_cur = next_cur
  71. end
  72. end
  73. next_cur = next_cur + 1
  74. end
  75. when :cls
  76. close_count = 1
  77. buf_cur = cur
  78. while close_count > 0
  79. close_count.times do
  80. next_cur = src.rindex(self.class.bf_mapping[:opn], buf_cur)
  81. close_count = src[next_cur..buf_cur-1].count(self.class.bf_mapping[:cls])
  82. buf_cur = next_cur
  83. end
  84. end
  85. end
  86. cur = next_cur || src.index(reg, cur) + matches[1].length
  87. end
  88. output.join
  89. end
  90. class << self
  91. Brainfuck.default_mapping.keys.each do |op|
  92. define_method(op) do |val|
  93. default_mapping[op] = val
  94. end
  95. end
  96. end
  97. end
  98. # For backwards compatibility.
  99. BrainFuck = Brainfuck