abnf-parsing 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. checksums.yaml +5 -13
  2. data/LICENSE +17 -0
  3. metadata +14 -15
  4. data/Rakefile +0 -40
  5. data/lib/abnf.rb +0 -264
  6. data/test/basics.rb +0 -123
  7. data/test/url.rb +0 -206
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- Y2Y2ZTliMTljZGZlYTA3YTJiOWUwMjJkM2FiOWFjM2NmYTFhNDY2OQ==
5
- data.tar.gz: !binary |-
6
- NjM4MzZjYjlkOTNkMWE2MWJjMTIxMDE4ODM3MmFjMTAyNzFhNGZkNA==
2
+ SHA1:
3
+ metadata.gz: 50439e86902c1e02472ce2cea0fa57944c82f452
4
+ data.tar.gz: 52f768ac2bba47dcef60a29757d0f5416382b8f8
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- NTJhMWUxZmI4YzBmNGI4MWQzZjc3NjhlODI3NDVjOWE3YmM2NTA3NDBkYzdh
10
- OWQ5MDQzNzI1ZDY3ZjQ1ZTcyNGUyZjYzN2ZhOWU5N2U1ZTFiYmNjYmU4ZTE3
11
- NjQzODdhZjQ2ZmJhOTk4NzJmZTdlOWViNjRhMjc4OWY2OTgxOTQ=
12
- data.tar.gz: !binary |-
13
- NzAzMzg5MjBlMzk4ODIwYmFlN2JkYzJkMDI5ZTAyYTMxYWNlOWRhODg2MzUy
14
- MjQwMjZjYzEyNTI5OTA2MzYyZGVkZjg0NGFjMzA1MzA5YTFmZDUyMTA4MjIx
15
- MTZmY2YwMDQ5ZjYwODgwNGJlNDc1MWNiMTA5MzhlMTkzNjYzYjE=
6
+ metadata.gz: b6ea44110b9ef1bd31bcdbc380d2fe3ca1e563e80934c8ff7dc3912cd467f3fec149d57ad5c4bd7e185479dfff8109d82bff4a10cd73125e0f537277bb8aa8af
7
+ data.tar.gz: dbfc58d6fc0c3532de8461e5511e061f933184099ec260e563f6130762f9b3ad0e3d0dcf4d7845d8e25e223fc79f6c23c00ec87335d98b90374ee552cd332848
data/LICENSE ADDED
@@ -0,0 +1,17 @@
1
+ Permission is hereby granted, free of charge, to any person obtaining a copy
2
+ of this software and associated documentation files (the "Software"), to deal
3
+ in the Software without restriction, including without limitation the rights
4
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5
+ copies of the Software, and to permit persons to whom the Software is
6
+ furnished to do so, subject to the following conditions:
7
+
8
+ The above copyright notice and this permission notice shall be included in
9
+ all copies or substantial portions of the Software.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
17
+ THE SOFTWARE.
metadata CHANGED
@@ -1,33 +1,32 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: abnf-parsing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
- - Rob Day
8
7
  - Ryan Tecco
8
+ - Rob Day
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-09 00:00:00.000000000 Z
12
+ date: 2014-06-15 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: A Ruby library for implementing parsers specified with Augmented Backus
15
15
  Naur Form (ABNF).
16
- email: ruby-abnf@rkd.me.uk
16
+ email: rkd@rkd.me.uk
17
17
  executables: []
18
18
  extensions: []
19
19
  extra_rdoc_files:
20
20
  - README
21
21
  - TODO
22
+ - LICENSE
22
23
  files:
23
24
  - README
24
- - Rakefile
25
25
  - TODO
26
- - lib/abnf.rb
27
- - test/basics.rb
28
- - test/url.rb
29
- homepage: https://github.com/rkday/ruby-abnf
30
- licenses: []
26
+ - LICENSE
27
+ homepage:
28
+ licenses:
29
+ - MIT
31
30
  metadata: {}
