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(&block)
def endless_each(&block) 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 ||= Regexp.new("^#{to_re}$").tap do |regexp| regexp.respond_to?(:match?) || def regexp.match?(str); !!match(str) end end end
def to_re
def to_re "(?:#{reify.call}){#{min_rep},#{max_rep unless max_rep == Float::INFINITY}}" end