lib/ragel/bitmap/replace.rb in ragel-bitmap-0.1.0 vs lib/ragel/bitmap/replace.rb in ragel-bitmap-0.2.0
- old
+ new
@@ -1,32 +1,57 @@
# frozen_string_literal: true
require 'ripper'
module Ragel
- class Bitmap
+ module Bitmap
# A ruby parser that finds instances of table declarations in a
# ragel-outputted file.
class Replace < Ripper::SexpBuilderPP
+ class << self
+ # Get the required args for a bitmap from a set of numbers
+ def bitmap_args_from(numbers)
+ size = (Math.log2(numbers.max) / 8).ceil
+ strings =
+ size.downto(1).map do |index|
+ shift = (index - 1) * 8
+ numbers.map { |number| (number >> shift) & 0xff }.pack('C*')
+ end
+
+ [class_from(size), strings]
+ end
+
+ private
+
+ def class_from(size)
+ case size
+ when 1 then :Array8
+ when 2 then :Array16
+ when 3 then :Array24
+ else
+ :ArrayGeneric
+ end
+ end
+ end
+
# Represents a table declaration in the source
class Table
attr_reader :source, :start_line, :end_line
def initialize(left, right, lineno)
@source = source_from(left[3][1], right[1].map { |int| int[1].to_i })
@start_line = left[1][1][2][0] - 1
@end_line = lineno
end
+ private
+
def source_from(name, numbers)
- width = Math.log2(numbers.max).ceil
- bitmap =
- numbers.each_with_index.inject(0) do |accum, (number, index)|
- accum | (number << (width * index))
- end
+ clazz, strings = Replace.bitmap_args_from(numbers)
+ arguments = strings.map(&:inspect).join(', ')
- "self.#{name} = ::Ragel::Bitmap.new(#{width}, #{bitmap})"
+ "self.#{name} = ::Ragel::Bitmap::#{clazz}.new(#{arguments})"
end
end
# Represents the source as it changes
class Buffer
@@ -54,29 +79,24 @@
def initialize(*)
super
@tables = []
end
- class << self
- def replace(source)
- buffer = Buffer.new(source)
- tables_from(source).reverse_each { |table| buffer.replace(table) }
- buffer.to_source
+ def each_table(&block)
+ parse
+
+ if error?
+ warn 'Invalid ruby'
+ exit 1
end
- private
+ tables.reverse_each(&block)
+ end
- def tables_from(source)
- replace = new(source)
- replace.parse
-
- if replace.error?
- warn 'Invalid ruby'
- exit 1
- end
-
- replace.tables
- end
+ def self.replace(source)
+ buffer = Buffer.new(source)
+ new(source).each_table { |table| buffer.replace(table) }
+ buffer.to_source
end
private
def on_assign(left, right)