reddy 0.1.0
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/HACKNOTES +2 -0
- data/History.txt +3 -0
- data/Manifest.txt +80 -0
- data/README.rdoc +48 -0
- data/README.txt +62 -0
- data/Rakefile +67 -0
- data/lib/reddy.rb +8 -0
- data/lib/reddy/bnode.rb +70 -0
- data/lib/reddy/exceptions/about_each_exception.rb +2 -0
- data/lib/reddy/exceptions/uri_relative_exception.rb +2 -0
- data/lib/reddy/graph.rb +182 -0
- data/lib/reddy/libxml_hacks.rb +6 -0
- data/lib/reddy/literal.rb +211 -0
- data/lib/reddy/n3_grammar.treetop +129 -0
- data/lib/reddy/n3parser.rb +145 -0
- data/lib/reddy/namespace.rb +73 -0
- data/lib/reddy/rdfaparser.rb +63 -0
- data/lib/reddy/rdfxmlparser.rb +254 -0
- data/lib/reddy/rexml_hacks.rb +97 -0
- data/lib/reddy/triple.rb +95 -0
- data/lib/reddy/uriref.rb +66 -0
- data/reddy.gemspec +50 -0
- data/spec/bnode_spec.rb +29 -0
- data/spec/graph_spec.rb +138 -0
- data/spec/literal_spec.rb +142 -0
- data/spec/n3parser_spec.rb +86 -0
- data/spec/namespaces_spec.rb +44 -0
- data/spec/parser_spec.rb +391 -0
- data/spec/rdfa_parser_spec.rb +28 -0
- data/spec/rexml_hacks_spec.rb +99 -0
- data/spec/triple_spec.rb +108 -0
- data/spec/uriref_spec.rb +96 -0
- data/test/longtests_spec.rb +25 -0
- data/test/n3_tests/lcsh/sh85062913.n3 +41 -0
- data/test/n3_tests/lcsh/sh85062913.nt +21 -0
- data/test/n3_tests/lcsh/sh85082139.n3 +157 -0
- data/test/n3_tests/lcsh/sh85082139.nt +79 -0
- data/test/n3_tests/lcsh/sh85118553.n3 +123 -0
- data/test/n3_tests/lcsh/sh85118553.nt +63 -0
- data/test/n3_tests/misc/on_now-01.n3 +30 -0
- data/test/n3_tests/misc/on_now-01.nt +15 -0
- data/test/n3_tests/n3p/simple-01.n3 +1 -0
- data/test/n3_tests/n3p/simple-01.nt +0 -0
- data/test/n3_tests/n3p/simple-02.n3 +4 -0
- data/test/n3_tests/n3p/simple-02.nt +0 -0
- data/test/n3_tests/n3p/simple-03.n3 +5 -0
- data/test/n3_tests/n3p/simple-03.nt +1 -0
- data/test/n3_tests/n3p/simple-04.n3 +6 -0
- data/test/n3_tests/n3p/simple-04.nt +3 -0
- data/test/n3_tests/n3p/simple-05.n3 +7 -0
- data/test/n3_tests/n3p/simple-05.nt +2 -0
- data/test/n3_tests/n3p/simple-06.n3 +6 -0
- data/test/n3_tests/n3p/simple-06.nt +4 -0
- data/test/n3_tests/n3p/simple-07.n3 +7 -0
- data/test/n3_tests/n3p/simple-07.nt +6 -0
- data/test/perf_test/test.rb +11 -0
- data/test/perf_test/tommorris.rdf +2267 -0
- data/test/rdf_tests/cc197bad-dc9c-440d-a5b5-d52ba2e14234.nt +24 -0
- data/test/rdf_tests/cc197bad-dc9c-440d-a5b5-d52ba2e14234.rdf +46 -0
- data/test/rdf_tests/tm_001.nt +1 -0
- data/test/rdf_tests/tm_001.rdf +7 -0
- data/test/rdf_tests/xml-literal-mixed.nt +7 -0
- data/test/rdf_tests/xml-literal-mixed.rdf +15 -0
- data/test/ruby_fundamentals.spec.rb +17 -0
- data/test/test_helper.rb +2 -0
- data/test/test_reddy.rb +11 -0
- data/test/test_uris.rb +13 -0
- data/test/xml.rdf +6 -0
- metadata +198 -0
@@ -0,0 +1,211 @@
|
|
1
|
+
module Reddy
|
2
|
+
class Literal
|
3
|
+
class Encoding
|
4
|
+
def self.integer
|
5
|
+
@integer ||= coerce "http://www.w3.org/2001/XMLSchema#int"
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.float
|
9
|
+
@float ||= coerce "http://www.w3.org/2001/XMLSchema#float"
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.string
|
13
|
+
@string ||= coerce "http://www.w3.org/2001/XMLSchema#string"
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.coerce(string_or_nil)
|
17
|
+
if string_or_nil.nil? || string_or_nil == ''
|
18
|
+
the_null_encoding
|
19
|
+
else
|
20
|
+
new string_or_nil
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def inspect
|
25
|
+
to_s()
|
26
|
+
end
|
27
|
+
|
28
|
+
class Null
|
29
|
+
def to_s
|
30
|
+
''
|
31
|
+
end
|
32
|
+
|
33
|
+
def format_as_n3(content)
|
34
|
+
"\"#{content}\""
|
35
|
+
end
|
36
|
+
|
37
|
+
def format_as_trix(content)
|
38
|
+
"<plainLiteral>#{content}</plainLiteral>"
|
39
|
+
end
|
40
|
+
|
41
|
+
def inspect
|
42
|
+
"<theReddy::TypeLiteral::Encoding::Null>"
|
43
|
+
end
|
44
|
+
|
45
|
+
def xmlliteral?
|
46
|
+
false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.the_null_encoding
|
51
|
+
@the_null_encoding ||= Null.new
|
52
|
+
end
|
53
|
+
|
54
|
+
attr_reader :value
|
55
|
+
def initialize(value)
|
56
|
+
@value = value
|
57
|
+
end
|
58
|
+
|
59
|
+
def should_quote?
|
60
|
+
@value != self.class.integer.to_s
|
61
|
+
end
|
62
|
+
|
63
|
+
def ==(other)
|
64
|
+
case other
|
65
|
+
when String
|
66
|
+
other == @value
|
67
|
+
when self.class
|
68
|
+
other.value == @value
|
69
|
+
else
|
70
|
+
false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def hash
|
75
|
+
@value.hash
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_s
|
79
|
+
@value
|
80
|
+
end
|
81
|
+
|
82
|
+
def format_as_n3(content)
|
83
|
+
quoted_content = should_quote? ? "\"#{content}\"" : content
|
84
|
+
"#{quoted_content}^^<#{value}>"
|
85
|
+
end
|
86
|
+
|
87
|
+
def format_as_trix(value)
|
88
|
+
"<typedLiteral datatype=\"#{@value}\">#{value}</typedLiteral>"
|
89
|
+
end
|
90
|
+
|
91
|
+
def xmlliteral?
|
92
|
+
@value == "http://www.w3.org/1999/02/22-rdf-syntax-ns#XMLLiteral"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
class Language < Encoding
|
97
|
+
def initialize(string)
|
98
|
+
@value = string.downcase
|
99
|
+
end
|
100
|
+
|
101
|
+
def clean(string)
|
102
|
+
case string
|
103
|
+
when "eng"; "en"
|
104
|
+
else string
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def format_as_n3(contents)
|
109
|
+
"\"#{contents}\"@#{@value}"
|
110
|
+
end
|
111
|
+
|
112
|
+
def format_as_trix(contents)
|
113
|
+
"<plainLiteral xml:lang=\"#{@value}\">#{contents}</plainLiteral>"
|
114
|
+
end
|
115
|
+
|
116
|
+
def == (other)
|
117
|
+
case other
|
118
|
+
when String
|
119
|
+
other == @value
|
120
|
+
when self.class
|
121
|
+
other.value == @value
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
attr_accessor :contents, :encoding
|
127
|
+
def initialize(contents, encoding)
|
128
|
+
@contents = contents.to_s
|
129
|
+
unless encoding.is_a?(Encoding) || encoding.is_a?(Encoding::Null)
|
130
|
+
raise TypeError, "#{encoding.inspect} should be an instance of Encoding"
|
131
|
+
end
|
132
|
+
@encoding = encoding
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.untyped(contents, language = nil)
|
136
|
+
new(contents, Language.coerce(language))
|
137
|
+
end
|
138
|
+
|
139
|
+
def self.typed(contents, encoding)
|
140
|
+
new(contents, Encoding.coerce(encoding))
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.build_from(object)
|
144
|
+
new(object.to_s, infer_encoding_for(object))
|
145
|
+
end
|
146
|
+
|
147
|
+
def self.infer_encoding_for(object)
|
148
|
+
case object
|
149
|
+
when Integer; Encoding.integer
|
150
|
+
when Float; Encoding.float
|
151
|
+
else Encoding.string
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
require 'whatlanguage'
|
156
|
+
unless WhatLanguage.nil?
|
157
|
+
def self.infer_language_for(object)
|
158
|
+
inferred_lang = object.language
|
159
|
+
case inferred_lang
|
160
|
+
when :dutch; Language.new("nl")
|
161
|
+
when :english; Language.new("en")
|
162
|
+
when :farsi; Langauge.new("fa")
|
163
|
+
when :french; Language.new("fr")
|
164
|
+
when :german; Language.new("de")
|
165
|
+
when :pinyin; Language.new("zh-CN")
|
166
|
+
when :portugese; Language.new("pt")
|
167
|
+
when :russian; Language.new("ru")
|
168
|
+
when :spanish; Language.new("es")
|
169
|
+
when :swedish; Language.new("sv")
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def self.build_from_language(object)
|
174
|
+
new(object.to_s, infer_language_for(object))
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
class << self
|
179
|
+
protected :new
|
180
|
+
end
|
181
|
+
|
182
|
+
def == (obj)
|
183
|
+
obj.is_a?(self.class) && obj.contents == @contents && obj.encoding == @encoding
|
184
|
+
end
|
185
|
+
|
186
|
+
def to_n3
|
187
|
+
encoding.format_as_n3(@contents)
|
188
|
+
end
|
189
|
+
|
190
|
+
## alias_method breaks subclasses! Beware! Here be dragons!
|
191
|
+
def to_ntriples
|
192
|
+
to_n3
|
193
|
+
end
|
194
|
+
|
195
|
+
def to_trix
|
196
|
+
encoding.format_as_trix(@contents)
|
197
|
+
end
|
198
|
+
|
199
|
+
def xmlliteral?
|
200
|
+
encoding.xmlliteral?
|
201
|
+
end
|
202
|
+
|
203
|
+
def to_s
|
204
|
+
@contents.to_s
|
205
|
+
end
|
206
|
+
|
207
|
+
def lang
|
208
|
+
encoding.is_a?(Language) ? encoding : nil
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
grammar N3Grammer
|
2
|
+
rule document
|
3
|
+
statements
|
4
|
+
end
|
5
|
+
|
6
|
+
rule statements
|
7
|
+
(space / (statement / directive) space* ('.' space*)? )*
|
8
|
+
end
|
9
|
+
|
10
|
+
rule statement
|
11
|
+
subject space+ property_list
|
12
|
+
end
|
13
|
+
|
14
|
+
rule subject
|
15
|
+
node
|
16
|
+
end
|
17
|
+
|
18
|
+
rule verb
|
19
|
+
">-" prop "->" # has xxx of
|
20
|
+
/ "<-" prop "<-" # is xxx of
|
21
|
+
# / # / operator # has operator:xxx of??? NOT IMPLMENTED
|
22
|
+
/ prop # has xxx of -- shorthand
|
23
|
+
# / "has" prop # has xxx of
|
24
|
+
# / "is" prop "of" # is xxx of
|
25
|
+
/ "a" # has rdf:type of
|
26
|
+
# / "=" # has daml:equivaent of
|
27
|
+
end
|
28
|
+
|
29
|
+
rule prop
|
30
|
+
node
|
31
|
+
end
|
32
|
+
|
33
|
+
rule node
|
34
|
+
uri_ref2 / anonnode / 'this'
|
35
|
+
end
|
36
|
+
|
37
|
+
rule anonnode
|
38
|
+
"[" space* property_list space* "]" # something which ...
|
39
|
+
/ "{" statementlist "}" # the statementlist itself as a resource
|
40
|
+
/ "(" nodelist ")" {
|
41
|
+
def anonnode; true; end
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
rule property_list
|
46
|
+
verb space+ object_list space* ";" space+ property_list
|
47
|
+
/ verb space+ object_list
|
48
|
+
/ ":-" anonnode #to allow two anonymous forms to be given eg [ a :Truth; :- { :sky :color :blue } ] )
|
49
|
+
/ ":-" anonnode ";" property_list
|
50
|
+
/ '.'
|
51
|
+
end
|
52
|
+
|
53
|
+
rule object_list
|
54
|
+
object "," space* object_list / object
|
55
|
+
end
|
56
|
+
|
57
|
+
rule directive
|
58
|
+
'@prefix' space+ nprefix:nprefix? ':' space+ uri_ref2:uri_ref2 {
|
59
|
+
def directive; true; end
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
rule uri_ref2
|
64
|
+
qname / "<" uri:URI_Reference ">"
|
65
|
+
end
|
66
|
+
|
67
|
+
rule qname
|
68
|
+
nprefix ":" localname / ':' localname
|
69
|
+
end
|
70
|
+
|
71
|
+
rule object
|
72
|
+
subject / literal
|
73
|
+
end
|
74
|
+
|
75
|
+
rule literal
|
76
|
+
(string1 / string2) ("^^<" uri:URI_Reference ">" / "@" [a-z]+ )?
|
77
|
+
end
|
78
|
+
|
79
|
+
rule localname
|
80
|
+
fragid
|
81
|
+
end
|
82
|
+
|
83
|
+
rule URI_Reference
|
84
|
+
[^{}<>]*
|
85
|
+
end
|
86
|
+
|
87
|
+
rule nprefix
|
88
|
+
((alpha / "_") alphanumeric*)
|
89
|
+
end
|
90
|
+
|
91
|
+
rule fragid
|
92
|
+
alpha alphanumeric*
|
93
|
+
end
|
94
|
+
|
95
|
+
rule alpha
|
96
|
+
[a-zA-Z]
|
97
|
+
end
|
98
|
+
|
99
|
+
rule alphanumeric
|
100
|
+
alpha / [0-9] / "_"
|
101
|
+
end
|
102
|
+
|
103
|
+
rule space
|
104
|
+
[ \t\n\r]+ / comment
|
105
|
+
end
|
106
|
+
|
107
|
+
rule comment
|
108
|
+
'#' (![\n\r] .)*
|
109
|
+
end
|
110
|
+
|
111
|
+
# " constant-value-with-escaping "
|
112
|
+
rule string1
|
113
|
+
'"' string1_char+ '"'
|
114
|
+
end
|
115
|
+
|
116
|
+
rule string1_char
|
117
|
+
!["] .
|
118
|
+
end
|
119
|
+
|
120
|
+
# """ constant value with escaping including single or double occurences of quotes and/or newlines """
|
121
|
+
rule string2
|
122
|
+
'"""' string2_char* '"""'
|
123
|
+
end
|
124
|
+
|
125
|
+
rule string2_char
|
126
|
+
!'"""' . # something like this; need to think about it some more
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'treetop'
|
2
|
+
include Reddy
|
3
|
+
|
4
|
+
Treetop.load(File.join(File.dirname(__FILE__), "n3_grammar"))
|
5
|
+
|
6
|
+
module Reddy
|
7
|
+
class N3Parser
|
8
|
+
attr_accessor :graph
|
9
|
+
|
10
|
+
##
|
11
|
+
# Creates a new parser for N3 (or Turtle).
|
12
|
+
#
|
13
|
+
# @param [String] n3_str the Notation3/Turtle string
|
14
|
+
# @param [String] uri the URI of the document
|
15
|
+
#
|
16
|
+
# @author Patrick Sinclair (metade)
|
17
|
+
def initialize(n3_str, uri=nil)
|
18
|
+
@uri = Addressable::URI.parse(uri) unless uri.nil?
|
19
|
+
parser = N3GrammerParser.new
|
20
|
+
document = parser.parse(n3_str)
|
21
|
+
if document
|
22
|
+
@graph = Graph.new
|
23
|
+
process_directives(document)
|
24
|
+
process_statements(document)
|
25
|
+
else
|
26
|
+
parser.terminal_failures.each do |tf|
|
27
|
+
puts "Expected #{tf.expected_string.inspect} (#{tf.index})- '#{n3_str[tf.index,10].inspect}'"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
def process_directives(document)
|
35
|
+
directives = document.elements.find_all { |e| e.elements.first.respond_to? :directive }
|
36
|
+
directives.map! { |d| d.elements.first }
|
37
|
+
directives.each { |d| namespace(d.uri_ref2.uri.text_value, d.nprefix.text_value) }
|
38
|
+
end
|
39
|
+
|
40
|
+
def namespace(uri, short)
|
41
|
+
short = '__local__' if short == ''
|
42
|
+
@graph.namespace(uri, short)
|
43
|
+
end
|
44
|
+
|
45
|
+
def process_statements(document)
|
46
|
+
subjects = document.elements.find_all { |e| e.elements.first.respond_to? :subject }
|
47
|
+
subjects.map! { |s| s.elements.first }
|
48
|
+
subjects.each do |s|
|
49
|
+
subject = process_node(s.subject)
|
50
|
+
properties = process_properties(s.property_list)
|
51
|
+
properties.each do |p|
|
52
|
+
predicate = process_verb(p.verb)
|
53
|
+
objects = process_objects(p.object_list)
|
54
|
+
objects.each { |object| triple(subject, predicate, object) }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def triple(subject, predicate, object)
|
60
|
+
@graph.add_triple(subject, predicate, object)
|
61
|
+
end
|
62
|
+
|
63
|
+
def process_anonnode(anonnode)
|
64
|
+
bnode = BNode.new
|
65
|
+
properties = process_properties(anonnode.property_list)
|
66
|
+
properties.each do |p|
|
67
|
+
predicate = process_node(p.verb)
|
68
|
+
objects = process_objects(p.object_list)
|
69
|
+
objects.each { |object| triple(bnode, predicate, object) }
|
70
|
+
end
|
71
|
+
bnode
|
72
|
+
end
|
73
|
+
|
74
|
+
def process_verb(verb)
|
75
|
+
return URIRef.new('http://www.w3.org/1999/02/22-rdf-syntax-ns#type') if (verb.text_value=='a')
|
76
|
+
return process_node(verb)
|
77
|
+
end
|
78
|
+
|
79
|
+
def process_node(node)
|
80
|
+
if (node.respond_to? :uri)
|
81
|
+
URIRef.new(node.uri.text_value)
|
82
|
+
else
|
83
|
+
prefix = (node.respond_to? :nprefix) ? node.nprefix.text_value : nil
|
84
|
+
localname = node.localname.text_value
|
85
|
+
build_uri(prefix, localname)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def process_properties(properties)
|
90
|
+
result = []
|
91
|
+
result << properties if (properties.respond_to? :verb)
|
92
|
+
result << process_properties(properties.property_list) if (properties.respond_to? :property_list)
|
93
|
+
result.flatten
|
94
|
+
end
|
95
|
+
|
96
|
+
def process_objects(objects)
|
97
|
+
result = []
|
98
|
+
if (objects.respond_to? :object)
|
99
|
+
result << process_object(objects.object)
|
100
|
+
else
|
101
|
+
result << process_object(objects)
|
102
|
+
end
|
103
|
+
result << process_objects(objects.object_list) if (objects.respond_to? :object_list)
|
104
|
+
result.flatten
|
105
|
+
end
|
106
|
+
|
107
|
+
def process_object(object)
|
108
|
+
if (object.respond_to? :localname or object.respond_to? :uri)
|
109
|
+
process_node(object)
|
110
|
+
elsif (object.respond_to? :property_list)
|
111
|
+
process_anonnode(object)
|
112
|
+
else
|
113
|
+
process_literal(object)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def process_literal(object)
|
118
|
+
encoding, language = nil, nil
|
119
|
+
string, type = object.elements
|
120
|
+
|
121
|
+
unless type.elements.nil?
|
122
|
+
if (type.elements[0].text_value=='@')
|
123
|
+
language = type.elements[1].text_value
|
124
|
+
else
|
125
|
+
encoding = type.elements[1].text_value
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
if (encoding.nil?)
|
130
|
+
Literal.untyped(string.elements[1].text_value, language)
|
131
|
+
else
|
132
|
+
Literal.typed(string.elements[1].text_value, encoding)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def build_uri(prefix, localname)
|
137
|
+
prefix = '__local__' if prefix.nil?
|
138
|
+
if (prefix=='_')
|
139
|
+
BNode.new(localname)
|
140
|
+
else
|
141
|
+
@graph.nsbinding[prefix].send(localname)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|