32
31
  post_install_message:
33
32
  rdoc_options: []
@@ -35,18 +34,18 @@ require_paths:
35
34
  - lib
36
35
  required_ruby_version: !ruby/object:Gem::Requirement
37
36
  requirements:
38
- - - ! '>='
37
+ - - '>='
39
38
  - !ruby/object:Gem::Version
40
39
  version: '0'
41
40
  required_rubygems_version: !ruby/object:Gem::Requirement
42
41
  requirements:
43
- - - ! '>='
42
+ - - '>='
44
43
  - !ruby/object:Gem::Version
45
44
  version: '0'
46
45
  requirements: []
47
46
  rubyforge_project:
48
- rubygems_version: 2.2.2
47
+ rubygems_version: 2.1.11
49
48
  signing_key:
50
- specification_version: 4
51
- summary: ABNF parsing in Ruby
49
+ specification_version: 2
50
+ summary: A library for implementing ABNF parsers.
52
51
  test_files: []
data/Rakefile DELETED
@@ -1,40 +0,0 @@
1
-
2
-
3
-
4
-
5
- require 'rubygems'
6
- require 'rake'
7
- require 'rake/testtask'
8
- require 'rubygems/package_task'
9
-
10
- Rake::TestTask.new do |t|
11
- t.libs << "test"
12
- t.test_files = FileList['test/*.rb']
13
- t.verbose = true
14
- end
15
-
16
- GEM = "abnf-parsing"
17
-
18
- spec = Gem::Specification.new do |s|
19
- s.name = GEM
20
- s.version = "0.2.0"
21
- s.platform = Gem::Platform::RUBY
22
- s.has_rdoc = true
23
- s.extra_rdoc_files = ["README", "TODO"]
24
- s.summary = "ABNF parsing in Ruby"
25
- s.description = "A Ruby library for implementing parsers specified with Augmented Backus Naur Form (ABNF)."
26
- s.authors = ["Rob Day", "Ryan Tecco"]
27
- s.homepage = "https://github.com/rkday/ruby-abnf"
28
- s.email = "ruby-abnf@rkd.me.uk"
29
- s.require_path = "lib"
30
- s.files = %w{README Rakefile TODO} + Dir.glob("{lib,test}/*")
31
- end
32
-
33
- Gem::PackageTask.new(spec) do |pkg|
34
-
35
- end
36
-
37
- desc "Create the gemspec file."
38
- task :gemspec do
39
- File.open("#{GEM}.gemspec", "w"){|f| f.puts spec.to_ruby}
40
- end
@@ -1,264 +0,0 @@
1
-
2
- # ABNF (RFC 2234) parser objects.
3
-
4
- module ABNF
5
- class ::Range
6
- def until_end # &blk
7
- self.last.times{|i| yield i}
8
- end
9
- end
10
-
11
- class RangeWithInfiniteUpperBound
12
- def initialize(first)
13
- @first = first
14
- end
15
-
16
- def first
17
- @first
18
- end
19
-
20
- def until_end # &blk
21
- i = 0
22
-
23
- while true
24
- yield i
25
- i += 1
26
- end
27
- end
28
- end
29
-
30
- class Stream
31
- attr_reader :pos
32
-
33
- def initialize(s, full = nil, pos = 0)
34
- @s = s
35
- @full = full.nil? ? s : full
36
- @pos = pos
37
- end
38
-
39
- def first
40
- @s[0].ord if @s[0]
41
- end
42
-
43
- def rest
44
- Stream.new(@s[1..-1], @full, @pos + 1)
45
- end
46
-
47
- def clip(start)
48
- @full[start...@pos]
49
- end
50
- end
51
-
52
- #
53
- # Helper Classes
54
-
55
- class Satisfies
56
-
57
- # Takes a stream, returns a stream or failure.
58
- def match(s)
59
- s.rest if predicate(s.first)
60
- end
61
- end
62
-
63
- class Range < Satisfies
64
- def initialize(r)
65
- @r = r
66
- end
67
-
68
- def predicate(c)
69
- @r.member?(c)
70
- end
71
- end
72
-
73
- #
74
- # Core Operators
75
-
76
- # Remember to place the longest matches first!
77
- class Alternate
78
- def initialize(*choices, &blk)
79
- @choices = choices
80
- @blk = blk
81
- end
82
-
83
- def set_block(&blk)
84
- @blk = blk
85
- return self
86
- end
87
-
88
- def match(strm)
89
- start = strm.pos
90
-
91
- @choices.each {
92
- |c|
93
-
94
- n_strm = c.match(strm);
95
-
96
- if n_strm
97
- @blk.call(n_strm.clip(start)) unless @blk.nil?
98
-
99
- return n_strm
100
- end
101
- }
102
-
103
- return nil
104
- end
105
- end
106
-
107
- class AlternateChars < Alternate
108
- def initialize(string, &blk)
109
- @choices = string.each_char.map { |c| Char.new(c) }
110
- @blk = blk
111
- end
112
- end
113
-
114
- class Concat
115
- def initialize(*choices, &blk)
116
- @choices = choices
117
- @blk = blk
118
- end
119
-
120
- def set_block(&blk)
121
- @blk = blk
122
- return self
123
- end
124
-
125
- def match(strm)
126
- c_strm = strm
127
- start = c_strm.pos
128
-
129
- @choices.each {
130
- |c|
131
-
132
- c_strm = c.match(c_strm)
133
-
134
- return nil if c_strm.nil?
135
- }
136
-
137
- @blk.call(c_strm.clip(start)) unless @blk.nil?
138
-
139
- return c_strm
140
- end
141
- end
142
-
143
- class Literal < Concat
144
- def initialize(string, &blk)
145
- @choices = string.each_char.map { |c| Char.new(c) }
146
- @blk = blk
147
- end
148
- end
149
-
150
- class Repetition
151
- # Spec: range (between), integer (exact), [:at_most, N], [:at_least, N], :any (zero or more)
152
- def initialize(spec, what, &blk)
153
- @spec = spec
154
- @what = what
155
- @blk = blk
156
- end
157
-
158
- def set_block(&blk)
159
- @blk = blk
160
- return self
161
- end
162
-
163
- def match(strm)
164
- c_strm = strm
165
- start = strm.pos
166
-
167
- r = \
168
- case @spec
169
- when Array # :at_least, :at_most
170
- option, i = @spec
171
-
172
- if option == :at_most
173
- (0..i)
174
- elsif option == :at_least
175
- RangeWithInfiniteUpperBound.new(i)
176
- end
177
- when Integer # Exact
178
- @spec..@spec
179
- when ::Range # Between
180
- @spec
181
- when Symbol # Any (zero or more)
182
- RangeWithInfiniteUpperBound.new(0)
183
- end
184
-
185
- r.until_end {
186
- |i|
187
-
188
- tried = @what.match(c_strm)
189
-
190
- if tried.nil?
191
- if i < r.first
192
- return nil
193
- else
194
- break
195
- end
196
- else
197
- c_strm = tried
198
- end
199
- }
200
-
201
- @blk.call(c_strm.clip(start)) unless @blk.nil?
202
-
203
- c_strm
204
- end
205
- end
206
-
207
- class Optional < Repetition
208
- def initialize(what)
209
- super([:at_most, 1], what)
210
- end
211
- end
212
-
213
- class OptionalConcat < Optional
214
- def initialize(*what)
215
- super(Concat.new(*what))
216
- end
217
- end
218
-
219
- #
220
- # Core Rules
221
- #
222
- # I tried to preserve the RFC names where possible.
223
-
224
- class Char < Satisfies
225
- def initialize(c)
226
- @char = c.ord
227
- end
228
-
229
- def predicate(c)
230
- c == @char
231
- end
232
- end
233
-
234
- class Alpha < Alternate; def initialize; super(Range.new(0x41..0x5A), Range.new(0x61..0x7A)) end end
235
- class AsciiChar < Range; def initialize; super(0x1..0x7F) end end # char
236
- class Bit < Alternate; def initialize; super(Char.new(?0), Char.new(?1)) end end
237
- class CR < Char; def initialize; super(0x0D) end end # carriage return
238
- class LF < Char; def initialize; super(0x0A) end end # line feed
239
- class CRLF < Concat; def initialize; super(CR.new, LF.new) end end # Internet standard newline
240
- class Ctl < Alternate; def initialize; super(Range.new(0..0x1F), Char.new(0x7F)) end end # control characters
241
- class Digit < Range; def initialize; super(0x30..0x39) end end
242
- class DQuote < Char; def initialize; super(0x22) end end # double quote
243
- class HTab < Char; def initialize; super(0x9) end end # horizontal tab
244
- class SP < Char; def initialize; super(0x20) end end # space
245
- class Octet < Range; def initialize; super(0..255) end end # any 8-bit data value
246
- class VChar < Range; def initialize; super(0x21..0x7E) end end # visible (printing) characters
247
- class WSP < Alternate; def initialize; super(SP.new, HTab.new) end end # whitespace
248
-
249
- class HexDigit < Alternate
250
- def initialize
251
- super(Digit.new, Range.new(0x41..0x46), Range.new(0x61..0x66))
252
- end
253
- end
254
-
255
- class LWSP < Repetition # Linear white space (past newline)
256
- def initialize
257
- super(:any, Alternate.new(WSP.new, Concat.new(CRLF.new, WSP.new)))
258
- end
259
- end
260
-
261
- def parse(parser, str)
262
- parser.match(Stream.new(str))
263
- end
264
- end
@@ -1,123 +0,0 @@
1
- $: << File.join(File.dirname(__FILE__), "../lib")
2
-
3
- require 'test/unit'
4
- require 'abnf'
5
-
6
- class ABNFTest < Test::Unit::TestCase
7
- include ABNF
8
-
9
- def assert_blank(s)
10
- assert s.nil? || (s.class == String && s.empty?)
11
- end
12
-
13
- def test_variable_repetition
14
- assert parse(Repetition.new(3, Alpha.new), "abcdefg")
15
- assert parse(Repetition.new(1, Alpha.new), "a12345")
16
- assert_nil parse(Repetition.new(3, Alpha.new), "ab123")
17
- assert_nil parse(Repetition.new(1, Alpha.new), "123456")
18
- assert parse(Repetition.new(1..3, Alpha.new), "ab1234")
19
- assert_nil parse(Repetition.new(3..5, Alpha.new), "ab1234")
20
- assert parse(Repetition.new(0, Alpha.new), "12345")
21
- assert parse(Repetition.new(0..4, Alpha.new), "a1234")
22
- assert parse(Repetition.new(0..1, Alpha.new), "1234")
23
- assert parse(Repetition.new(0..1, Alpha.new), "a1234")
24
- assert parse(Repetition.new(0..1, Alpha.new), "ab1234")
25
- assert parse(Repetition.new([:at_least, 2], Alpha.new){|r| assert_equal "ab", r}, "ab1234")
26
- assert parse(Repetition.new([:at_least, 2], Alpha.new){|r| assert_equal "abcde", r}, "abcde12")
27
- assert parse(Repetition.new([:at_most, 3], Alpha.new){|r| assert_equal "abc", r}, "abcdefgh")
28
- assert parse(Repetition.new([:at_most, 3], Alpha.new), "12345")
29
- assert parse(Repetition.new([:at_most, 3], Alpha.new){|r| assert_equal "ab", r}, "ab12345")
30
- assert parse(Concat.new(Optional.new(Digit.new), Alpha.new), "a")
31
- assert parse(Concat.new(Optional.new(Digit.new), Alpha.new), "1a")
32
- assert parse(Repetition.new(:any, Alpha.new), "12345")
33
- assert parse(Repetition.new(:any, Alpha.new), "abcdefg12345")
34
- end
35
-
36
- def test_single_char_parse
37
- parser = Char.new(?-)
38
- assert_nil parse(parser, ")")
39
- assert parse(parser, "-")
40
- end
41
-
42
- def test_alternate_char_parse
43
- parser = AlternateChars.new("abcdef")
44
- assert_nil parse(parser, ")")
45
- assert_nil parse(parser, "-")
46
- assert parse(parser, "a")
47
- assert parse(parser, "b")
48
- assert parse(parser, "c")
49
- assert parse(parser, "d")
50
- assert parse(parser, "e")
51
- assert parse(parser, "f")
52
- assert_nil parse(parser, "g")
53
- end
54
-
55
- def test_literal_parse
56
- parser = Literal.new("abcdef")
57
-
58
- assert parse(parser, "abcdef")
59
-
60
- assert_nil parse(parser, ")")
61
- assert_nil parse(parser, "-")
62
- assert_nil parse(parser, "a")
63
- assert_nil parse(parser, "abcd")
64
- end
65
-
66
- def test_set_block
67
- output = nil
68
- parser = Literal.new("abcdef")
69
-
70
- assert parse(parser, "abcdef")
71
- assert_nil output
72
-
73
- parser.set_block {|m| output = m}
74
-
75
- assert parse(parser, "abcdef")
76
-
77
- assert (output == "abcdef")
78
- end
79
-
80
- def test_optional_concat_parse
81
- # Parser represents ["a" "b"] "c"
82
- parser = Concat.new(OptionalConcat.new(Char.new(?a), Char.new(?b)), Char.new(?c))
83
-
84
- assert parse(parser, "abc")
85
- assert parse(parser, "c")
86
-
87
- assert_nil parse(parser, ")")
88
- assert_nil parse(parser, "-")
89
- assert_nil parse(parser, "a")
90
- assert_nil parse(parser, "ab")
91
- assert_nil parse(parser, "ac")
92
- end
93
-
94
- def test_example_1
95
-
96
- # Phone Number
97
- p1 = Concat.new(Repetition.new(3, Digit.new), Char.new(?-), Repetition.new(4, Digit.new))
98
- assert_nil parse(p1, "22-3452")
99
- assert_nil parse(p1, "hello world")
100
- assert_nil parse(p1, "4293-603")
101
- assert_nil parse(p1, "")
102
- assert_nil parse(p1, "4293-3603")
103
- assert_nil parse(p1, "734-904-2840")
104
- assert parse(p1, "429-3603")
105
-
106
- # Phone Number w/ optional Area Code, same delimiters
107
- phone_number = Concat.new(Repetition.new(3, Digit.new), Char.new(?-), Repetition.new(4, Digit.new)){|pn| assert_equal "904-2840", pn}
108
- area_code = Concat.new(Repetition.new(3, Digit.new), Char.new(?-))
109
- p2 = Alternate.new(Concat.new(area_code, phone_number){|f| assert_equal "734-904-2840", f}, phone_number)
110
- assert_nil parse(p2, "22-3452")
111
- assert_nil parse(p2, "hello world")
112
- assert_nil parse(p2, "4293-603")
113
- assert_nil parse(p2, "")
114
- assert_nil parse(p2, "4293-3603")
115
- assert parse(p2, "904-2840")
116
- assert parse(p2, "734-904-2840")
117
-
118
- # Phone Number w/ optional Area Code, different delimiters
119
- area_code = Concat.new(Char.new(?(), Repetition.new(3, Digit.new), Char.new(?)))
120
- p3 = Concat.new(Optional.new(area_code), phone_number)
121
- assert parse(p3, "904-2840")
122
- end
123
- end
@@ -1,206 +0,0 @@
1
- $: << File.join(File.dirname(__FILE__), "../lib")
2
-
3
- require 'test/unit'
4
- require 'abnf'
5
-
6
- # The rules and state for a URL parser. Taken almost verbatim from RFC 3986.
7
- # There is no support for IP-literal, IPvFuture, or IPv6address.
8
- # These rules are not implemented: absolute_uri, path, reserved and gen_delims although there is
9
- # no functional reason that they couldn't be.
10
-
11
- class URLParser
12
- include ABNF
13
-
14
- URL = Struct.new("URL", :fragment, :host, :path, :port, :scheme, :user)
15
-
16
- # API
17
-
18
- def parse(str)
19
- @result = Struct::URL.new
20
-
21
- if uri_reference.match(Stream.new(str))
22
- @result
23
- else
24
- raise RuntimeError.new("Parse error")
25
- end
26
- end
27
-
28
- # Rules
29
-
30
- def scheme
31
- Concat.new(Alpha.new, Repetition.new(:any, Alternate.new(Alpha.new, Digit.new,
32
- Char.new(?+), Char.new(?-), Char.new(?.)))){|s| @result.scheme = s}
33
- end
34
-
35
- def dec_octet
36
- Alternate.new(Concat.new(Char.new(?2), Char.new(?5), Range.new(0x30..0x35)), # 250-255
37
- Concat.new(Char.new(?2), Range.new(0x30..0x34), Digit.new), # 200-249
38
- Concat.new(Char.new(?1), Repetition.new(2, Digit.new)), # 100-199
39
- Concat.new(Range.new(0x31..0x39), Digit.new), # 10-99
40
- Digit.new) # 0-9
41
- end
42
-
43
- def pct_encoded
44
- Concat.new(Char.new(?%), HexDigit.new, HexDigit.new)
45
- end
46
-
47
- def sub_delims
48
- Alternate.new(Char.new(?!), Char.new(?$), Char.new(?&), Char.new(?'), Char.new(?(),
49
- Char.new(?)), Char.new(?*), Char.new(?+), Char.new(?,), Char.new(?;), Char.new(?=))
50
- end
51
-
52
- def unreserved
53
- Alternate.new(Alpha.new, Digit.new, Char.new(?-), Char.new(?.), Char.new(?_), Char.new(?~))
54
- end
55
-
56
- def pchar
57
- Alternate.new(unreserved, pct_encoded, sub_delims, Char.new(?:), Char.new(?@))
58
- end
59
-
60
- def ipv4_address
61
- Concat.new(dec_octet, Char.new(?.), dec_octet, Char.new(?.), dec_octet, Char.new(?.), dec_octet)
62
- end
63
-
64
- def reg_name
65
- Repetition.new(:any, Alternate.new(unreserved, pct_encoded, sub_delims))
66
- end
67
-
68
- def host
69
- Alternate.new(ipv4_address, reg_name){|host| @result.host = host}
70
- end
71
-
72
- def port
73
- Repetition.new(:any, Digit.new){|port| @result.port = port.to_i}
74
- end
75
-
76
- def userinfo
77
- Repetition.new(:any, Alternate.new(unreserved, pct_encoded, sub_delims, Char.new(?:))){|u| @result.user = u}
78
- end
79
-
80
- def authority
81
- Concat.new(Optional.new(Concat.new(userinfo, Char.new(?@))), host, Optional.new(Concat.new(Char.new(?:), port)))
82
- end
83
-
84
- def segment
85
- Repetition.new(:any, pchar)
86
- end
87
-
88
- def segment_nz
89
- Repetition.new([:at_least, 1], pchar)
90
- end
91
-
92
- def segment_nz_nc # non-zero-length segment without any colon
93
- Repetition.new([:at_least, 1], Alternate.new(unreserved, pct_encoded, sub_delims, Char.new(?@)))
94
- end
95
-
96
- def path_abempty
97
- Repetition.new(:any, Concat.new(Char.new(?/), segment)){|path| @result.path = path}
98
- end
99
-
100
- def path_absolute
101
- Concat.new(Char.new(?/),
102
- Optional.new(Concat.new(segment_nz, Repetition.new(:any, Concat.new(Char.new(?/), segment))))){|path| @result.path = path}
103
- end
104
-
105
- def path_empty
106
- Repetition.new(0, pchar){|path| @result.path = path}
107
- end
108
-
109
- def path_noscheme
110
- Concat.new(segment_nz_nc, Repetition.new(:any, Concat.new(Char.new(?/), segment)))
111
- end
112
-
113
- def path_rootless
114
- Concat.new(segment_nz, Repetition.new(:any, Concat.new(Char.new(?/), segment))){|path| @result.path = path}
115
- end
116
-
117
- def hier_part
118
- Alternate.new(Concat.new(Char.new(?/), Char.new(?/), authority, path_abempty),
119
- path_absolute,
120
- path_rootless,
121
- path_empty)
122
- end
123
-
124
- def query
125
- Repetition.new(:any, Alternate.new(pchar, Char.new(?/), Char.new(??))){|query| puts query}
126
- end
127
-
128
- def fragment
129
- Repetition.new(:any, Alternate.new(pchar, Char.new(?/), Char.new(??))){|fragment| @result.fragment = fragment}
130
- end
131
-
132
- def uri
133
- Concat.new(scheme,
134
- Char.new(?:),
135
- hier_part,
136
- Optional.new(Concat.new(Char.new(??), query)),
137
- Optional.new(Concat.new(Char.new(?#), fragment)))
138
- end
139
-
140
- def relative_part
141
- Alternate.new(Concat.new(Char.new(?/), Char.new(?/), authority, path_abempty),
142
- path_absolute,
143
- path_noscheme,
144
- path_empty)
145
- end
146
-
147
- def relative_ref
148
- Concat.new(relative_part,
149
- Optional.new(Concat.new(Char.new(??), query)),
150
- Optional.new(Concat.new(Char.new(?#), fragment)))
151
- end
152
-
153
- def uri_reference
154
- Alternate.new(uri, relative_ref)
155
- end
156
- end
157
-
158
- class ABNFTest < Test::Unit::TestCase
159
- include ABNF
160
-
161
- def test_url_parser
162
-
163
- #
164
- # URLs
165
-
166
- u = URLParser.new.parse("http://karmalab.org")
167
- assert u
168
- assert_equal "http", u.scheme
169
- assert_equal "karmalab.org", u.host
170
- assert_nil u.port
171
- assert_equal "", u.path
172
-
173
- u = URLParser.new.parse("http://rt@karmalab.org:9001")
174
- assert u
175
- assert_equal "http", u.scheme
176
- assert_equal "karmalab.org", u.host
177
- assert_equal 9001, u.port
178
- assert_equal "rt", u.user
179
- assert_equal "", u.path
180
-
181
- u = URLParser.new.parse("file:///tmp/file.txt")
182
- assert u
183
- assert_equal "file", u.scheme
184
- assert_equal "/tmp/file.txt", u.path
185
- assert_blank u.host
186
- assert_blank u.port
187
- assert_blank u.user
188
-
189
- u = URLParser.new.parse("http://triggit.com/j?u=rt10880&p=http://lambda/#fragment16")
190
- assert u
191
- assert_equal "http", u.scheme
192
- assert_equal "triggit.com", u.host
193
- assert_equal "/j", u.path
194
- assert_equal "fragment16", u.fragment
195
-
196
- u = URLParser.new.parse("about:config")
197
- assert u
198
- assert_equal "about", u.scheme
199
- assert_equal "config", u.path
200
-
201
- u = URLParser.new.parse("/path/to/file.html#fr23-1")
202
- assert u
203
- assert_equal "/path/to/file.html", u.path
204
- assert_equal "fr23-1", u.fragment
205
- end
206
- end