sxp 0.0.3 → 0.0.4

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/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.0.4
data/lib/sxp.rb CHANGED
@@ -1,7 +1,73 @@
1
1
  require 'sxp/version'
2
2
  require 'sxp/extensions'
3
- require 'sxp/pair'
4
- require 'sxp/list'
5
- require 'sxp/reader'
6
3
  require 'sxp/writer'
7
- require 'sxp/generator'
4
+
5
+ module SXP
6
+ autoload :Pair, 'sxp/pair'
7
+ autoload :List, 'sxp/list'
8
+ autoload :Generator, 'sxp/generator'
9
+ autoload :Reader, 'sxp/reader'
10
+
11
+ ##
12
+ # Reads all S-expressions from a given input URI using the HTTP or FTP
13
+ # protocols.
14
+ #
15
+ # @param [String, #to_s] url
16
+ # @param [Hash{Symbol => Object}] options
17
+ # @return [Enumerable<Object>]
18
+ def self.read_url(url, options = {})
19
+ require 'openuri'
20
+ open(url.to_s, 'rb', nil, options) { |io| read_all(io, options) }
21
+ end
22
+
23
+ ##
24
+ # Reads all S-expressions from the given input files.
25
+ #
26
+ # @param [Enumerable<String>] filenames
27
+ # @param [Hash{Symbol => Object}] options
28
+ # @return [Enumerable<Object>]
29
+ def self.read_files(*filenames)
30
+ options = filenames.last.is_a?(Hash) ? filenames.pop : {}
31
+ filenames.map { |filename| read_file(filename, options) }.inject { |sxps, sxp| sxps + sxp }
32
+ end
33
+
34
+ ##
35
+ # Reads all S-expressions from a given input file.
36
+ #
37
+ # @param [String, #to_s] filename
38
+ # @param [Hash{Symbol => Object}] options
39
+ # @return [Enumerable<Object>]
40
+ def self.read_file(filename, options = {})
41
+ File.open(filename.to_s, 'rb') { |io| read_all(io, options) }
42
+ end
43
+
44
+ ##
45
+ # Reads all S-expressions from the given input stream.
46
+ #
47
+ # @param [IO, StringIO, String] input
48
+ # @param [Hash{Symbol => Object}] options
49
+ # @return [Enumerable<Object>]
50
+ def self.read_all(input, options = {})
51
+ Reader.new(input, options).read_all
52
+ end
53
+
54
+ ##
55
+ # Reads one S-expression from the given input stream.
56
+ #
57
+ # @param [IO, StringIO, String] input
58
+ # @param [Hash{Symbol => Object}] options
59
+ # @return [Object]
60
+ def self.read(input, options = {})
61
+ Reader.new(input, options).read
62
+ end
63
+
64
+ class << self
65
+ alias_method :parse, :read
66
+ alias_method :parse_all, :read_all
67
+ alias_method :parse_files, :read_files
68
+ alias_method :parse_file, :read_file
69
+ alias_method :parse_url, :read_url
70
+ alias_method :parse_uri, :read_url # @deprecated
71
+ alias_method :read_uri, :read_url # @deprecated
72
+ end
73
+ end # module SXP
@@ -1,6 +1,10 @@
1
+ ##
2
+ # Extensions for Ruby's `Symbol` class.
1
3
  class Symbol
2
4
  ##
3
- # Returns +true+ if this is a keyword symbol.
5
+ # Returns `true` if this is a keyword symbol.
6
+ #
7
+ # @return [Boolean]
4
8
  def keyword?
5
9
  to_s[-1] == ?:
6
10
  end
data/lib/sxp/generator.rb CHANGED
@@ -1,14 +1,26 @@
1
1
  module SXP
2
+ ##
3
+ # An S-expression generator.
2
4
  class Generator
5
+ ##
6
+ # @param [Array] sxps
7
+ # @return [Object]
3
8
  def self.string(*sxps)
4
9
  require 'stringio' unless defined?(StringIO)
5
10
  write(StringIO.new, *sxps).instance_variable_get('@buffer').string
6
11
  end
7
12
 
13
+ ##
14
+ # @param [Array] sxps
15
+ # @return [Object]
8
16
  def self.print(*sxps)
9
17
  write($stdout, *sxps)
10
18
  end
11
19
 
20
+ ##
21
+ # @param [Object] out
22
+ # @param [Array] sxps
23
+ # @return [Object]
12
24
  def self.write(out, *sxps)
