sxp 1.1.0 → 1.2.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.
- checksums.yaml +4 -4
- data/AUTHORS +1 -1
- data/README.md +196 -33
- data/UNLICENSE +1 -1
- data/VERSION +1 -1
- data/bin/sxp2json +2 -2
- data/bin/sxp2rdf +2 -2
- data/bin/sxp2xml +2 -2
- data/bin/sxp2yaml +2 -2
- data/lib/sxp/extensions.rb +320 -4
- data/lib/sxp/generator.rb +31 -8
- data/lib/sxp/pair.rb +2 -2
- data/lib/sxp/reader/basic.rb +4 -4
- data/lib/sxp/reader/common_lisp.rb +8 -5
- data/lib/sxp/reader/scheme.rb +5 -5
- data/lib/sxp/reader/sparql.rb +8 -12
- data/lib/sxp.rb +0 -15
- metadata +52 -20
- data/lib/sxp/writer.rb +0 -216
data/lib/sxp/extensions.rb
CHANGED
@@ -1,6 +1,95 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require 'bigdecimal'
|
3
|
+
require 'matrix'
|
4
|
+
require 'time'
|
5
|
+
|
6
|
+
##
|
7
|
+
# Extensions for Ruby's `Object` class.
|
8
|
+
class Object
|
9
|
+
##
|
10
|
+
# Returns the SXP representation of this object.
|
11
|
+
#
|
12
|
+
# @return [String]
|
13
|
+
def to_sxp(**options)
|
14
|
+
to_s.to_json
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
##
|
19
|
+
# Extensions for Ruby's `NilClass` class.
|
20
|
+
class NilClass
|
21
|
+
##
|
22
|
+
# Returns the SXP representation of this object.
|
23
|
+
#
|
24
|
+
# @return [String]
|
25
|
+
def to_sxp(**options)
|
26
|
+
'#n'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# Extensions for Ruby's `FalseClass` class.
|
32
|
+
class FalseClass
|
33
|
+
##
|
34
|
+
# Returns the SXP representation of this object.
|
35
|
+
#
|
36
|
+
# @return [String]
|
37
|
+
def to_sxp(**options)
|
38
|
+
'#f'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# Extensions for Ruby's `TrueClass` class.
|
44
|
+
class TrueClass
|
45
|
+
##
|
46
|
+
# Returns the SXP representation of this object.
|
47
|
+
#
|
48
|
+
# @return [String]
|
49
|
+
def to_sxp(**options)
|
50
|
+
'#t'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Extensions for Ruby's `String` class.
|
56
|
+
class String
|
57
|
+
##
|
58
|
+
# Returns the SXP representation of this object. Uses SPARQL-like escaping.
|
59
|
+
#
|
60
|
+
# @return [String]
|
61
|
+
def to_sxp(**options)
|
62
|
+
buffer = ""
|
63
|
+
each_char do |u|
|
64
|
+
buffer << case u.ord
|
65
|
+
when (0x00..0x07) then sprintf("\\u%04X", u.ord)
|
66
|
+
when (0x08) then '\b'
|
67
|
+
when (0x09) then '\t'
|
68
|
+
when (0x0A) then '\n'
|
69
|
+
when (0x0C) then '\f'
|
70
|
+
when (0x0D) then '\r'
|
71
|
+
when (0x0E..0x1F) then sprintf("\\u%04X", u.ord)
|
72
|
+
when (0x22) then '\"'
|
73
|
+
when (0x5C) then '\\\\'
|
74
|
+
when (0x7F) then sprintf("\\u%04X", u.ord)
|
75
|
+
else u.chr
|
76
|
+
end
|
77
|
+
end
|
78
|
+
'"' + buffer + '"'
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
1
82
|
##
|
2
83
|
# Extensions for Ruby's `Symbol` class.
|
3
84
|
class Symbol
|
85
|
+
##
|
86
|
+
# Returns the SXP representation of this object.
|
87
|
+
#
|
88
|
+
# @return [String]
|
89
|
+
def to_sxp(**options)
|
90
|
+
to_s
|
91
|
+
end
|
92
|
+
|
4
93
|
##
|
5
94
|
# Returns `true` if this is a keyword symbol.
|
6
95
|
#
|
@@ -10,17 +99,244 @@ class Symbol
|
|
10
99
|
end
|
11
100
|
end
|
12
101
|
|
13
|
-
|
102
|
+
##
|
103
|
+
# Extensions for Ruby's `Integer` class.
|
104
|
+
class Integer
|
105
|
+
##
|
106
|
+
# Returns the SXP representation of this object.
|
107
|
+
#
|
108
|
+
# @return [String]
|
109
|
+
def to_sxp(**options)
|
110
|
+
to_s
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
##
|
115
|
+
# Extensions for Ruby's `BigDecimal` class.
|
116
|
+
class BigDecimal
|
117
|
+
##
|
118
|
+
# Returns the SXP representation of this object.
|
119
|
+
#
|
120
|
+
# @return [String]
|
121
|
+
def to_sxp(**options)
|
122
|
+
to_f.to_s
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
##
|
127
|
+
# Extensions for Ruby's `Float` class.
|
128
|
+
class Float
|
129
|
+
##
|
130
|
+
# Returns the SXP representation of this object.
|
131
|
+
#
|
132
|
+
# @return [String]
|
133
|
+
def to_sxp(**options)
|
134
|
+
case
|
135
|
+
when nan? then 'nan.0'
|
136
|
+
when infinite? then (infinite? > 0 ? '+inf.0' : '-inf.0')
|
137
|
+
else to_s
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
##
|
143
|
+
# Extensions for Ruby's `Array` class.
|
144
|
+
class Array
|
145
|
+
##
|
146
|
+
# Returns the SXP representation of this object.
|
147
|
+
#
|
148
|
+
# @return [String]
|
149
|
+
def to_sxp()
|
150
|
+
'(' << map { |x| x.to_sxp(**options) }.join(' ') << ')'
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
##
|
155
|
+
# Extensions for Ruby's `Vector` class.
|
156
|
+
class Vector
|
157
|
+
##
|
158
|
+
# Returns the SXP representation of this object.
|
159
|
+
#
|
160
|
+
# @return [String]
|
161
|
+
def to_sxp(**options)
|
162
|
+
'#(' << to_a.map { |x| x.to_sxp(**options) }.join(' ') << ')'
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
##
|
167
|
+
# Extensions for Ruby's `Hash` class.
|
168
|
+
class Hash
|
169
|
+
##
|
170
|
+
# Returns the SXP representation of this object.
|
171
|
+
#
|
172
|
+
# @return [String]
|
173
|
+
def to_sxp(**options)
|
174
|
+
to_a.to_sxp(**options)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
##
|
179
|
+
# Extensions for Ruby's `Time` class.
|
180
|
+
class Time
|
181
|
+
##
|
182
|
+
# Returns the SXP representation of this object.
|
183
|
+
#
|
184
|
+
# @return [String]
|
185
|
+
def to_sxp(**options)
|
186
|
+
'#@' << (respond_to?(:xmlschema) ? xmlschema : to_i).to_s
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
##
|
191
|
+
# Extensions for Ruby's `Regexp` class.
|
192
|
+
class Regexp
|
193
|
+
##
|
194
|
+
# Returns the SXP representation of this object.
|
195
|
+
#
|
196
|
+
# @return [String]
|
197
|
+
def to_sxp(**options)
|
198
|
+
'#' << inspect
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
14
202
|
begin
|
15
|
-
require 'rdf'
|
203
|
+
require 'rdf' # For SPARQL/RDF
|
16
204
|
|
17
205
|
##
|
18
|
-
# Extensions for
|
206
|
+
# Extensions for Ruby's `Array` class.
|
207
|
+
# These extensions depend on RDF being loaded
|
208
|
+
class Array
|
209
|
+
##
|
210
|
+
# Returns the SXP representation of this object.
|
211
|
+
#
|
212
|
+
# If array is of the form `[:base, uri, ..]`, the base_uri is taken from the second value
|
213
|
+
#
|
214
|
+
# If array is of the form `[:prefix, [..], ..]`, prefixes are taken from the second value
|
215
|
+
#
|
216
|
+
# Prefixes always are terminated by a ':'
|
217
|
+
#
|
218
|
+
# @param [Hash{Symbol => RDF::URI}] prefixes(nil)
|
219
|
+
# @param [RDF::URI] base_uri(nil)
|
220
|
+
# @return [String]
|
221
|
+
def to_sxp(prefixes: nil, base_uri: nil, **options)
|
222
|
+
if self.first == :base && self.length == 3 && self[1].is_a?(RDF::URI)
|
223
|
+
base_uri = self[1]
|
224
|
+
'(' << (
|
225
|
+
self[0,2].map(&:to_sxp) <<
|
226
|
+
self.last.to_sxp(prefixes: prefixes, base_uri: base_uri, **options)
|
227
|
+
).join(' ') << ')'
|
228
|
+
elsif self.first == :prefix && self.length == 3 && self[1].is_a?(Array)
|
229
|
+
prefixes = prefixes ? prefixes.dup : {}
|
230
|
+
self[1].each do |defn|
|
231
|
+
prefixes[defn.first.to_s.chomp(':').to_sym] = RDF::URI(defn.last) if
|
232
|
+
defn.is_a?(Array) && defn.length == 2
|
233
|
+
end
|
234
|
+
pfx_sxp = self[1].map {|(p,s)|["#{p.to_s.chomp(':')}:".to_sym, RDF::URI(s)]}.to_sxp
|
235
|
+
'(' << [
|
236
|
+
:prefix,
|
237
|
+
pfx_sxp,
|
238
|
+
self.last.to_sxp(prefixes: prefixes, base_uri: base_uri, **options)
|
239
|
+
].join(' ') << ')'
|
240
|
+
else
|
241
|
+
'(' << map { |x| x.to_sxp(prefixes: prefixes, base_uri: base_uri, **options) }.join(' ') << ')'
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
19
246
|
class RDF::URI
|
247
|
+
##
|
248
|
+
# Returns the SXP representation of this URI. Uses Lexical representation, if set, otherwise, any PName match, otherwise, the relativized version of the URI if a base_uri is given, otherwise just the URI.
|
249
|
+
#
|
250
|
+
# @param [Hash{Symbol => RDF::URI}] prefixes(nil)
|
251
|
+
# @param [RDF::URI] base_uri(nil)
|
252
|
+
# @return [String]
|
253
|
+
def to_sxp(prefixes: nil, base_uri: nil, **options)
|
254
|
+
return lexical if lexical
|
255
|
+
pn = pname(prefixes: prefixes || {})
|
256
|
+
return pn unless to_s == pn
|
257
|
+
md = self == base_uri ? '' : self.relativize(base_uri)
|
258
|
+
"<#{md}>"
|
259
|
+
end
|
260
|
+
|
20
261
|
# Original lexical value of this URI to allow for round-trip serialization.
|
21
262
|
def lexical=(value); @lexical = value; end
|
22
263
|
def lexical; @lexical; end
|
23
264
|
end
|
265
|
+
|
266
|
+
class RDF::Node
|
267
|
+
##
|
268
|
+
# Returns the SXP representation of this object.
|
269
|
+
#
|
270
|
+
# @return [String]
|
271
|
+
def to_sxp(**options)
|
272
|
+
to_s
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
class RDF::Literal
|
277
|
+
##
|
278
|
+
# Returns the SXP representation of a Literal.
|
279
|
+
#
|
280
|
+
# @return [String]
|
281
|
+
def to_sxp(**options)
|
282
|
+
case datatype
|
283
|
+
when RDF::XSD.boolean, RDF::XSD.integer, RDF::XSD.double, RDF::XSD.decimal
|
284
|
+
# Retain stated lexical form if possible
|
285
|
+
valid? ? to_s : object.to_sxp(**options)
|
286
|
+
else
|
287
|
+
text = value.to_sxp
|
288
|
+
text << "@#{language}" if self.has_language?
|
289
|
+
text << "^^#{datatype.to_sxp(**options)}" if self.has_datatype?
|
290
|
+
text
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
class Double
|
295
|
+
##
|
296
|
+
# Returns the SXP representation of this object.
|
297
|
+
#
|
298
|
+
# @return [String]
|
299
|
+
def to_sxp(**options)
|
300
|
+
case
|
301
|
+
when nan? then 'nan.0'
|
302
|
+
when infinite? then (infinite? > 0 ? '+inf.0' : '-inf.0')
|
303
|
+
else canonicalize.to_s.downcase
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
class RDF::Query
|
310
|
+
# Transform Query into an Array form of an SXP
|
311
|
+
#
|
312
|
+
# If Query is named, it's treated as a GroupGraphPattern, otherwise, a BGP
|
313
|
+
#
|
314
|
+
# @return [Array]
|
315
|
+
def to_sxp(**options)
|
316
|
+
res = [:bgp] + patterns
|
317
|
+
(named? ? [:graph, graph_name, res] : res).to_sxp(**options)
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
class RDF::Query::Pattern
|
322
|
+
# Transform Query Pattern into an SXP
|
323
|
+
#
|
324
|
+
# @return [String]
|
325
|
+
def to_sxp(**options)
|
326
|
+
[:triple, subject, predicate, object].to_sxp(**options)
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
class RDF::Query::Variable
|
331
|
+
##
|
332
|
+
# Transform Query variable into an SXP.
|
333
|
+
#
|
334
|
+
# @return [String]
|
335
|
+
def to_sxp(**options)
|
336
|
+
prefix = distinguished? ? (existential? ? '$' : '?') : (existential? ? '$$' : '??')
|
337
|
+
unbound? ? "#{prefix}#{name}".to_sym.to_sxp : ["#{prefix}#{name}".to_sym, value].to_sxp
|
338
|
+
end
|
339
|
+
end
|
24
340
|
rescue LoadError
|
25
|
-
# Ignore
|
341
|
+
# Ignore if RDF not loaded
|
26
342
|
end
|
data/lib/sxp/generator.rb
CHANGED
@@ -16,18 +16,41 @@ module SXP
|
|
16
16
|
|
17
17
|
##
|
18
18
|
# @param [Object] obj
|
19
|
-
|
19
|
+
# @param [Integer] indent
|
20
|
+
# @param [Hash{Symbol => RDF::URI}] prefixes (nil)
|
21
|
+
# @param [RDF::URI] base_uri (nil)
|
22
|
+
def initialize(obj, indent, prefixes: nil, base_uri: nil)
|
20
23
|
@indent = indent
|
21
24
|
@elements = []
|
25
|
+
@prefixes = prefixes
|
26
|
+
@base_uri = base_uri
|
22
27
|
if obj.is_a?(Array)
|
23
|
-
|
28
|
+
# If this is a base or prefix element, update our representations
|
29
|
+
if obj.first == :base && obj.length == 3 && obj[1].is_a?(RDF::URI)
|
30
|
+
base_uri = obj[1]
|
31
|
+
@elements << Block.new(:base, indent + 1)
|
32
|
+
@elements << Block.new(obj[1], indent + 1)
|
33
|
+
@elements << Block.new(obj.last, indent + 1, prefixes: prefixes, base_uri: base_uri)
|
34
|
+
elsif obj.first == :prefix && obj.length == 3 && obj[1].is_a?(Array)
|
35
|
+
prefixes = prefixes ? prefixes.dup : {}
|
36
|
+
obj[1].each do |defn|
|
37
|
+
prefixes[defn.first.to_s.chomp(':').to_sym] = RDF::URI(defn.last) if defn.is_a?(Array) && defn.length == 2
|
38
|
+
end
|
39
|
+
@elements << Block.new(:prefix, indent + 1)
|
40
|
+
@elements << Block.new(obj[1], indent + 1)
|
41
|
+
@elements << Block.new(obj.last, indent + 1, prefixes: prefixes, base_uri: base_uri)
|
42
|
+
else
|
43
|
+
obj.compact.each do |o|
|
44
|
+
@elements << Block.new(o, indent + 1, prefixes: prefixes, base_uri: base_uri)
|
45
|
+
end
|
46
|
+
end
|
24
47
|
else
|
25
48
|
@elements = obj
|
26
49
|
end
|
27
50
|
end
|
28
51
|
|
29
52
|
##
|
30
|
-
#
|
53
|
+
# Aggregate length over each element accounting for spaces
|
31
54
|
#
|
32
55
|
# @return [Integer]
|
33
56
|
# If indent is not not nil, returns zero
|
@@ -35,7 +58,7 @@ module SXP
|
|
35
58
|
if @elements.is_a?(Array)
|
36
59
|
@elements.map(&:length).inject(:+).to_i + @elements.length - 1
|
37
60
|
else
|
38
|
-
@elements.to_sxp.length
|
61
|
+
@elements.to_sxp(prefixes: @prefixes, base_uri: @base_uri).length
|
39
62
|
end
|
40
63
|
end
|
41
64
|
|
@@ -44,8 +67,8 @@ module SXP
|
|
44
67
|
# This should only be called on a block when
|
45
68
|
# no indentation is to be applied
|
46
69
|
# @return [String]
|
47
|
-
def to_sxp
|
48
|
-
@elements.to_sxp
|
70
|
+
def to_sxp(prefixes: nil, base_uri: nil)
|
71
|
+
@elements.to_sxp(prefixes: prefixes || @prefixes, base_uri: base_uri || @base_uri)
|
49
72
|
end
|
50
73
|
|
51
74
|
##
|
@@ -67,7 +90,7 @@ module SXP
|
|
67
90
|
first, *elems = @elements
|
68
91
|
unless first.sxp?
|
69
92
|
# It's atomic, write out after paren
|
70
|
-
buffer += first.to_sxp + "\n"
|
93
|
+
buffer += first.to_sxp(prefixes: @prefixes, base_uri: @base_uri) + "\n"
|
71
94
|
else
|
72
95
|
buffer += "\n"
|
73
96
|
elems.unshift(first)
|
@@ -77,7 +100,7 @@ module SXP
|
|
77
100
|
end
|
78
101
|
buffer += do_indent + ")\n"
|
79
102
|
else
|
80
|
-
buffer += do_indent + @elements.to_sxp + "\n"
|
103
|
+
buffer += do_indent + @elements.to_sxp(prefixes: @prefixes, base_uri: @base_uri) + "\n"
|
81
104
|
end
|
82
105
|
buffer
|
83
106
|
end
|
data/lib/sxp/pair.rb
CHANGED
@@ -27,7 +27,7 @@ module SXP
|
|
27
27
|
# Returns `true` if the tail of this pair is not `nil` or another pair.
|
28
28
|
#
|
29
29
|
# @return [Boolean]
|
30
|
-
# @see
|
30
|
+
# @see https:/srfi.schemers.org/srfi-1/srfi-1.html#ImproperLists
|
31
31
|
def dotted?
|
32
32
|
!proper?
|
33
33
|
end
|
@@ -36,7 +36,7 @@ module SXP
|
|
36
36
|
# Returns `true` if the tail of this pair is `nil` or another pair.
|
37
37
|
#
|
38
38
|
# @return [Boolean]
|
39
|
-
# @see
|
39
|
+
# @see https:/srfi.schemers.org/srfi-1/srfi-1.html#ImproperLists
|
40
40
|
def proper?
|
41
41
|
tail.nil? || tail.is_a?(Pair)
|
42
42
|
end
|
data/lib/sxp/reader/basic.rb
CHANGED
@@ -35,7 +35,7 @@ module SXP; class Reader
|
|
35
35
|
##
|
36
36
|
# @return [String]
|
37
37
|
def read_string
|
38
|
-
buffer =
|
38
|
+
buffer = ""
|
39
39
|
skip_char # '"'
|
40
40
|
until peek_char == ?" #"
|
41
41
|
buffer <<
|
@@ -57,8 +57,8 @@ module SXP; class Reader
|
|
57
57
|
when ?n then ?\n
|
58
58
|
when ?r then ?\r
|
59
59
|
when ?t then ?\t
|
60
|
-
when ?u then read_chars(4).to_i(16).chr
|
61
|
-
when ?U then read_chars(8).to_i(16).chr
|
60
|
+
when ?u then read_chars(4).to_i(16).chr(Encoding::UTF_8)
|
61
|
+
when ?U then read_chars(8).to_i(16).chr(Encoding::UTF_8)
|
62
62
|
when ?" then char #"
|
63
63
|
when ?\\ then char
|
64
64
|
else char
|
@@ -69,7 +69,7 @@ module SXP; class Reader
|
|
69
69
|
# @return [String]
|
70
70
|
def read_literal
|
71
71
|
grammar = self.class.const_get(:ATOM)
|
72
|
-
buffer =
|
72
|
+
buffer = ""
|
73
73
|
buffer << read_char while !eof? && peek_char.chr =~ grammar
|
74
74
|
buffer
|
75
75
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
+
require 'matrix'
|
3
|
+
|
2
4
|
module SXP; class Reader
|
3
5
|
##
|
4
6
|
# A Common Lisp S-expressions parser.
|
5
7
|
#
|
6
|
-
# @see
|
8
|
+
# @see https:/www.cs.cmu.edu/Groups/AI/html/cltl/clm/node14.html
|
7
9
|
class CommonLisp < Basic
|
8
10
|
OPTIONS = {nil: nil, t: true, quote: :quote, function: :function}
|
9
11
|
|
@@ -16,7 +18,7 @@ module SXP; class Reader
|
|
16
18
|
|
17
19
|
# Escape characters, used in the form `#\Backspace`. Case is treated
|
18
20
|
# insensitively
|
19
|
-
# @see
|
21
|
+
# @see https:/www.cs.cmu.edu/Groups/AI/html/cltl/clm/node22.html
|
20
22
|
CHARACTERS = {
|
21
23
|
'newline' => "\n",
|
22
24
|
'space' => " ",
|
@@ -70,7 +72,7 @@ module SXP; class Reader
|
|
70
72
|
##
|
71
73
|
# @return [Symbol]
|
72
74
|
def read_symbol(delimiter = nil)
|
73
|
-
buffer =
|
75
|
+
buffer = ""
|
74
76
|
skip_char # '|'
|
75
77
|
until delimiter === peek_char
|
76
78
|
buffer <<
|
@@ -88,7 +90,8 @@ module SXP; class Reader
|
|
88
90
|
#
|
89
91
|
# @return [Array]
|
90
92
|
def read_vector
|
91
|
-
|
93
|
+
list = read_list(')')
|
94
|
+
Vector.[](*list)
|
92
95
|
end
|
93
96
|
|
94
97
|
##
|
@@ -114,7 +117,7 @@ module SXP; class Reader
|
|
114
117
|
# eroneously read characters back in the input stream
|
115
118
|
#
|
116
119
|
# @return [String]
|
117
|
-
# @see
|
120
|
+
# @see https:/www.cs.cmu.edu/Groups/AI/html/cltl/clm/node22.html
|
118
121
|
def read_character
|
119
122
|
lit = read_literal
|
120
123
|
|
data/lib/sxp/reader/scheme.rb
CHANGED
@@ -3,7 +3,7 @@ module SXP; class Reader
|
|
3
3
|
##
|
4
4
|
# A Scheme R4RS S-expressions parser.
|
5
5
|
#
|
6
|
-
# @see
|
6
|
+
# @see https:/people.csail.mit.edu/jaffer/r4rs_9.html#SEC65
|
7
7
|
class Scheme < Extended
|
8
8
|
DECIMAL = /^[+-]?(\d*)?\.\d*$/
|
9
9
|
INTEGER_BASE_2 = /^[+-]?[01]+$/
|
@@ -14,7 +14,7 @@ module SXP; class Reader
|
|
14
14
|
|
15
15
|
# Escape characters, used in the form `#\newline`. Case is treated
|
16
16
|
# insensitively
|
17
|
-
# @see
|
17
|
+
# @see https:/people.csail.mit.edu/jaffer/r4rs_9.html#SEC65
|
18
18
|
CHARACTERS = {
|
19
19
|
'newline' => "\n",
|
20
20
|
'space' => " ",
|
@@ -64,8 +64,8 @@ module SXP; class Reader
|
|
64
64
|
when ?d, ?D then read_integer(10)
|
65
65
|
when ?x, ?X then read_integer(16)
|
66
66
|
when ?\\ then read_character
|
67
|
-
when ?; then skip
|
68
|
-
when ?! then skip_line;
|
67
|
+
when ?; then skip # comment character
|
68
|
+
when ?! then skip_line; skip # shebang
|
69
69
|
else raise Error, "invalid sharp-sign read syntax: ##{char.chr}"
|
70
70
|
end
|
71
71
|
end
|
@@ -76,7 +76,7 @@ module SXP; class Reader
|
|
76
76
|
# eroneously read characters back in the input stream
|
77
77
|
#
|
78
78
|
# @return [String]
|
79
|
-
# @see
|
79
|
+
# @see https:/people.csail.mit.edu/jaffer/r4rs_9.html#SEC65
|
80
80
|
def read_character
|
81
81
|
lit = read_literal
|
82
82
|
|
data/lib/sxp/reader/sparql.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
require 'rdf' # @see
|
2
|
+
require 'rdf' # @see https:/rubygems.org/gems/rdf
|
3
3
|
|
4
4
|
module SXP; class Reader
|
5
5
|
##
|
6
6
|
# A SPARQL Syntax Expressions (SSE) parser.
|
7
7
|
#
|
8
|
-
# Requires [RDF.rb](
|
8
|
+
# Requires [RDF.rb](https:/rubygems.org/gems/rdf/).
|
9
9
|
#
|
10
|
-
# @see
|
10
|
+
# @see https:/openjena.org/wiki/SSE
|
11
11
|
class SPARQL < Extended
|
12
12
|
# Alias for rdf:type
|
13
13
|
A = /^a$/
|
@@ -83,12 +83,12 @@ module SXP; class Reader
|
|
83
83
|
end
|
84
84
|
|
85
85
|
##
|
86
|
-
# Reads SSE Tokens, including
|
86
|
+
# Reads SSE Tokens, including `RDF::Literal`, `RDF::URI` and `RDF::Node`.
|
87
87
|
#
|
88
88
|
# Performs forward reference for prefix and base URI representations and saves in
|
89
89
|
# {#base_uri} and {#prefixes} accessors.
|
90
90
|
#
|
91
|
-
# Transforms tokens matching a {PNAME} pattern into
|
91
|
+
# Transforms tokens matching a {PNAME} pattern into `RDF::URI` instances if a match is
|
92
92
|
# found with a previously identified {PREFIX}.
|
93
93
|
# @return [Object]
|
94
94
|
def read_token
|
@@ -129,8 +129,6 @@ module SXP; class Reader
|
|
129
129
|
uri = RDF::URI(base.to_s + suffix)
|
130
130
|
#STDERR.puts "read_tok lexical uri: #{uri.inspect}"
|
131
131
|
|
132
|
-
# Cause URI to be serialized as a lexical
|
133
|
-
uri.lexical = value
|
134
132
|
[:atom, uri]
|
135
133
|
else
|
136
134
|
tok
|
@@ -173,7 +171,7 @@ module SXP; class Reader
|
|
173
171
|
#
|
174
172
|
# @return [RDF::URI]
|
175
173
|
def read_rdf_uri
|
176
|
-
buffer =
|
174
|
+
buffer = ""
|
177
175
|
skip_char # '<'
|
178
176
|
return :< if (char = peek_char).nil? || char.chr !~ ATOM # FIXME: nasty special case for the '< symbol
|
179
177
|
return :<= if peek_char.chr.eql?(?=.chr) && read_char # FIXME: nasty special case for the '<= symbol
|
@@ -184,9 +182,7 @@ module SXP; class Reader
|
|
184
182
|
|
185
183
|
# If we have a base URI, use that when constructing a new URI
|
186
184
|
uri = if self.base_uri && RDF::URI(buffer).relative?
|
187
|
-
|
188
|
-
u.lexical = "<#{buffer}>" unless u.to_s == buffer # So that it can be re-serialized properly
|
189
|
-
u
|
185
|
+
self.base_uri.join(buffer)
|
190
186
|
else
|
191
187
|
RDF::URI(buffer)
|
192
188
|
end
|
@@ -211,7 +207,7 @@ module SXP; class Reader
|
|
211
207
|
#
|
212
208
|
# Atoms parsed including `base`, `prefix`, `true`, `false`, numeric, BNodes and variables.
|
213
209
|
#
|
214
|
-
# Creates
|
210
|
+
# Creates `RDF::Literal`, `RDF::Node`, or `RDF::Query::Variable` instances where appropriate.
|
215
211
|
#
|
216
212
|
# @return [Object]
|
217
213
|
def read_atom
|
data/lib/sxp.rb
CHANGED
@@ -1,23 +1,8 @@
|
|
1
1
|
require 'rational'
|
2
2
|
require 'stringio'
|
3
3
|
|
4
|
-
if RUBY_VERSION < '1.8.7'
|
5
|
-
# @see http://rubygems.org/gems/backports
|
6
|
-
begin
|
7
|
-
require 'backports/1.8.7'
|
8
|
-
rescue LoadError
|
9
|
-
begin
|
10
|
-
require 'rubygems'
|
11
|
-
require 'backports/1.8.7'
|
12
|
-
rescue LoadError
|
13
|
-
abort "SXP.rb requires Ruby 1.8.7 or the Backports gem (hint: `gem install backports')."
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
4
|
require 'sxp/version'
|
19
5
|
require 'sxp/extensions'
|
20
|
-
require 'sxp/writer'
|
21
6
|
|
22
7
|
module SXP
|
23
8
|
autoload :Pair, 'sxp/pair'
|