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.
Files changed (69) hide show
  1. data/HACKNOTES +2 -0
  2. data/History.txt +3 -0
  3. data/Manifest.txt +80 -0
  4. data/README.rdoc +48 -0
  5. data/README.txt +62 -0
  6. data/Rakefile +67 -0
  7. data/lib/reddy.rb +8 -0
  8. data/lib/reddy/bnode.rb +70 -0
  9. data/lib/reddy/exceptions/about_each_exception.rb +2 -0
  10. data/lib/reddy/exceptions/uri_relative_exception.rb +2 -0
  11. data/lib/reddy/graph.rb +182 -0
  12. data/lib/reddy/libxml_hacks.rb +6 -0
  13. data/lib/reddy/literal.rb +211 -0
  14. data/lib/reddy/n3_grammar.treetop +129 -0
  15. data/lib/reddy/n3parser.rb +145 -0
  16. data/lib/reddy/namespace.rb +73 -0
  17. data/lib/reddy/rdfaparser.rb +63 -0
  18. data/lib/reddy/rdfxmlparser.rb +254 -0
  19. data/lib/reddy/rexml_hacks.rb +97 -0
  20. data/lib/reddy/triple.rb +95 -0
  21. data/lib/reddy/uriref.rb +66 -0
  22. data/reddy.gemspec +50 -0
  23. data/spec/bnode_spec.rb +29 -0
  24. data/spec/graph_spec.rb +138 -0
  25. data/spec/literal_spec.rb +142 -0
  26. data/spec/n3parser_spec.rb +86 -0
  27. data/spec/namespaces_spec.rb +44 -0
  28. data/spec/parser_spec.rb +391 -0
  29. data/spec/rdfa_parser_spec.rb +28 -0
  30. data/spec/rexml_hacks_spec.rb +99 -0
  31. data/spec/triple_spec.rb +108 -0
  32. data/spec/uriref_spec.rb +96 -0
  33. data/test/longtests_spec.rb +25 -0
  34. data/test/n3_tests/lcsh/sh85062913.n3 +41 -0
  35. data/test/n3_tests/lcsh/sh85062913.nt +21 -0
  36. data/test/n3_tests/lcsh/sh85082139.n3 +157 -0
  37. data/test/n3_tests/lcsh/sh85082139.nt +79 -0
  38. data/test/n3_tests/lcsh/sh85118553.n3 +123 -0
  39. data/test/n3_tests/lcsh/sh85118553.nt +63 -0
  40. data/test/n3_tests/misc/on_now-01.n3 +30 -0
  41. data/test/n3_tests/misc/on_now-01.nt +15 -0
  42. data/test/n3_tests/n3p/simple-01.n3 +1 -0
  43. data/test/n3_tests/n3p/simple-01.nt +0 -0
  44. data/test/n3_tests/n3p/simple-02.n3 +4 -0
  45. data/test/n3_tests/n3p/simple-02.nt +0 -0
  46. data/test/n3_tests/n3p/simple-03.n3 +5 -0
  47. data/test/n3_tests/n3p/simple-03.nt +1 -0
  48. data/test/n3_tests/n3p/simple-04.n3 +6 -0
  49. data/test/n3_tests/n3p/simple-04.nt +3 -0
  50. data/test/n3_tests/n3p/simple-05.n3 +7 -0
  51. data/test/n3_tests/n3p/simple-05.nt +2 -0
  52. data/test/n3_tests/n3p/simple-06.n3 +6 -0
  53. data/test/n3_tests/n3p/simple-06.nt +4 -0
  54. data/test/n3_tests/n3p/simple-07.n3 +7 -0
  55. data/test/n3_tests/n3p/simple-07.nt +6 -0
  56. data/test/perf_test/test.rb +11 -0
  57. data/test/perf_test/tommorris.rdf +2267 -0
  58. data/test/rdf_tests/cc197bad-dc9c-440d-a5b5-d52ba2e14234.nt +24 -0
  59. data/test/rdf_tests/cc197bad-dc9c-440d-a5b5-d52ba2e14234.rdf +46 -0
  60. data/test/rdf_tests/tm_001.nt +1 -0
  61. data/test/rdf_tests/tm_001.rdf +7 -0
  62. data/test/rdf_tests/xml-literal-mixed.nt +7 -0
  63. data/test/rdf_tests/xml-literal-mixed.rdf +15 -0
  64. data/test/ruby_fundamentals.spec.rb +17 -0
  65. data/test/test_helper.rb +2 -0
  66. data/test/test_reddy.rb +11 -0
  67. data/test/test_uris.rb +13 -0
  68. data/test/xml.rdf +6 -0
  69. metadata +198 -0
@@ -0,0 +1,6 @@
1
+ require 'xml'
2
+ class LibXML::XML::Node
3
+ def namespaced_to_s
4
+ self.copy(true).to_s
5
+ end
6
+ end
@@ -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