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)