class Regexp::MatchLength
def self.of(obj)
def self.of(obj) exp = obj.is_a?(Regexp::Expression::Base) ? obj : Regexp::Parser.parse(obj) exp.match_length end
def each(opts = {})
def each(opts = {}) return enum_for(__method__, opts) unless block_given? limit = opts[:limit] || 1000 yielded = 0 (min..max).each do |num| next unless include?(num) yield(num) break if (yielded += 1) >= limit end end
def endless_each
def endless_each return enum_for(__method__) unless block_given? (min..max).each { |num| yield(num) if include?(num) } end
def fixed?
def fixed? min == max end
def include?(length)
def include?(length) test_regexp.match?('X' * length) end
def initialize(exp, opts = {})
def initialize(exp, opts = {}) self.exp_class = exp.class self.min_rep = exp.repetitions.min self.max_rep = exp.repetitions.max if (base = opts[:base]) self.base_min = base self.base_max = base self.reify = ->{ '.' * base } else self.base_min = opts.fetch(:base_min) self.base_max = opts.fetch(:base_max) self.reify = opts.fetch(:reify) end end
def inspect
def inspect type = exp_class.name.sub('Regexp::Expression::', '') "#<#{self.class}<#{type}> min=#{min} max=#{max}>" end
def max
def max max_rep * base_max end
def min
def min min_rep * base_min end
def minmax
def minmax [min, max] end
def test_regexp
def test_regexp @test_regexp ||= /^#{to_re}$/ end
def test_regexp
def test_regexp @test_regexp ||= /^#{to_re}$/.tap { |r| def r.match?(s); !!match(s) end } end
def to_re
def to_re /(?:#{reify.call}){#{min_rep},#{max_rep unless max_rep == Float::INFINITY}}/ end