13
25
  generator = self.new(out)
14
26
  sxps.each do |sxp|
@@ -17,6 +29,8 @@ module SXP
17
29
  generator
18
30
  end
19
31
 
32
+ ##
33
+ # @param [Object] buffer
20
34
  def initialize(buffer)
21
35
  @output = [@buffer = buffer]
22
36
  @indent = 0
@@ -24,39 +38,53 @@ module SXP
24
38
 
25
39
  protected
26
40
 
27
- def emit(text, options = {})
28
- if out = @output.last
29
- out.print(' ' * (indent * 2)) if options[:indent]
30
- out.print(text)
31
- end
41
+ ##
42
+ # @param [String] text
43
+ # @param [Hash{Symbol => Object}] options
44
+ # @return [void]
45
+ def emit(text, options = {})
46
+ if out = @output.last
47
+ out.print(' ' * (indent * 2)) if options[:indent]
48
+ out.print(text)
32
49
  end
50
+ end
33
51
 
34
- def captured(&block)
35
- require 'stringio' unless defined?(StringIO)
36
- begin
37
- @output.push(buffer = StringIO.new)
38
- block.call
39
- ensure
40
- @output.pop
41
- end
42
- buffer.string
52
+ ##
53
+ # @yield
54
+ # @return [String]
55
+ def captured(&block)
56
+ require 'stringio' unless defined?(StringIO)
57
+ begin
58
+ @output.push(buffer = StringIO.new)
59
+ block.call
60
+ ensure
61
+ @output.pop
43
62
  end
63
+ buffer.string
64
+ end
44
65
 
45
- def indented(&block)
46
- begin
47
- increase_indent!
48
- block.call
49
- ensure
50
- decrease_indent!
51
- end
66
+ ##
67
+ # @yield
68
+ # @return [Object]
69
+ def indented(&block)
70
+ begin
71
+ increase_indent!
72
+ block.call
73
+ ensure
74
+ decrease_indent!
52
75
  end
76
+ end
53
77
 
54
- def increase_indent!()
55
- @indent += 1
56
- end
78
+ ##
79
+ # @return [void]
80
+ def increase_indent!
81
+ @indent += 1
82
+ end
57
83
 
58
- def decrease_indent!()
59
- @indent -= 1
60
- end
61
- end
62
- end
84
+ ##
85
+ # @return [void]
86
+ def decrease_indent!
87
+ @indent -= 1
88
+ end
89
+ end # class Generator
90
+ end # module SXP
data/lib/sxp/list.rb CHANGED
@@ -1,62 +1,106 @@
1
1
  require 'sxp/pair'
2
2
 
3
3
  module SXP
4
+ ##
5
+ # A singly-linked list.
4
6
  class List < Pair
5
7
  include Enumerable
6
8
 
9
+ ##
10
+ # @param [Array] elements
11
+ # @return [Object]
7
12
  def self.[](*elements)
8
13
  self.new(elements)
9
14
  end
10
15
 
16
+ ##
17
+ # @param [Array] elements
18
+ # @yield [list]
19
+ # @yieldparam [List] list
11
20
  def initialize(elements = [], &block)
12
21
  @pair = nil
13
22
  unshift(*elements) unless elements.empty?
14
23
  block.call(self) if block_given?
15
24
  end
16
25
 
26
+ ##
27
+ # @return [String]
17
28
  def inspect
18
29
  "(" << map { |value| value.inspect }.join(' ') << ")"
19
30
  end
20
31
 
21
- def head() first end
22
- def tail() rest end
32
+ ##
33
+ # @return [Object]
34
+ def head
35
+ first
36
+ end
37
+
38
+ ##
39
+ # @return [Object]
40
+ def tail
41
+ rest
42
+ end
23
43
 
44
+ ##
45
+ # @return [Object]
24
46
  def rest
25
47
  empty? ? false : @pair.tail
26
48
  end
27
49
 
28
- # Array interface
29
-
50
+ ##
51
+ # @param [Object] other
52
+ # @return [Object]
30
53
  def &(other)
31
54
  self.class.new(self.to_a & other.to_a)
32
55
  end
33
56
 
57
+ ##
58
+ # @param [Object] other
59
+ # @return [Object]
34
60
  def |(other)
35
61
  self.class.new(self.to_a | other.to_a)
36
62
  end
37
63
 
64
+ ##
65
+ # @param [Object] times
66
+ # @return [Object]
38
67
  def *(times)
