rack-mount 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. data/README.rdoc +1 -1
  2. data/lib/rack/mount.rb +0 -2
  3. data/lib/rack/mount/analysis/frequency.rb +10 -3
  4. data/lib/rack/mount/analysis/splitting.rb +79 -62
  5. data/lib/rack/mount/generatable_regexp.rb +48 -45
  6. data/lib/rack/mount/generation/route.rb +10 -5
  7. data/lib/rack/mount/generation/route_set.rb +23 -31
  8. data/lib/rack/mount/prefix.rb +14 -15
  9. data/lib/rack/mount/recognition/code_generation.rb +51 -61
  10. data/lib/rack/mount/recognition/route.rb +7 -22
  11. data/lib/rack/mount/recognition/route_set.rb +40 -16
  12. data/lib/rack/mount/regexp_with_named_groups.rb +33 -7
  13. data/lib/rack/mount/route_set.rb +7 -5
  14. data/lib/rack/mount/strexp.rb +11 -40
  15. data/lib/rack/mount/strexp/parser.rb +158 -0
  16. data/lib/rack/mount/strexp/tokenizer.rb +84 -0
  17. data/lib/rack/mount/utils.rb +26 -163
  18. data/lib/rack/mount/vendor/multimap/multimap.rb +1 -0
  19. data/lib/rack/mount/vendor/reginald/reginald.rb +55 -0
  20. data/lib/rack/mount/vendor/reginald/reginald/alternation.rb +50 -0
  21. data/lib/rack/mount/vendor/reginald/reginald/anchor.rb +20 -0
  22. data/lib/rack/mount/vendor/reginald/reginald/character.rb +53 -0
  23. data/lib/rack/mount/vendor/reginald/reginald/character_class.rb +61 -0
  24. data/lib/rack/mount/vendor/reginald/reginald/expression.rb +75 -0
  25. data/lib/rack/mount/vendor/reginald/reginald/group.rb +61 -0
  26. data/lib/rack/mount/vendor/reginald/reginald/parser.rb +306 -0
  27. data/lib/rack/mount/vendor/reginald/reginald/tokenizer.rb +141 -0
  28. metadata +14 -15
  29. data/lib/rack/mount/const.rb +0 -45
  30. 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
@@ -1,5 +1,10 @@
1
- require 'rack/mount/regexp_with_named_groups'
2
- require 'strscan'
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!(Const::SLASH)
23
- path.sub!(%r{/+\Z}, Const::EMPTY_STRING)
24
- path = Const::SLASH if path == Const::EMPTY_STRING
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
- # Determines whether the regexp must match the entire string.
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
- if regexp.source =~ /\?<([^>]+)>/
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
- capture_index = 0
235
- until scanner.eos?
236
- char = scanner.getch
237
- cur = stack.last
238
-
239
- escaped = cur.last.is_a?(String) && cur.last[-1, 1] == '\\'
240
-
241
- if char == '\\' && scanner.peek(1) == 'Z'
242
- scanner.pos += 1
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
- stack.pop
128
+ expression
129
+ rescue Racc::ParseError
130
+ []
268
131
  end
269
- module_function :extract_regexp_parts
132
+ module_function :parse_regexp
270
133
  end
271
134
  end