rack-mount 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +1 -1
- data/lib/rack/mount.rb +0 -2
- data/lib/rack/mount/analysis/frequency.rb +10 -3
- data/lib/rack/mount/analysis/splitting.rb +79 -62
- data/lib/rack/mount/generatable_regexp.rb +48 -45
- data/lib/rack/mount/generation/route.rb +10 -5
- data/lib/rack/mount/generation/route_set.rb +23 -31
- data/lib/rack/mount/prefix.rb +14 -15
- data/lib/rack/mount/recognition/code_generation.rb +51 -61
- data/lib/rack/mount/recognition/route.rb +7 -22
- data/lib/rack/mount/recognition/route_set.rb +40 -16
- data/lib/rack/mount/regexp_with_named_groups.rb +33 -7
- data/lib/rack/mount/route_set.rb +7 -5
- data/lib/rack/mount/strexp.rb +11 -40
- data/lib/rack/mount/strexp/parser.rb +158 -0
- data/lib/rack/mount/strexp/tokenizer.rb +84 -0
- data/lib/rack/mount/utils.rb +26 -163
- data/lib/rack/mount/vendor/multimap/multimap.rb +1 -0
- data/lib/rack/mount/vendor/reginald/reginald.rb +55 -0
- data/lib/rack/mount/vendor/reginald/reginald/alternation.rb +50 -0
- data/lib/rack/mount/vendor/reginald/reginald/anchor.rb +20 -0
- data/lib/rack/mount/vendor/reginald/reginald/character.rb +53 -0
- data/lib/rack/mount/vendor/reginald/reginald/character_class.rb +61 -0
- data/lib/rack/mount/vendor/reginald/reginald/expression.rb +75 -0
- data/lib/rack/mount/vendor/reginald/reginald/group.rb +61 -0
- data/lib/rack/mount/vendor/reginald/reginald/parser.rb +306 -0
- data/lib/rack/mount/vendor/reginald/reginald/tokenizer.rb +141 -0
- metadata +14 -15
- data/lib/rack/mount/const.rb +0 -45
- data/lib/rack/mount/meta_method.rb +0 -104
@@ -0,0 +1,158 @@
|
|
1
|
+
#
|
2
|
+
# DO NOT MODIFY!!!!
|
3
|
+
# This file is automatically generated by Racc 1.4.6
|
4
|
+
# from Racc grammer file "".
|
5
|
+
#
|
6
|
+
|
7
|
+
require 'racc/parser.rb'
|
8
|
+
|
9
|
+
require 'rack/mount/strexp/tokenizer'
|
10
|
+
|
11
|
+
module Rack
|
12
|
+
module Mount
|
13
|
+
class StrexpParser < Racc::Parser
|
14
|
+
|
15
|
+
|
16
|
+
if RegexpWithNamedGroups.supports_named_captures?
|
17
|
+
REGEXP_NAMED_CAPTURE = '(?<%s>%s)'.freeze
|
18
|
+
else
|
19
|
+
REGEXP_NAMED_CAPTURE = '(?:<%s>%s)'.freeze
|
20
|
+
end
|
21
|
+
|
22
|
+
attr_accessor :requirements
|
23
|
+
##### State transition tables begin ###
|
24
|
+
|
25
|
+
racc_action_table = [
|
26
|
+
4, 5, 6, 11, 7, 4, 5, 6, 12, 7,
|
27
|
+
4, 5, 6, 8, 7, 4, 5, 6, nil, 7 ]
|
28
|
+
|
29
|
+
racc_action_check = [
|
30
|
+
0, 0, 0, 8, 0, 10, 10, 10, 10, 10,
|
31
|
+
2, 2, 2, 1, 2, 6, 6, 6, nil, 6 ]
|
32
|
+
|
33
|
+
racc_action_pointer = [
|
34
|
+
-2, 13, 8, nil, nil, nil, 13, nil, 3, nil,
|
35
|
+
3, nil, nil ]
|
36
|
+
|
37
|
+
racc_action_default = [
|
38
|
+
-8, -8, -1, -3, -4, -5, -8, -7, -8, -2,
|
39
|
+
-8, 13, -6 ]
|
40
|
+
|
41
|
+
racc_goto_table = [
|
42
|
+
9, 2, 1, nil, nil, nil, nil, 10, 9 ]
|
43
|
+
|
44
|
+
racc_goto_check = [
|
45
|
+
3, 2, 1, nil, nil, nil, nil, 2, 3 ]
|
46
|
+
|
47
|
+
racc_goto_pointer = [
|
48
|
+
nil, 2, 1, -2 ]
|
49
|
+
|
50
|
+
racc_goto_default = [
|
51
|
+
nil, nil, nil, 3 ]
|
52
|
+
|
53
|
+
racc_reduce_table = [
|
54
|
+
0, 0, :racc_error,
|
55
|
+
1, 8, :_reduce_1,
|
56
|
+
2, 9, :_reduce_2,
|
57
|
+
1, 9, :_reduce_none,
|
58
|
+
1, 10, :_reduce_4,
|
59
|
+
1, 10, :_reduce_5,
|
60
|
+
3, 10, :_reduce_6,
|
61
|
+
1, 10, :_reduce_7 ]
|
62
|
+
|
63
|
+
racc_reduce_n = 8
|
64
|
+
|
65
|
+
racc_shift_n = 13
|
66
|
+
|
67
|
+
racc_token_table = {
|
68
|
+
false => 0,
|
69
|
+
:error => 1,
|
70
|
+
:PARAM => 2,
|
71
|
+
:GLOB => 3,
|
72
|
+
:LPAREN => 4,
|
73
|
+
:RPAREN => 5,
|
74
|
+
:CHAR => 6 }
|
75
|
+
|
76
|
+
racc_nt_base = 7
|
77
|
+
|
78
|
+
racc_use_result_var = true
|
79
|
+
|
80
|
+
Racc_arg = [
|
81
|
+
racc_action_table,
|
82
|
+
racc_action_check,
|
83
|
+
racc_action_default,
|
84
|
+
racc_action_pointer,
|
85
|
+
racc_goto_table,
|
86
|
+
racc_goto_check,
|
87
|
+
racc_goto_default,
|
88
|
+
racc_goto_pointer,
|
89
|
+
racc_nt_base,
|
90
|
+
racc_reduce_table,
|
91
|
+
racc_token_table,
|
92
|
+
racc_shift_n,
|
93
|
+
racc_reduce_n,
|
94
|
+
racc_use_result_var ]
|
95
|
+
|
96
|
+
Racc_token_to_s_table = [
|
97
|
+
"$end",
|
98
|
+
"error",
|
99
|
+
"PARAM",
|
100
|
+
"GLOB",
|
101
|
+
"LPAREN",
|
102
|
+
"RPAREN",
|
103
|
+
"CHAR",
|
104
|
+
"$start",
|
105
|
+
"target",
|
106
|
+
"expr",
|
107
|
+
"token" ]
|
108
|
+
|
109
|
+
Racc_debug_parser = false
|
110
|
+
|
111
|
+
##### State transition tables end #####
|
112
|
+
|
113
|
+
# reduce 0 omitted
|
114
|
+
|
115
|
+
def _reduce_1(val, _values, result)
|
116
|
+
result = "\\A#{val.join}\\Z"
|
117
|
+
result
|
118
|
+
end
|
119
|
+
|
120
|
+
def _reduce_2(val, _values, result)
|
121
|
+
result = val.join
|
122
|
+
result
|
123
|
+
end
|
124
|
+
|
125
|
+
# reduce 3 omitted
|
126
|
+
|
127
|
+
def _reduce_4(val, _values, result)
|
128
|
+
name = val[0].to_sym
|
129
|
+
requirement = requirements[name]
|
130
|
+
result = REGEXP_NAMED_CAPTURE % [name, requirement]
|
131
|
+
|
132
|
+
result
|
133
|
+
end
|
134
|
+
|
135
|
+
def _reduce_5(val, _values, result)
|
136
|
+
name = val[0].to_sym
|
137
|
+
result = REGEXP_NAMED_CAPTURE % [name, '.+']
|
138
|
+
|
139
|
+
result
|
140
|
+
end
|
141
|
+
|
142
|
+
def _reduce_6(val, _values, result)
|
143
|
+
result = "(?:#{val[1]})?"
|
144
|
+
result
|
145
|
+
end
|
146
|
+
|
147
|
+
def _reduce_7(val, _values, result)
|
148
|
+
result = Regexp.escape(val[0])
|
149
|
+
result
|
150
|
+
end
|
151
|
+
|
152
|
+
def _reduce_none(val, _values, result)
|
153
|
+
val[0]
|
154
|
+
end
|
155
|
+
|
156
|
+
end # class StrexpParser
|
157
|
+
end # module Mount
|
158
|
+
end # module Rack
|
@@ -0,0 +1,84 @@
|
|
1
|
+
#--
|
2
|
+
# DO NOT MODIFY!!!!
|
3
|
+
# This file is automatically generated by rex 1.0.4
|
4
|
+
# from lexical definition file "lib/rack/mount/strexp/tokenizer.rex".
|
5
|
+
#++
|
6
|
+
|
7
|
+
require 'racc/parser'
|
8
|
+
module Rack::Mount
|
9
|
+
class StrexpParser < Racc::Parser
|
10
|
+
require 'strscan'
|
11
|
+
|
12
|
+
class ScanError < StandardError ; end
|
13
|
+
|
14
|
+
attr_reader :lineno
|
15
|
+
attr_reader :filename
|
16
|
+
attr_accessor :state
|
17
|
+
|
18
|
+
def scan_setup(str)
|
19
|
+
@ss = StringScanner.new(str)
|
20
|
+
@lineno = 1
|
21
|
+
@state = nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def action(&block)
|
25
|
+
yield
|
26
|
+
end
|
27
|
+
|
28
|
+
def scan_str(str)
|
29
|
+
scan_setup(str)
|
30
|
+
do_parse
|
31
|
+
end
|
32
|
+
|
33
|
+
def load_file( filename )
|
34
|
+
@filename = filename
|
35
|
+
open(filename, "r") do |f|
|
36
|
+
scan_setup(f.read)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def scan_file( filename )
|
41
|
+
load_file(filename)
|
42
|
+
do_parse
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
def next_token
|
47
|
+
return if @ss.eos?
|
48
|
+
|
49
|
+
text = @ss.peek(1)
|
50
|
+
@lineno += 1 if text == "\n"
|
51
|
+
token = case @state
|
52
|
+
when nil
|
53
|
+
case
|
54
|
+
when (text = @ss.scan(/\\(\(|\)|:|\*)/))
|
55
|
+
action { [:CHAR, @ss[1]] }
|
56
|
+
|
57
|
+
when (text = @ss.scan(/\:([a-zA-Z_]\w*)/))
|
58
|
+
action { [:PARAM, @ss[1]] }
|
59
|
+
|
60
|
+
when (text = @ss.scan(/\*([a-zA-Z_]\w*)/))
|
61
|
+
action { [:GLOB, @ss[1]] }
|
62
|
+
|
63
|
+
when (text = @ss.scan(/\(/))
|
64
|
+
action { [:LPAREN, text] }
|
65
|
+
|
66
|
+
when (text = @ss.scan(/\)/))
|
67
|
+
action { [:RPAREN, text] }
|
68
|
+
|
69
|
+
when (text = @ss.scan(/./))
|
70
|
+
action { [:CHAR, text] }
|
71
|
+
|
72
|
+
else
|
73
|
+
text = @ss.string[@ss.pos .. -1]
|
74
|
+
raise ScanError, "can not match: '" + text + "'"
|
75
|
+
end # if
|
76
|
+
|
77
|
+
else
|
78
|
+
raise ScanError, "undefined state: '" + state.to_s + "'"
|
79
|
+
end # case state
|
80
|
+
token
|
81
|
+
end # def next_token
|
82
|
+
|
83
|
+
end # class
|
84
|
+
end # module
|
data/lib/rack/mount/utils.rb
CHANGED
@@ -1,5 +1,10 @@
|
|
1
|
-
|
2
|
-
require '
|
1
|
+
begin
|
2
|
+
require 'reginald'
|
3
|
+
rescue LoadError
|
4
|
+
$: << File.expand_path(File.join(File.dirname(__FILE__), 'vendor/reginald'))
|
5
|
+
require 'reginald'
|
6
|
+
end
|
7
|
+
|
3
8
|
require 'uri'
|
4
9
|
|
5
10
|
module Rack::Mount
|
@@ -19,9 +24,9 @@ module Rack::Mount
|
|
19
24
|
# normalize_path("") # => "/"
|
20
25
|
def normalize_path(path)
|
21
26
|
path = "/#{path}"
|
22
|
-
path.squeeze!(
|
23
|
-
path.sub!(%r{/+\Z},
|
24
|
-
path =
|
27
|
+
path.squeeze!('/')
|
28
|
+
path.sub!(%r{/+\Z}, '')
|
29
|
+
path = '/' if path == ''
|
25
30
|
path
|
26
31
|
end
|
27
32
|
module_function :normalize_path
|
@@ -99,173 +104,31 @@ module Rack::Mount
|
|
99
104
|
end
|
100
105
|
module_function :normalize_extended_expression
|
101
106
|
|
102
|
-
|
103
|
-
#
|
104
|
-
# regexp_anchored?(/^foo$/) # => true
|
105
|
-
# regexp_anchored?(/foo/) # => false
|
106
|
-
# regexp_anchored?(/^foo/) # => false
|
107
|
-
# regexp_anchored?(/foo$/) # => false
|
108
|
-
def regexp_anchored?(regexp)
|
109
|
-
regexp.source =~ /\A(\\A|\^).*(\\Z|\$)\Z/ ? true : false
|
110
|
-
end
|
111
|
-
module_function :regexp_anchored?
|
112
|
-
|
113
|
-
# Returns static string source of Regexp if it only includes static
|
114
|
-
# characters and no metacharacters. Otherwise the original Regexp is
|
115
|
-
# returned.
|
116
|
-
#
|
117
|
-
# extract_static_regexp(/^foo$/) # => "foo"
|
118
|
-
# extract_static_regexp(/^foo\.bar$/) # => "foo.bar"
|
119
|
-
# extract_static_regexp(/^foo|bar$/) # => /^foo|bar$/
|
120
|
-
def extract_static_regexp(regexp, options = nil)
|
121
|
-
if regexp.is_a?(String)
|
122
|
-
regexp = Regexp.compile("\\A#{regexp}\\Z", options)
|
123
|
-
end
|
124
|
-
|
125
|
-
# Just return if regexp is case-insensitive
|
126
|
-
return regexp if regexp.casefold?
|
127
|
-
|
128
|
-
source = regexp.source
|
129
|
-
if regexp_anchored?(regexp)
|
130
|
-
source.sub!(/^(\\A|\^)(.*)(\\Z|\$)$/, '\2')
|
131
|
-
unescaped_source = source.gsub(/\\/, Const::EMPTY_STRING)
|
132
|
-
if source == Regexp.escape(unescaped_source) &&
|
133
|
-
Regexp.compile("\\A(#{source})\\Z") =~ unescaped_source
|
134
|
-
return unescaped_source
|
135
|
-
end
|
136
|
-
end
|
137
|
-
regexp
|
138
|
-
end
|
139
|
-
module_function :extract_static_regexp
|
140
|
-
|
141
|
-
if Const::SUPPORTS_NAMED_CAPTURES
|
142
|
-
NAMED_CAPTURE_REGEXP = /\?<([^>]+)>/
|
143
|
-
else
|
144
|
-
NAMED_CAPTURE_REGEXP = /\?:<([^>]+)>/
|
145
|
-
end
|
146
|
-
|
147
|
-
# Strips shim named capture syntax and returns a clean Regexp and
|
148
|
-
# an ordered array of the named captures.
|
149
|
-
#
|
150
|
-
# extract_named_captures(/[a-z]+/) # => /[a-z]+/, []
|
151
|
-
# extract_named_captures(/(?:<foo>[a-z]+)/) # => /([a-z]+)/, ['foo']
|
152
|
-
# extract_named_captures(/([a-z]+)(?:<foo>[a-z]+)/)
|
153
|
-
# # => /([a-z]+)([a-z]+)/, [nil, 'foo']
|
154
|
-
def extract_named_captures(regexp)
|
155
|
-
options = regexp.is_a?(Regexp) ? regexp.options : nil
|
156
|
-
source = Regexp.compile(regexp).source
|
157
|
-
names, scanner = [], StringScanner.new(source)
|
158
|
-
|
159
|
-
while scanner.skip_until(/\(/)
|
160
|
-
if scanner.scan(NAMED_CAPTURE_REGEXP)
|
161
|
-
names << scanner[1]
|
162
|
-
else
|
163
|
-
names << nil
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
names = [] unless names.any?
|
168
|
-
source.gsub!(NAMED_CAPTURE_REGEXP, Const::EMPTY_STRING)
|
169
|
-
return Regexp.compile(source, options), names
|
170
|
-
end
|
171
|
-
module_function :extract_named_captures
|
172
|
-
|
173
|
-
class Capture < Array #:nodoc:
|
174
|
-
attr_reader :name, :optional
|
175
|
-
alias_method :optional?, :optional
|
176
|
-
|
177
|
-
def initialize(*args)
|
178
|
-
options = args.last.is_a?(Hash) ? args.pop : {}
|
179
|
-
|
180
|
-
@name = options.delete(:name)
|
181
|
-
@name = @name.to_s if @name
|
182
|
-
|
183
|
-
@optional = options.delete(:optional) || false
|
184
|
-
|
185
|
-
super(args)
|
186
|
-
end
|
187
|
-
|
188
|
-
def ==(obj)
|
189
|
-
obj.is_a?(Capture) && @name == obj.name && @optional == obj.optional && super
|
190
|
-
end
|
191
|
-
|
192
|
-
def optionalize!
|
193
|
-
@optional = true
|
194
|
-
self
|
195
|
-
end
|
196
|
-
|
197
|
-
def named?
|
198
|
-
name && name != Const::EMPTY_STRING
|
199
|
-
end
|
200
|
-
|
201
|
-
def to_s
|
202
|
-
source = "(#{join})"
|
203
|
-
source << '?' if optional?
|
204
|
-
source
|
205
|
-
end
|
206
|
-
|
207
|
-
def first_part
|
208
|
-
first.is_a?(Capture) ? first.first_part : first
|
209
|
-
end
|
210
|
-
|
211
|
-
def last_part
|
212
|
-
last.is_a?(Capture) ? last.last_part : last
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
def extract_regexp_parts(regexp) #:nodoc:
|
107
|
+
def parse_regexp(regexp)
|
217
108
|
unless regexp.is_a?(RegexpWithNamedGroups)
|
218
109
|
regexp = RegexpWithNamedGroups.new(regexp)
|
219
110
|
end
|
220
111
|
|
221
|
-
|
222
|
-
regexp, names = extract_named_captures(regexp)
|
223
|
-
else
|
224
|
-
names = regexp.names
|
225
|
-
end
|
226
|
-
source = regexp.source
|
227
|
-
|
228
|
-
source =~ /^(\\A|\^)/ ? source.gsub!(/^(\\A|\^)/, Const::EMPTY_STRING) :
|
229
|
-
raise(ArgumentError, "#{source} needs to match the start of the string")
|
230
|
-
|
231
|
-
scanner = StringScanner.new(source)
|
232
|
-
stack = [[]]
|
112
|
+
expression = Reginald.parse(regexp)
|
233
113
|
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
cur.push(Const::NULL)
|
244
|
-
elsif escaped
|
245
|
-
cur.push('') unless cur.last.is_a?(String)
|
246
|
-
cur.last << char
|
247
|
-
elsif char == '('
|
248
|
-
name = names[capture_index]
|
249
|
-
capture = Capture.new(:name => name)
|
250
|
-
capture_index += 1
|
251
|
-
cur.push(capture)
|
252
|
-
stack.push(capture)
|
253
|
-
elsif char == ')'
|
254
|
-
capture = stack.pop
|
255
|
-
if scanner.peek(1) == '?'
|
256
|
-
scanner.pos += 1
|
257
|
-
capture.optionalize!
|
114
|
+
unless RegexpWithNamedGroups.supports_named_captures?
|
115
|
+
tag_captures = Proc.new do |group|
|
116
|
+
group.each do |child|
|
117
|
+
if child.is_a?(Reginald::Group)
|
118
|
+
child.name = regexp.names[child.index] if child.index
|
119
|
+
tag_captures.call(child)
|
120
|
+
elsif child.is_a?(Reginald::Expression)
|
121
|
+
tag_captures.call(child)
|
122
|
+
end
|
258
123
|
end
|
259
|
-
elsif char == '$'
|
260
|
-
cur.push(Const::NULL)
|
261
|
-
else
|
262
|
-
cur.push('') unless cur.last.is_a?(String)
|
263
|
-
cur.last << char
|
264
124
|
end
|
125
|
+
tag_captures.call(expression)
|
265
126
|
end
|
266
127
|
|
267
|
-
|
128
|
+
expression
|
129
|
+
rescue Racc::ParseError
|
130
|
+
[]
|
268
131
|
end
|
269
|
-
module_function :
|
132
|
+
module_function :parse_regexp
|
270
133
|
end
|
271
134
|
end
|