39
68
  result = (self.to_a * times)
40
69
  result.is_a?(Array) ? self.class.new(result) : result
41
70
  end
42
71
 
72
+ ##
73
+ # @param [Object] other
74
+ # @return [Object]
43
75
  def +(other)
44
76
  self.class.new(self.to_a + other.to_a)
45
77
  end
46
78
 
79
+ ##
80
+ # @param [Object] other
81
+ # @return [Object]
47
82
  def -(other)
48
83
  self.class.new(self.to_a - other.to_a)
49
84
  end
50
85
 
86
+ ##
87
+ # @param [Object] object
88
+ # @return [Object]
51
89
  def <<(object)
52
90
  push(object)
53
91
  self
54
92
  end
55
93
 
94
+ ##
95
+ # @param [Object] other
96
+ # @return [Object]
56
97
  def <=>(other)
57
98
  to_a <=> other.to_a
58
99
  end
59
100
 
101
+ ##
102
+ # @param [Object] other
103
+ # @return [Object]
60
104
  def ==(other)
61
105
  case other
62
106
  when List
@@ -68,56 +112,89 @@ module SXP
68
112
  end
69
113
  end
70
114
 
115
+ ##
116
+ # @param [Array] args
117
+ # @return [Object]
71
118
  def [](*args)
72
119
  result = to_a[*args]
73
120
  result.is_a?(Array) ? self.class.new(result) : result # FIXME
74
121
  end
75
122
 
123
+ ##
124
+ # @param [Array] args
125
+ # @return [Object]
76
126
  def []=(*args)
77
127
  raise NotImplementedError # TODO
78
128
  end
79
129
 
130
+ ##
131
+ # @param [Object] object
132
+ # @return [Object]
80
133
  def assoc(object)
81
134
  raise NotImplementedError # TODO
82
135
  end
83
136
 
137
+ ##
138
+ # @param [Integer] index
139
+ # @return [Object]
84
140
  def at(index)
85
141
  to_a.at(index)
86
142
  end
87
143
 
144
+ ##
145
+ # @return [Object]
88
146
  def clear
89
147
  @pair = nil
90
148
  self
91
149
  end
92
150
 
151
+ ##
152
+ # @return [Object]
93
153
  def collect!(&block)
94
154
  raise NotImplementedError # TODO
95
155
  end
96
156
 
157
+ ##
158
+ # @return [Object]
97
159
  def compact
98
160
  self.class.new(to_a.compact)
99
161
  end
100
162
 
163
+ ##
164
+ # @return [Object]
101
165
  def compact!
102
166
  raise NotImplementedError # TODO
103
167
  end
104
168
 
169
+ ##
170
+ # @param [Object] other
171
+ # @return [Object]
105
172
  def concat(other)
106
173
  raise NotImplementedError # TODO
107
174
  end
108
175
 
176
+ ##
177
+ # @param [Object] object
178
+ # @return [Object]
109
179
  def delete(object, &block)
110
180
  raise NotImplementedError # TODO
111
181
  end
112
182
 
183
+ ##
184
+ # @param [Integer] index
185
+ # @return [Object]
113
186
  def delete_at(index)
114
187
  raise NotImplementedError # TODO
115
188
  end
116
189
 
190
+ ##
191
+ # @return [Object]
117
192
  def delete_if(&block)
118
193
  raise NotImplementedError # TODO
119
194
  end
120
195
 
196
+ ##
197
+ # @return [Enumerator]
121
198
  def each(&block)
122
199
  pair = @pair
123
200
  while pair != nil
@@ -127,19 +204,25 @@ module SXP
127
204
  self
128
205
  end
129
206
 
207
+ ##
208
+ # @return [Enumerator]
130
209
  def each_index(&block)
131
210
  index = 0
132
211
  each do
133
212
  block.call(index)
134
213
  index += 1
135
214
  end
136
- self
137
215
  end
138
216
 
217
+ ##
218
+ # @return [Boolean]
139
219
  def empty?
140
220
  @pair.nil?
141
221
  end
142
222
 
223
+ ##
224
+ # @param [Object] other
225
+ # @return [Boolean]
143
226
  def eql?(other)
144
227
  case other
145
228
  when self then true
@@ -148,14 +231,23 @@ module SXP
148
231
  end
149
232
  end
150
233
 
234
+ ##
235
+ # @param [Array] args
236
+ # @return [Object]
151
237
  def fetch(*args, &block)
