aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/vendor/rack-mount-0.6.6.pre/rack/mount/strexp.rb
blob: d0d8797008606e8cd59ef5f585a2783fb8accc47 (plain) (blame)
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