1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
|
require 'rack/mount/strexp/parser'
module Rack::Mount
class Strexp
class << self
# Parses segmented string expression and converts it into a Regexp
#
# Strexp.compile('foo')
# # => %r{\Afoo\Z}
#
# Strexp.compile('foo/:bar', {}, ['/'])
# # => %r{\Afoo/(?<bar>[^/]+)\Z}
#
# Strexp.compile(':foo.example.com')
# # => %r{\A(?<foo>.+)\.example\.com\Z}
#
# Strexp.compile('foo/:bar', {:bar => /[a-z]+/}, ['/'])
# # => %r{\Afoo/(?<bar>[a-z]+)\Z}
#
# Strexp.compile('foo(.:extension)')
# # => %r{\Afoo(\.(?<extension>.+))?\Z}
#
# Strexp.compile('src/*files')
# # => %r{\Asrc/(?<files>.+)\Z}
def compile(str, requirements = {}, separators = [], anchor = true)
return Regexp.compile(str) if str.is_a?(Regexp)
requirements = requirements ? requirements.dup : {}
normalize_requirements!(requirements, separators)
parser = StrexpParser.new
parser.anchor = anchor
parser.requirements = requirements
begin
re = parser.scan_str(str)
rescue Racc::ParseError => e
raise RegexpError, e.message
end
Regexp.compile(re)
end
alias_method :new, :compile
private
def normalize_requirements!(requirements, separators)
requirements.each do |key, value|
if value.is_a?(Regexp)
if regexp_has_modifiers?(value)
requirements[key] = value
else
requirements[key] = value.source
end
else
requirements[key] = Regexp.escape(value)
end
end
requirements.default ||= separators.any? ?
"[^#{separators.join}]+" : '.+'
requirements
end
def regexp_has_modifiers?(regexp)
regexp.options & (Regexp::IGNORECASE | Regexp::EXTENDED) != 0
end
end
end
end
|