152
238
  to_a.fetch(*args, &block)
153
239
  end
154
240
 
241
+ ##
242
+ # @param [Array] args
243
+ # @return [Object]
155
244
  def fill(*args, &block)
156
245
  raise NotImplementedError # TODO
157
246
  end
158
247
 
248
+ ##
249
+ # @param [Integer] count
250
+ # @return [Object]
159
251
  def first(count = nil)
160
252
  case
161
253
  when count.nil?
@@ -167,30 +259,50 @@ module SXP
167
259
  end
168
260
  end
169
261
 
262
+ ##
263
+ # @return [Object]
170
264
  def flatten
171
265
  raise NotImplementedError # TODO
172
266
  end
173
267
 
268
+ ##
269
+ # @return [Object]
174
270
  def flatten!
175
271
  raise NotImplementedError # TODO
176
272
  end
177
273
 
274
+ ##
275
+ # @param [Object] object
276
+ # @return [Object]
178
277
  def include?(object)
179
278
  to_a.include?(object)
180
279
  end
181
280
 
281
+ ##
282
+ # @param [Object] object
283
+ # @return [Object]
182
284
  def index(object)
183
285
  to_a.index(object)
184
286
  end
185
287
 
288
+ ##
289
+ # @param [Integer] index
290
+ # @param [Array] objects
291
+ # @return [Object]
186
292
  def insert(index, *objects)
187
293
  raise NotImplementedError # TODO
188
294
  end
189
295
 
296
+ ##
297
+ # @param [String] separator
298
+ # @return [Object]
190
299
  def join(separator = $,)
191
300
  to_a.join(separator)
192
301
  end
193
302
 
303
+ ##
304
+ # @param [Integer] count
305
+ # @return [Object]
194
306
  def last(count = nil)
195
307
  case
196
308
  when count.nil?
@@ -200,38 +312,60 @@ module SXP
200
312
  end
201
313
  end
202
314
 
315
+ ##
316
+ # @return [Integer]
203
317
  def length
204
318
  @length ||= to_a.length
205
319
  end
206
320
 
321
+ ##
322
+ # @return [Object]
207
323
  def map!(&block)
208
324
  collect!(&block)
209
325
  end
210
326
 
327
+ ##
328
+ # @return [Integer]
211
329
  def nitems
212
330
  to_a.nitems
213
331
  end
214
332
 
333
+ ##
334
+ # @param [Object] template
335
+ # @return [Object]
215
336
  def pack(template)
216
337
  to_a.pack(template)
217
338
  end
218
339
 
340
+ ##
341
+ # @return [Object]
219
342
  def pop
220
343
  raise NotImplementedError # TODO
221
344
  end
222
345
 
346
+ ##
347
+ # @param [Array] objects
348
+ # @return [Object]
223
349
  def push(*objects)
224
350
  raise NotImplementedError # TODO
225
351
  end
226
352
 
353
+ ##
354
+ # @param [Object] key
355
+ # @return [Object]
227
356
  def rassoc(key)
228
357
  raise NotImplementedError # TODO
229
358
  end
230
359
 
360
+ ##
361
+ # @return [Object]
231
362
  def reject!(&block)
232
363
  raise NotImplementedError # TODO
233
364
  end
234
365
 
366
+ ##
367
+ # @param [Object] other_list
368
+ # @return [Object]
235
369
  def replace(other_list)
236
370
  case other_list
237
371
  when Pair
@@ -247,72 +381,110 @@ module SXP
247
381
  self
248
382
  end
249
383
 
384
+ ##
385
+ # @return [Object]
250
386
  def reverse
251
387
  self.class.new(to_a.reverse)
252
388
  end
253
389
 
390
+ ##
391
+ # @return [Object]
254
392
  def reverse!
255
393
  raise NotImplementedError # TODO
256
394
  end
257
395
 
396
+ ##
397
+ # @return [Object]
258
398
  def reverse_each(&block)
259
399
  to_a.reverse_each(&block)
260
400
  self
261
401
  end
262
402
 
403
+ ##
404
+ # @param [Object] object
405
+ # @return [Object]
263
406
  def rindex(object)
264
407
  to_a.rindex(object)
265
408
  end
266
409
 
410
+ ##
411
+ # @return [Object]
267
412
  def shift
268
413
  raise NotImplementedError # TODO
269
414
  end
270
415
 
416
+ ##
417
+ # @return [Integer]
271
418
  def size
