class Pyrosoma class Pattern def initialize(source) @source = source @rx = Regexp.new compile end def compile @fields = {} field_count = 1 r = '\A' @source.scan(/((?:\*\*|\*|%|\$|\{.*?\})(?::(\w+))?|:\w+|.)/m) { |token, name| r << case token when /^\*\*/ '(.*?)' when /^\*/ '([^/]*?)' when /^%/ '(\d+)' when /^\$/ '([A-Fa-f0-9]+)' when /^\{(.*)\}/ "(" + $1.split(',').map { |x| Regexp.quote x }.join("|") + ")" when /^:/ @fields[$'.downcase.intern] = field_count '([^/]*?)' else field_count -= 1 # oops, no field Regexp.quote(token) end @fields[name.downcase.intern] = field_count if name field_count += 1 } r << '\z' end def match(uri) if uri =~ @rx matches = {} $~.captures.each_with_index { |v, k| matches[k+1] = v } @fields.each { |k, v| matches[k] = matches[v] } matches else nil end end alias =~ match def generality [@fields.size, @source.index("**") || 0, @rx.source.index('(') || 0, @rx.source.size] end end end