Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 197 lines (156 sloc) 4.746 kb
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
1 module ActionDispatch
a36ae63 @frodsan :nodoc: Journey because is not part of the public API [ci skip]
frodsan authored
2 module Journey # :nodoc:
3 module Path # :nodoc:
4 class Pattern # :nodoc:
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
5 attr_reader :spec, :requirements, :anchored
6
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
7 def initialize(strexp)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
8 parser = Journey::Parser.new
9
10 @anchored = true
11
12 case strexp
13 when String
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
14 @spec = parser.parse(strexp)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
15 @requirements = {}
16 @separators = "/.?"
17 when Router::Strexp
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
18 @spec = parser.parse(strexp.path)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
19 @requirements = strexp.requirements
20 @separators = strexp.separators.join
21 @anchored = strexp.anchor
22 else
35f38b7 @zires Make ActionDispatch::Journey::Path::Pattern#new raise more meaningful ex...
zires authored
23 raise ArgumentError, "Bad expression: #{strexp}"
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
24 end
25
26 @names = nil
27 @optional_names = nil
28 @required_names = nil
29 @re = nil
30 @offsets = nil
31 end
32
33 def ast
34 @spec.grep(Nodes::Symbol).each do |node|
35 re = @requirements[node.to_sym]
36 node.regexp = re if re
37 end
38
39 @spec.grep(Nodes::Star).each do |node|
40 node = node.left
41 node.regexp = @requirements[node.to_sym] || /(.+)/
42 end
43
44 @spec
45 end
46
47 def names
48 @names ||= spec.grep(Nodes::Symbol).map { |n| n.name }
49 end
50
51 def required_names
52 @required_names ||= names - optional_names
53 end
54
55 def optional_names
56 @optional_names ||= spec.grep(Nodes::Group).map { |group|
57 group.grep(Nodes::Symbol)
58 }.flatten.map { |n| n.name }.uniq
59 end
60
61 class RegexpOffsets < Journey::Visitors::Visitor # :nodoc:
62 attr_reader :offsets
63
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
64 def initialize(matchers)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
65 @matchers = matchers
66 @capture_count = [0]
67 end
68
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
69 def visit(node)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
70 super
71 @capture_count
72 end
73
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
74 def visit_SYMBOL(node)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
75 node = node.to_sym
76
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
77 if @matchers.key?(node)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
78 re = /#{@matchers[node]}|/
79 @capture_count.push((re.match('').length - 1) + (@capture_count.last || 0))
80 else
81 @capture_count << (@capture_count.last || 0)
82 end
83 end
84 end
85
86 class AnchoredRegexp < Journey::Visitors::Visitor # :nodoc:
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
87 def initialize(separator, matchers)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
88 @separator = separator
89 @matchers = matchers
90 @separator_re = "([^#{separator}]+)"
91 super()
92 end
93
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
94 def accept(node)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
95 %r{\A#{visit node}\Z}
96 end
97
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
98 def visit_CAT(node)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
99 [visit(node.left), visit(node.right)].join
100 end
101
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
102 def visit_SYMBOL(node)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
103 node = node.to_sym
104
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
105 return @separator_re unless @matchers.key?(node)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
106
107 re = @matchers[node]
108 "(#{re})"
109 end
110
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
111 def visit_GROUP(node)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
112 "(?:#{visit node.left})?"
113 end
114
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
115 def visit_LITERAL(node)
116 Regexp.escape(node.left)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
117 end
118 alias :visit_DOT :visit_LITERAL
119
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
120 def visit_SLASH(node)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
121 node.left
122 end
123
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
124 def visit_STAR(node)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
125 re = @matchers[node.left.to_sym] || '.+'
126 "(#{re})"
127 end
128 end
129
130 class UnanchoredRegexp < AnchoredRegexp # :nodoc:
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
131 def accept(node)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
132 %r{\A#{visit node}}
133 end
134 end
135
a36ae63 @frodsan :nodoc: Journey because is not part of the public API [ci skip]
frodsan authored
136 class MatchData # :nodoc:
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
137 attr_reader :names
138
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
139 def initialize(names, offsets, match)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
140 @names = names
141 @offsets = offsets
142 @match = match
143 end
144
145 def captures
146 (length - 1).times.map { |i| self[i + 1] }
147 end
148
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
149 def [](x)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
150 idx = @offsets[x - 1] + x
151 @match[idx]
152 end
153
154 def length
155 @offsets.length
156 end
157
158 def post_match
159 @match.post_match
160 end
161
162 def to_s
163 @match.to_s
164 end
165 end
166
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
167 def match(other)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
168 return unless match = to_regexp.match(other)
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
169 MatchData.new(names, offsets, match)
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
170 end
171 alias :=~ :match
172
173 def source
174 to_regexp.source
175 end
176
177 def to_regexp
178 @re ||= regexp_visitor.new(@separators, @requirements).accept spec
179 end
180
181 private
182
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
183 def regexp_visitor
184 @anchored ? AnchoredRegexp : UnanchoredRegexp
185 end
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
186
eb493f5 @frodsan update AD::Journey to follow Rails coding conventions
frodsan authored
187 def offsets
188 return @offsets if @offsets
189
190 viz = RegexpOffsets.new(@requirements)
191 @offsets = viz.accept(spec)
192 end
56fee39 @pixeltrix Integrate Journey into Action Dispatch
pixeltrix authored
193 end
194 end
195 end
196 end
Something went wrong with that request. Please try again.