272
419
  length
273
420
  end
274
421
 
422
+ ##
423
+ # @param [Array] args
424
+ # @return [Object]
275
425
  def slice(*args)
276
426
  self[*args]
277
427
  end
278
428
 
429
+ ##
430
+ # @param [Array] args
431
+ # @return [Object]
279
432
  def slice!(*args)
280
433
  raise NotImplementedError # TODO
281
434
  end
282
435
 
436
+ ##
437
+ # @return [Object]
283
438
  def sort(&block)
284
439
  (array = to_a).sort!(&block)
285
440
  self.class.new(array)
286
441
  end
287
442
 
443
+ ##
444
+ # @return [Object]
288
445
  def sort!
289
446
  raise NotImplementedError # TODO
290
447
  end
291
448
 
449
+ ##
450
+ # @return [List]
292
451
  def to_list
293
452
  self
294
453
  end
295
454
 
455
+ ##
456
+ # @return [Pair]
296
457
  def to_pair
297
458
  @pair
298
459
  end
299
460
 
461
+ ##
462
+ # @return [String]
300
463
  def to_s
301
464
  join
302
465
  end
303
466
 
467
+ ##
468
+ # @return [Object]
304
469
  def transpose
305
470
  self.class.new(to_a.transpose)
306
471
  end
307
472
 
473
+ ##
474
+ # @return [Object]
308
475
  def uniq
309
476
  self.class.new(to_a.uniq)
310
477
  end
311
478
 
479
+ ##
480
+ # @return [Object]
312
481
  def uniq!
313
482
  raise NotImplementedError # TODO
314
483
  end
315
484
 
485
+ ##
486
+ # @param [Array] objects
487
+ # @return [Object]
316
488
  def unshift(*objects)
317
489
  objects.reverse_each do |object|
318
490
  @pair = Pair.new(object, @pair)
@@ -320,8 +492,11 @@ module SXP
320
492
  self
321
493
  end
322
494
 
495
+ ##
496
+ # @param [Array] selector
497
+ # @return [Object]
323
498
  def values_at(*selector)
324
499
  self.class.new(to_a.values_at(*selector))
325
500
  end
326
- end
327
- end
501
+ end # class List
502
+ end # module SXP
data/lib/sxp/pair.rb CHANGED
@@ -1,39 +1,64 @@
1
1
  module SXP
2
+ ##
2
3
  class Pair
4
+ # @return [Object]
3
5
  attr_accessor :head
6
+
7
+ # @return [Object]
4
8
  attr_accessor :tail
5
9
 
10
+ ##
11
+ # @param [Object] head
12
+ # @param [Object] tail
6
13
  def initialize(head = nil, tail = nil)
7
14
  @head, @tail = head, tail
8
15
  end
9
16
 
10
- def inspect
11
- case
12
- when tail.nil?
13
- "(#{head.inspect})"
14
- else
15
- "(#{head.inspect} . #{tail.inspect})"
16
- end
17
- end
18
-
17
+ ##
18
+ # Returns `true` if the head and tail of this pair are both `nil`.
19
+ #
20
+ # @return [Boolean]
19
21
  def empty?
20
22
  head.nil? && tail.nil?
21
23
  end
22
24
 
23
25
  ##
24
- # @see http://srfi.schemers.org/srfi-1/srfi-1.html#ImproperLists
26
+ # Returns `true` if the tail of this pair is not `nil` or another pair.
27
+ #
28
+ # @return [Boolean]
29
+ # @see http://srfi.schemers.org/srfi-1/srfi-1.html#ImproperLists
25
30
  def dotted?
26
31
  !proper?
27
32
  end
28
33
 
29
34
  ##
30
- # @see http://srfi.schemers.org/srfi-1/srfi-1.html#ImproperLists
35
+ # Returns `true` if the tail of this pair is `nil` or another pair.
36
+ #
37
+ # @return [Boolean]
38
+ # @see http://srfi.schemers.org/srfi-1/srfi-1.html#ImproperLists
31
39
  def proper?
32
40
  tail.nil? || tail.is_a?(Pair)
33
41
  end
34
42
 
43
+ ##
44
+ # Returns an array representation of this pair.
45
+ #
46
+ # @return [Array]
35
47
  def to_a
36
48
  [head, tail]
37
49
  end
38
- end
39
- end
50
+
51
+ ##
52
+ # Returns a developer-friendly representation of this pair.
53
+ #
54
+ # @return [String]
55
+ def inspect
56
+ case
57
+ when tail.nil?
58
+ "(#{head.inspect})"
59
+ else
60
+ "(#{head.inspect} . #{tail.inspect})"
61
+ end
62
+ end
63
+ end # class Pair
64
+ end # module SXP
data/lib/sxp/reader.rb CHANGED
@@ -1,67 +1,6 @@
1
1
  module SXP
2
2
  ##
3
- # Reads all S-expressions from a given input URI using the HTTP or FTP
4
- # protocols.
5
- #
6
- # @param [String, #to_s] url
7
- # @param [Hash{Symbol => Object}] options
8
- # @return [Enumerable<Object>]
9
- def self.read_url(url, options = {})
10
- require 'openuri'
11
- open(url.to_s, 'rb', nil, options) { |io| read_all(io, options) }
12
- end
13
-
14
- ##
15
- # Reads all S-expressions from the given input files.
16
- #
17
- # @param [Enumerable<String>] filenames
18
- # @param [Hash{Symbol => Object}] options
19
- # @return [Enumerable<Object>]
20
- def self.read_files(*filenames)
21
- options = filenames.last.is_a?(Hash) ? filenames.pop : {}
22
- filenames.map { |filename| read_file(filename, options) }.inject { |sxps, sxp| sxps + sxp }
23
- end
24
-
25
- ##
26
- # Reads all S-expressions from a given input file.
27
- #
28
- # @param [String, #to_s] filename
29
- # @param [Hash{Symbol => Object}] options
30
- # @return [Enumerable<Object>]
31
- def self.read_file(filename, options = {})
32
- File.open(filename.to_s, 'rb') { |io| read_all(io, options) }
33
- end
34
-
35
- ##
36
- # Reads all S-expressions from the given input stream.
37
- #
38
- # @param [IO, StringIO, String] input
39
- # @param [Hash{Symbol => Object}] options
40
- # @return [Enumerable<Object>]
41
- def self.read_all(input, options = {})
42
- Reader.new(input, options).read_all
43
- end
44
-
45
- ##
46
- # Reads one S-expression from the given input stream.
47
- #
48
- # @param [IO, StringIO, String] input
49
- # @param [Hash{Symbol => Object}] options
50
- # @return [Object]
51
- def self.read(input, options = {})
52
- Reader.new(input, options).read
53
- end
54
-
55
- class << self
56
- alias_method :parse, :read
57
- alias_method :parse_all, :read_all
58
- alias_method :parse_files, :read_files
59
- alias_method :parse_file, :read_file
60
- alias_method :parse_url, :read_url
61
- alias_method :parse_uri, :read_url # @deprecated
62
- alias_method :read_uri, :read_url # @deprecated
63
- end
64
-
3
+ # The base class for S-expression parsers.
65
4
  class Reader
66
5
  include Enumerable
67
6
 
@@ -76,8 +15,12 @@ module SXP
76
15
  RATIONAL = /^([+-]?\d+)\/(\d+)$/
77
16
  ATOM = /^[^\s()\[\]]+/
78
17
 
18
+ # @return [Object]
79
19
  attr_reader :input
80
20
 
21
+ ##
22
+ # @param [Object] input
23
+ # @param [Hash{Symbol => Object}] options
81
24
  def initialize(input, options = {})
82
25
  case
83
26
  when [:getc, :ungetc, :eof?].all? { |x| input.respond_to?(x) }
@@ -90,10 +33,17 @@ module SXP
90
33
  end
91
34
  end
92
35
 
36
+ ##
37
+ # @yield [object]
38
+ # @yieldparam [Object] object
39
+ # @return [Enumerator]
93
40
  def each(&block)
94
- block.call(read)
41
+ block.call(read) if block_given? # FIXME
95
42
  end
96
43
 
44
+ ##
45
+ # @param [Hash{Symbol => Object}] options
46
+ # @return [Array]
97
47
  def read_all(options = {})
98
48
  list = []
99
49
  catch (:eof) do
@@ -102,6 +52,9 @@ module SXP
102
52
  list
103
53
  end
104
54
 
55
+ ##
56
+ # @param [Hash{Symbol => Object}] options
57
+ # @return [Object]
105
58
  def read(options = {})
106
59
  skip_comments
107
60
  token, value = read_token
@@ -122,6 +75,8 @@ module SXP
122
75
 
123
76
  alias_method :skip, :read
124
77
 
78
+ ##
79
+ # @return [Object]
125
80
  def read_token
126
81
  case peek_char
127
82
  when nil then :eof
@@ -133,6 +88,8 @@ module SXP
133
88
  end
134
89
  end
135
90
 
91
+ ##
92
+ # @param [Array]
136
93
  def read_list
137
94
  list = []
138
95
  catch (:eol) do
@@ -141,23 +98,28 @@ module SXP
141
98
  list
142
99
  end
143
100
 
101
+ ##
102
+ # @return [Object]
144
103
  def read_sharp
145
104
  skip_char # '#'
146
105
  case char = read_char
147
- when ?n then nil
148
- when ?f then false
149
- when ?t then true
150
- when ?b then read_integer(2)
151
- when ?o then read_integer(8)
152
- when ?d then read_integer(10)
153
- when ?x then read_integer(16)
106
+ when ?n then nil
107
+ when ?f then false
108
+ when ?t then true
109
+ when ?b then read_integer(2)
110
+ when ?o then read_integer(8)
111
+ when ?d then read_integer(10)
112
+ when ?x then read_integer(16)
154
113
  when ?\\ then read_character
155
- when ?; then skip; read
156
- when ?! then skip_line # shebang
114
+ when ?; then skip; read
115
+ when ?! then skip_line; read # shebang
157
116
  else raise Error, "invalid sharp-sign read syntax: ##{char.chr}"
158
117
  end
159
118
  end
160
119
 
120
+ ##
121
+ # @param [Integer] base
122
+ # @return [Integer]
161
123
  def read_integer(base = 10)
162
124
  case buffer = read_literal
163
125
  when self.class.const_get(:"INTEGER_BASE_#{base}")
@@ -166,6 +128,8 @@ module SXP
166
128
  end
167
129
  end
168
130
 
131
+ ##
132
+ # @return [Object]
169
133
  def read_atom
170
134
  case buffer = read_literal
171
135
  when '.' then buffer.to_sym
@@ -176,6 +140,8 @@ module SXP
176
140
  end
177
141
  end
178
142
 
143
+ ##
144
+ # @return [String]
179
145
  def read_string
180
146
  buffer = String.new
181
147
  skip_char # '"'
@@ -190,6 +156,8 @@ module SXP
190
156
  buffer
191
157
  end
192
158
 
159
+ ##
160
+ # @return [String]
193
161
  def read_character
194
162
  case char = read_char
195
163
  when ?b then ?\b
@@ -203,12 +171,16 @@ module SXP
203
171
  end
204
172
  end
205
173
 
174
+ ##
175
+ # @return [String]
206
176
  def read_literal
207
177
  buffer = String.new
208
178
  buffer << read_char while !eof? && peek_char.chr =~ ATOM
209
179
  buffer
210
180
  end
211
181
 
182
+ ##
183
+ # @return [void]
212
184
  def skip_comments
213
185
  until eof?
214
186
  case (char = peek_char).chr
@@ -219,18 +191,25 @@ module SXP
219
191
  end
220
192
  end
221
193
 
194
+ ##
195
+ # @param [Integer] count
196
+ # @return [String]
222
197
  def read_chars(count = 1)
223
198
  buffer = ''
224
199
  count.times { buffer << read_char.chr }
225
200
  buffer
226
201
  end
227
202
 
203
+ ##
204
+ # @return [String]
228
205
  def read_char
229
206
  char = @input.getc
230
207
  raise EOF, 'unexpected end of input' if char.nil?
231
208
  char
232
209
  end
233
210
 
211
+ ##
212
+ # @return [void]
234
213
  def skip_line
235
214
  loop do
236
215
  break if eof? || read_char.chr == $/
@@ -239,13 +218,18 @@ module SXP
239
218
 
240
219
  alias_method :skip_char, :read_char
241
220
 
221
+ ##
222
+ # @return [String]
242
223
  def peek_char
243
224
  char = @input.getc
244
225
  @input.ungetc char unless char.nil?
245
226
  char
246
227
  end
247
228
 
248
- def eof?() @input.eof? end
249
- end
250
-
251
- end
229
+ ##
230
+ # @return [Boolean]
231
+ def eof?
232
+ @input.eof?
233
+ end
234
+ end # class Reader
235
+ end # module SXP
data/lib/sxp/version.rb CHANGED
@@ -2,7 +2,7 @@ module SXP
2
2
  module VERSION
3
3
  MAJOR = 0
4
4
  MINOR = 0
5
- TINY = 3
5
+ TINY = 4
6
6
  EXTRA = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY].join('.')
data/lib/sxp/writer.rb CHANGED
@@ -1,34 +1,94 @@
1
+ ##
2
+ # Extensions for Ruby's `Object` class.
1
3
  class Object
4
+ ##
5
+ # Returns the SXP representation of this object.
6
+ #
7
+ # @return [String]
2
8
  def to_sxp
3
9
  to_s.to_json
4
10
  end
5
11
  end
6
12
 
13
+ ##
14
+ # Extensions for Ruby's `NilClass` class.
7
15
  class NilClass
8
- def to_sxp; '#n'; end
16
+ ##
17
+ # Returns the SXP representation of this object.
18
+ #
19
+ # @return [String]
20
+ def to_sxp
21
+ '#n'
22
+ end
9
23
  end
10
24
 
25
+ ##
26
+ # Extensions for Ruby's `FalseClass` class.
11
27
  class FalseClass
12
- def to_sxp; '#f'; end
28
+ ##
29
+ # Returns the SXP representation of this object.
30
+ #
31
+ # @return [String]
32
+ def to_sxp
33
+ '#f'
34
+ end
13
35
  end
14
36
 
37
+ ##
38
+ # Extensions for Ruby's `TrueClass` class.
15
39
  class TrueClass
16
- def to_sxp; '#t'; end
40
+ ##
41
+ # Returns the SXP representation of this object.
42
+ #
43
+ # @return [String]
44
+ def to_sxp
45
+ '#t'
46
+ end
17
47
  end
18
48
 
49
+ ##
50
+ # Extensions for Ruby's `String` class.
19
51
  class String
20
- def to_sxp; inspect; end
52
+ ##
53
+ # Returns the SXP representation of this object.
54
+ #
55
+ # @return [String]
56
+ def to_sxp
57
+ inspect
58
+ end
21
59
  end
22
60
 
61
+ ##
62
+ # Extensions for Ruby's `Symbol` class.
23
63
  class Symbol
24
- def to_sxp; to_s; end
64
+ ##
65
+ # Returns the SXP representation of this object.
66
+ #
67
+ # @return [String]
68
+ def to_sxp
69
+ to_s
70
+ end
25
71
  end
26
72
 
73
+ ##
74
+ # Extensions for Ruby's `Integer` class.
27
75
  class Integer
28
- def to_sxp; to_s; end
76
+ ##
77
+ # Returns the SXP representation of this object.
78
+ #
79
+ # @return [String]
80
+ def to_sxp
81
+ to_s
82
+ end
29
83
  end
30
84
 
85
+ ##
86
+ # Extensions for Ruby's `Float` class.
31
87
  class Float
88
+ ##
89
+ # Returns the SXP representation of this object.
90
+ #
91
+ # @return [String]
32
92
  def to_sxp
33
93
  case
34
94
  when nan? then 'nan.'
@@ -38,19 +98,37 @@ class Float
38
98
  end
39
99
  end
40
100
 
101
+ ##
102
+ # Extensions for Ruby's `Array` class.
41
103
  class Array
104
+ ##
105
+ # Returns the SXP representation of this object.
106
+ #
107
+ # @return [String]
42
108
  def to_sxp
43
109
  '(' << map { |x| x.to_sxp }.join(' ') << ')'
44
110
  end
45
111
  end
46
112
 
113
+ ##
114
+ # Extensions for Ruby's `Time` class.
47
115
  class Time
116
+ ##
117
+ # Returns the SXP representation of this object.
118
+ #
119
+ # @return [String]
48
120
  def to_sxp
49
121
  '#@' << (respond_to?(:xmlschema) ? xmlschema : to_i).to_s
50
122
  end
51
123
  end
52
124
 
125
+ ##
126
+ # Extensions for Ruby's `Regexp` class.
53
127
  class Regexp
128
+ ##
129
+ # Returns the SXP representation of this object.
130
+ #
131
+ # @return [String]
54
132
  def to_sxp
55
133
  '#' << inspect
56
134
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 3
9
- version: 0.0.3
8
+ - 4
9
+ version: 0.0.4
10
10
  platform: ruby
11
11
  authors:
12
12
  - Arto Bendiken
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-05-14 00:00:00 +02:00
17
+ date: 2010-05-25 00:00:00 +02:00
18
18
  default_executable: sxp2rdf
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency