rdf-turtle 3.0.3 → 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 499e06e63d69ec0216db2600e34260d5eda5c7a3736e8f1a42c63a91c716779c
4
- data.tar.gz: 3443fdb3e53d2b12d66f6a9534a9532dabde58b0b319ecc62ffff0a4bd87afb3
3
+ metadata.gz: 6a527c2357a49551b152847f83943ac2e215ac10b2c4c76d0727fd42a85026cd
4
+ data.tar.gz: 0d8fa400deaf2bbc4c8ea996b0a37d5ead4fbb00519cc95ac84dad58052125e9
5
5
  SHA512:
6
- metadata.gz: 1cad03d53fb973b02f541168549cc110769fde86da3b37c1a6187d7fbfffe8bee3f72bea687d14786094ad0cb6a2cd7d4f2072c9989ec4d0c62b6ad81020bccd
7
- data.tar.gz: 1e7f38e3f561a6f16304727fa89b2bbeab0b93b31e8e5a58633f533ba69e2a874e461f59bcf31d015d23382290e33b9b2ecfd007691fe6f5dc0961c98ca0d285
6
+ metadata.gz: 2493ae5d441f97c947249a58a7fd8a49ce8aca6f675b08fc5b223a8f3bab2037d2004416ddca6f0ea78ad4dca9199b5c31c92f14b7068085222a7b191de44deb
7
+ data.tar.gz: c4db12c8fe5e8401f82ae472ee343474704bb19a1bf202b1e551f29be6b2a874697e046a0c6bd4a91fe0a29c3428a02fe2e7fd2dff249c44a783ee17bdc9481c
data/History CHANGED
@@ -30,7 +30,7 @@
30
30
  * Replace remaining uses of SPARQL with RDF::Turtle or RDF::LL1
31
31
 
32
32
  ### 0.0.3
33
- * Completed RDF 1.1 Turtle based on http://www.w3.org/TR/2011/WD-turtle-20110809/
33
+ * Completed RDF 1.1 Turtle based on https://www.w3.org/TR/2011/WD-turtle-20110809/
34
34
  * Reader
35
35
  * Writer
36
36
  * Issues:
data/README.md CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  [Turtle][] reader/writer for [RDF.rb][RDF.rb] .
4
4
 
5
- [![Gem Version](https://badge.fury.io/rb/rdf-turtle.png)](http://badge.fury.io/rb/rdf-turtle)
6
- [![Build Status](https://travis-ci.org/ruby-rdf/rdf-turtle.png?branch=master)](http://travis-ci.org/ruby-rdf/rdf-turtle)
5
+ [![Gem Version](https://badge.fury.io/rb/rdf-turtle.png)](https://badge.fury.io/rb/rdf-turtle)
6
+ [![Build Status](https://travis-ci.org/ruby-rdf/rdf-turtle.png?branch=master)](https://travis-ci.org/ruby-rdf/rdf-turtle)
7
7
  [![Coverage Status](https://coveralls.io/repos/ruby-rdf/rdf-turtle/badge.svg)](https://coveralls.io/r/ruby-rdf/rdf-turtle)
8
8
  [![Dependency Status](https://gemnasium.com/ruby-rdf/rdf-turtle.png)](https://gemnasium.com/ruby-rdf/rdf-turtle)
9
9
 
@@ -15,10 +15,11 @@ RDF::Turtle parses [Turtle][Turtle] and [N-Triples][N-Triples] into statements o
15
15
 
16
16
  Install with `gem install rdf-turtle`
17
17
 
18
- * 100% free and unencumbered [public domain](http://unlicense.org/) software.
18
+ * 100% free and unencumbered [public domain](https://unlicense.org/) software.
19
19
  * Implements a complete parser for [Turtle][].
20
20
  * Compatible with Ruby >= 2.2.2.
21
21
  * Optional streaming writer, to serialize large graphs
22
+ * Provisional support for [Turtle*][RDF*].
22
23
 
23
24
  ## Usage
24
25
  Instantiate a reader from a local file:
@@ -35,6 +36,50 @@ Write a graph to a file:
35
36
  writer << graph
36
37
  end
37
38
 
39
+ ## Turtle* (RDFStar)
40
+
41
+ Both reader and writer include provisional support for [Turtle*][RDF*].
42
+
43
+ Internally, an `RDF::Statement` is treated as another resource, along with `RDF::URI` and `RDF::Node`, which allows an `RDF::Statement` to have a `#subject` or `#object` which is also an `RDF::Statement`.
44
+
45
+ **Note: This feature is subject to change or elimination as the standards process progresses.**
46
+
47
+ ### Serializing a Graph containing embedded statements
48
+
49
+ require 'rdf/turtle'
50
+ statement = RDF::Statement(RDF::URI('bob'), RDF::Vocab::FOAF.age, RDF::Literal(23))
51
+ graph = RDF::Graph.new << [statement, RDF::URI("ex:certainty"), RDF::Literal(0.9)]
52
+ graph.dump(:ttl, validate: false, standard_prefixes: true)
53
+ # => '<<<bob> foaf:age 23>> <ex:certainty> 9.0e-1 .'
54
+
55
+ ### Reading a Graph containing embedded statements
56
+
57
+ By default, the Turtle reader will reject a document containing a subject resource.
58
+
59
+ ttl = %(
60
+ @prefix foaf: <http://xmlns.com/foaf/0.1/> .
61
+ @prefix ex: <http://example.com/> .
62
+ <<<bob> foaf:age 23>> ex:certainty 9.0e-1 .
63
+ )
64
+ graph = RDF::Graph.new do |graph|
65
+ RDF::Turtle::Reader.new(ttl) {|reader| graph << reader}
66
+ end
67
+ # => RDF::ReaderError
68
+
69
+ Readers support a `rdfstar` option with either `:PG` (Property Graph) or `:SA` (Separate Assertions) modes. In `:PG` mode, statements that are used in the subject or object positions are also implicitly added to the graph:
70
+
71
+ graph = RDF::Graph.new do |graph|
72
+ RDF::Turtle::Reader.new(ttl, rdfstar: :PG) {|reader| graph << reader}
73
+ end
74
+ graph.count #=> 2
75
+
76
+ When using the `:SA` mode, only one statement is asserted, although the reified statement is contained within the graph.
77
+
78
+ graph = RDF::Graph.new do |graph|
79
+ RDF::Turtle::Reader.new(ttl, rdfstar: :SA) {|reader| graph << reader}
80
+ end
81
+ graph.count #=> 1
82
+
38
83
  ## Documentation
39
84
  Full documentation available on [Rubydoc.info][Turtle doc]
40
85
 
@@ -85,22 +130,22 @@ This version uses a hand-written parser using the Lexer from the [EBNF][] gem in
85
130
 
86
131
  ## Dependencies
87
132
 
88
- * [Ruby](http://ruby-lang.org/) (>= 2.2)
89
- * [RDF.rb](http://rubygems.org/gems/rdf) (~> 3.0)
133
+ * [Ruby](https://ruby-lang.org/) (>= 2.4)
134
+ * [RDF.rb](https://rubygems.org/gems/rdf) (~> 3.1)
90
135
  * [EBNF][] (~> 1.1)
91
136
 
92
137
  ## Installation
93
138
 
94
- The recommended installation method is via [RubyGems](http://rubygems.org/).
139
+ The recommended installation method is via [RubyGems](https://rubygems.org/).
95
140
  To install the latest official release of the `RDF::Turtle` gem, do:
96
141
 
97
142
  % [sudo] gem install rdf-turtle
98
143
 
99
144
  ## Mailing List
100
- * <http://lists.w3.org/Archives/Public/public-rdf-ruby/>
145
+ * <https://lists.w3.org/Archives/Public/public-rdf-ruby/>
101
146
 
102
147
  ## Author
103
- * [Gregg Kellogg](http://github.com/gkellogg) - <http://greggkellogg.net/>
148
+ * [Gregg Kellogg](https://github.com/gkellogg) - <https://greggkellogg.net/>
104
149
 
105
150
  ## Contributing
106
151
  This repository uses [Git Flow](https://github.com/nvie/gitflow) to mange development and release activity. All submissions _must_ be on a feature branch based on the _develop_ branch to ease staging and integration.
@@ -119,20 +164,21 @@ This repository uses [Git Flow](https://github.com/nvie/gitflow) to mange develo
119
164
 
120
165
  ## License
121
166
  This is free and unencumbered public domain software. For more information,
122
- see <http://unlicense.org/> or the accompanying {file:UNLICENSE} file.
123
-
124
- A copy of the [Turtle EBNF][] and derived parser files are included in the repository, which are not covered under the UNLICENSE. These files are covered via the [W3C Document License](http://www.w3.org/Consortium/Legal/2002/copyright-documents-20021231).
125
-
126
- [Ruby]: http://ruby-lang.org/
127
- [RDF]: http://www.w3.org/RDF/
128
- [YARD]: http://yardoc.org/
129
- [YARD-GS]: http://rubydoc.info/docs/yard/file/docs/GettingStarted.md
130
- [PDD]: http://lists.w3.org/Archives/Public/public-rdf-ruby/2010May/0013.html
131
- [RDF.rb]: http://rubydoc.info/github/ruby-rdf/rdf
132
- [EBNF]: http://rubygems.org/gems/ebnf
133
- [Backports]: http://rubygems.org/gems/backports
134
- [N-Triples]: http://www.w3.org/TR/rdf-testcases/#ntriples
135
- [Turtle]: http://www.w3.org/TR/2012/WD-turtle-20120710/
136
- [Turtle doc]: http://rubydoc.info/github/ruby-rdf/rdf-turtle/master/file/README.md
137
- [Turtle EBNF]: http://dvcs.w3.org/hg/rdf/file/default/rdf-turtle/turtle.bnf
167
+ see <https://unlicense.org/> or the accompanying {file:UNLICENSE} file.
168
+
169
+ A copy of the [Turtle EBNF][] and derived parser files are included in the repository, which are not covered under the UNLICENSE. These files are covered via the [W3C Document License](https://www.w3.org/Consortium/Legal/2002/copyright-documents-20021231).
170
+
171
+ [Ruby]: https://ruby-lang.org/
172
+ [RDF]: https://www.w3.org/RDF/
173
+ [YARD]: https://yardoc.org/
174
+ [YARD-GS]: https://rubydoc.info/docs/yard/file/docs/GettingStarted.md
175
+ [PDD]: https://lists.w3.org/Archives/Public/public-rdf-ruby/2010May/0013.html
176
+ [RDF.rb]: https://rubydoc.info/github/ruby-rdf/rdf
177
+ [EBNF]: https://rubygems.org/gems/ebnf
178
+ [Backports]: https://rubygems.org/gems/backports
179
+ [N-Triples]: https://www.w3.org/TR/rdf-testcases/#ntriples
180
+ [Turtle]: https://www.w3.org/TR/2012/WD-turtle-20120710/
181
+ [RDF*]: https://lists.w3.org/Archives/Public/public-rdf-star/
182
+ [Turtle doc]: https://rubydoc.info/github/ruby-rdf/rdf-turtle/master/file/README.md
183
+ [Turtle EBNF]: https://dvcs.w3.org/hg/rdf/file/default/rdf-turtle/turtle.bnf
138
184
  [Freebase Dumps]: https://developers.google.com/freebase/data
data/UNLICENSE CHANGED
@@ -21,4 +21,4 @@ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
21
  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
22
  OTHER DEALINGS IN THE SOFTWARE.
23
23
 
24
- For more information, please refer to <http://unlicense.org/>
24
+ For more information, please refer to <https://unlicense.org/>
data/VERSION CHANGED
@@ -1 +1 @@
1
- 3.0.3
1
+ 3.1.1
@@ -15,10 +15,10 @@ module RDF
15
15
  # end
16
16
  # end
17
17
  #
18
- # @see http://rubydoc.info/github/ruby-rdf/rdf/master/frames
19
- # @see http://dvcs.w3.org/hg/rdf/raw-file/default/rdf-turtle/index.html
18
+ # @see https://rubydoc.info/github/ruby-rdf/rdf/master/frames
19
+ # @see https://dvcs.w3.org/hg/rdf/raw-file/default/rdf-turtle/index.html
20
20
  #
21
- # @author [Gregg Kellogg](http://greggkellogg.net/)
21
+ # @author [Gregg Kellogg](https://greggkellogg.net/)
22
22
  module Turtle
23
23
  require 'rdf/turtle/format'
24
24
  autoload :Reader, 'rdf/turtle/reader'
@@ -14,7 +14,7 @@ module RDF::Turtle
14
14
  # @example Obtaining serialization format file extension mappings
15
15
  # RDF::Format.file_extensions #=> {ttl: "text/turtle"}
16
16
  #
17
- # @see http://www.w3.org/TR/rdf-testcases/#ntriples
17
+ # @see https://www.w3.org/TR/rdf-testcases/#ntriples
18
18
  class Format < RDF::Format
19
19
  content_type 'text/turtle',
20
20
  extension: :ttl,
@@ -55,7 +55,7 @@ module RDF::Turtle
55
55
  ##
56
56
  # Read a PNAME of the form `prefix:suffix`.
57
57
  # @return [RDF::URI]
58
- def read_pname(options = {})
58
+ def read_pname(**options)
59
59
  if pname_str = match(/^(\w+:\S+)/)
60
60
  ns, suffix = pname_str.split(':', 2)
61
61
  if suffix[-1,1] == "."
@@ -74,7 +74,7 @@ module RDF::Turtle
74
74
 
75
75
  ##
76
76
  # @return [RDF::Literal]
77
- # @see http://www.w3.org/TR/rdf-testcases/#ntrip_grammar (literal)
77
+ # @see https://www.w3.org/TR/rdf-testcases/#ntrip_grammar (literal)
78
78
  def read_literal
79
79
  if literal_str = match(LITERAL_PLAIN)
80
80
  literal_str = self.class.unescape(literal_str)
@@ -25,7 +25,7 @@ module RDF::Turtle
25
25
  terminal(:STRING_LITERAL_SINGLE_QUOTE, STRING_LITERAL_SINGLE_QUOTE, unescape: true)
26
26
 
27
27
  # String terminals
28
- terminal(nil, %r([\(\),.;\[\]Aa]|\^\^|true|false))
28
+ terminal(nil, %r([\(\),.;\[\]Aa]|\^\^|true|false|<<|>>))
29
29
 
30
30
  terminal(:PREFIX, PREFIX)
31
31
  terminal(:BASE, BASE)
@@ -33,7 +33,7 @@ module RDF::Turtle
33
33
 
34
34
  ##
35
35
  # Reader options
36
- # @see http://www.rubydoc.info/github/ruby-rdf/rdf/RDF/Reader#options-class_method
36
+ # @see https://www.rubydoc.info/github/ruby-rdf/rdf/RDF/Reader#options-class_method
37
37
  def self.options
38
38
  super + [
39
39
  RDF::CLI::Option.new(
@@ -48,14 +48,14 @@ module RDF::Turtle
48
48
  # Redirect for Freebase Reader
49
49
  #
50
50
  # @private
51
- def self.new(input = nil, options = {}, &block)
51
+ def self.new(input = nil, **options, &block)
52
52
  klass = if options[:freebase]
53
53
  FreebaseReader
54
54
  else
55
55
  self
56
56
  end
57
57
  reader = klass.allocate
58
- reader.send(:initialize, input, options, &block)
58
+ reader.send(:initialize, input, **options, &block)
59
59
  reader
60
60
  end
61
61
 
@@ -82,15 +82,13 @@ module RDF::Turtle
82
82
  # @option options [Boolean] :freebase (false)
83
83
  # Use optimized Freebase reader
84
84
  # @return [RDF::Turtle::Reader]
85
- def initialize(input = nil, options = {}, &block)
85
+ def initialize(input = nil, **options, &block)
86
86
  super do
87
87
  @options = {
88
88
  anon_base: "b0",
89
- validate: false,
90
89
  whitespace: WS,
91
- log_depth: 0,
92
- }.merge(options)
93
- @options = {prefixes: {nil => ""}}.merge(@options) unless @options[:validate]
90
+ depth: 0,
91
+ }.merge(@options)
94
92
  @prod_stack = []
95
93
 
96
94
  @options[:base_uri] = RDF::URI(base_uri || "")
@@ -100,7 +98,7 @@ module RDF::Turtle
100
98
  log_debug("canonicalize") {canonicalize?.inspect}
101
99
  log_debug("intern") {intern?.inspect}
102
100
 
103
- @lexer = EBNF::LL1::Lexer.new(input, self.class.patterns, @options)
101
+ @lexer = EBNF::LL1::Lexer.new(input, self.class.patterns, **@options)
104
102
 
105
103
  if block_given?
106
104
  case block.arity
@@ -178,7 +176,7 @@ module RDF::Turtle
178
176
  value = RDF::URI(iri)
179
177
  value = base_uri.join(value) if value.relative?
180
178
  value.validate! if validate?
181
- value.canonicalize! if canonicalize?
179
+ value.canonicalize! if canonicalize? && !value.frozen?
182
180
  value = RDF::URI.intern(value) if intern?
183
181
  value
184
182
  rescue ArgumentError => e
@@ -186,14 +184,14 @@ module RDF::Turtle
186
184
  end
187
185
 
188
186
  # Create a literal
189
- def literal(value, options = {})
190
- log_debug("literal") do
187
+ def literal(value, **options)
188
+ log_debug("literal", depth: @options[:depth]) do
191
189
  "value: #{value.inspect}, " +
192
190
  "options: #{options.inspect}, " +
193
191
  "validate: #{validate?.inspect}, " +
194
192
  "c14n?: #{canonicalize?.inspect}"
195
193
  end
196
- RDF::Literal.new(value, options.merge(validate: validate?, canonicalize: canonicalize?))
194
+ RDF::Literal.new(value, validate: validate?, canonicalize: canonicalize?, **options)
197
195
  rescue ArgumentError => e
198
196
  error("Argument Error #{e.message}", production: :literal, token: @lexer.first)
199
197
  end
@@ -214,14 +212,16 @@ module RDF::Turtle
214
212
  # Expand a PNAME using string concatenation
215
213
  def pname(prefix, suffix)
216
214
  # Prefixes must be defined, except special case for empty prefix being alias for current @base
217
- if prefix(prefix)
218
- base = prefix(prefix).to_s
219
- elsif !prefix(prefix)
215
+ base = if prefix(prefix)
216
+ prefix(prefix).to_s
217
+ elsif prefix.to_s.empty? && !validate?
218
+ base_uri.to_s
219
+ else
220
220
  error("undefined prefix", production: :pname, token: prefix)
221
- base = ''
221
+ ''
222
222
  end
223
223
  suffix = suffix.to_s.sub(/^\#/, "") if base.index("#")
224
- log_debug("pname") {"base: '#{base}', suffix: '#{suffix}'"}
224
+ log_debug("pname", depth: options[:depth]) {"base: '#{base}', suffix: '#{suffix}'"}
225
225
  process_iri(base + suffix.to_s)
226
226
  end
227
227
 
@@ -283,7 +283,7 @@ module RDF::Turtle
283
283
  terminated = token.value == '@prefix'
284
284
  error("Expected PNAME_NS", production: :prefix, token: pfx) unless pfx === :PNAME_NS
285
285
  error("Expected IRIREF", production: :prefix, token: iri) unless iri === :IRIREF
286
- log_debug("prefixID") {"Defined prefix #{pfx.inspect} mapping to #{iri.inspect}"}
286
+ log_debug("prefixID", depth: options[:depth]) {"Defined prefix #{pfx.inspect} mapping to #{iri.inspect}"}
287
287
  prefix(pfx.value[0..-2], process_iri(iri))
288
288
  error("prefixId", "#{token} should be downcased") if token.value.start_with?('@') && token.value != '@prefix'
289
289
 
@@ -362,6 +362,7 @@ module RDF::Turtle
362
362
  read_iri ||
363
363
  read_BlankNode ||
364
364
  read_collection ||
365
+ read_rdfstar ||
365
366
  error( "Expected subject", production: :subject, token: @lexer.first)
366
367
  end
367
368
  end
@@ -373,7 +374,8 @@ module RDF::Turtle
373
374
  read_BlankNode ||
374
375
  read_collection ||
375
376
  read_blankNodePropertyList ||
376
- read_literal
377
+ read_literal ||
378
+ read_rdfstar
377
379
 
378
380
  add_statement(:object, RDF::Statement(subject, predicate, object)) if subject && predicate
379
381
  object
@@ -381,6 +383,28 @@ module RDF::Turtle
381
383
  end
382
384
  end
383
385
 
386
+ # Read an RDF* reified statement
387
+ # @return [RDF::Statement]
388
+ def read_rdfstar
389
+ return unless @options[:rdfstar]
390
+ if @lexer.first.value == '<<'
391
+ prod(:rdfstar) do
392
+ @lexer.shift # eat <<
393
+ subject = read_subject || error("Failed to parse subject", production: :rdfstar, token: @lexer.first)
394
+ predicate = read_verb || error("Failed to parse predicate", production: :rdfstar, token: @lexer.first)
395
+ object = read_object || error("Failed to parse object", production: :rdfstar, token: @lexer.first)
396
+ unless @lexer.first.value == '>>'
397
+ error("Failed to end of embedded triple", production: :rdfstar, token: @lexer.first)
398
+ end
399
+ @lexer.shift
400
+ statement = RDF::Statement(subject, predicate, object)
401
+ # Emit the statement if in Property Graph mode
402
+ add_statement(:rdfstar, statement) if @options[:rdfstar] == :PG
403
+ statement
404
+ end
405
+ end
406
+ end
407
+
384
408
  # @return [RDF::Literal]
385
409
  def read_literal
386
410
  error("Unexpected end of file", production: :literal) unless token = @lexer.first
@@ -431,7 +455,7 @@ module RDF::Turtle
431
455
  if token === '['
432
456
  prod(:blankNodePropertyList, %{]}) do
433
457
  @lexer.shift
434
- log_info("blankNodePropertyList") {"token: #{token.inspect}"}
458
+ log_info("blankNodePropertyList", depth: options[:depth]) {"token: #{token.inspect}"}
435
459
  node = bnode
436
460
  read_predicateObjectList(node)
437
461
  error("blankNodePropertyList", "Expected closing ']'") unless @lexer.first === ']'
@@ -447,7 +471,7 @@ module RDF::Turtle
447
471
  prod(:collection, %{)}) do
448
472
  @lexer.shift
449
473
  token = @lexer.first
450
- log_info("collection") {"token: #{token.inspect}"}
474
+ log_info("collection", depth: options[:depth]) {"token: #{token.inspect}"}
451
475
  objects = []
452
476
  while object = read_object
453
477
  objects << object
@@ -483,8 +507,8 @@ module RDF::Turtle
483
507
 
484
508
  def prod(production, recover_to = [])
485
509
  @prod_stack << {prod: production, recover_to: recover_to}
486
- @options[:log_depth] += 1
487
- log_recover("#{production}(start)") {"token: #{@lexer.first.inspect}"}
510
+ @options[:depth] += 1
511
+ log_recover("#{production}(start)", depth: options[:depth]) {"token: #{@lexer.first.inspect}"}
488
512
  yield
489
513
  rescue EBNF::LL1::Lexer::Error, SyntaxError, Recovery => e
490
514
  # Lexer encountered an illegal token or the parser encountered
@@ -504,13 +528,13 @@ module RDF::Turtle
504
528
  end
505
529
  end
506
530
  raise EOFError, "End of input found when recovering" if @lexer.first.nil?
507
- log_debug("recovery", "current token: #{@lexer.first.inspect}")
531
+ log_debug("recovery", "current token: #{@lexer.first.inspect}", depth: options[:depth])
508
532
 
509
533
  unless e.is_a?(Recovery)
510
534
  # Get the list of follows for this sequence, this production and the stacked productions.
511
- log_debug("recovery", "stack follows:")
535
+ log_debug("recovery", "stack follows:", depth: options[:depth])
512
536
  @prod_stack.reverse.each do |prod|
513
- log_debug("recovery", level: 4) {" #{prod[:prod]}: #{prod[:recover_to].inspect}"}
537
+ log_debug("recovery", level: 4, depth: options[:depth]) {" #{prod[:prod]}: #{prod[:recover_to].inspect}"}
514
538
  end
515
539
  end
516
540
 
@@ -520,9 +544,9 @@ module RDF::Turtle
520
544
  # Skip tokens until one is found in follows
521
545
  while (token = (@lexer.first rescue @lexer.recover)) && follows.none? {|t| token === t}
522
546
  skipped = @lexer.shift
523
- log_debug("recovery") {"skip #{skipped.inspect}"}
547
+ log_debug("recovery", depth: options[:depth]) {"skip #{skipped.inspect}"}
524
548
  end
525
- log_debug("recovery") {"found #{token.inspect} in follows"}
549
+ log_debug("recovery", depth: options[:depth]) {"found #{token.inspect} in follows"}
526
550
 
527
551
  # Re-raise the error unless token is a follows of this production
528
552
  raise Recovery unless Array(recover_to).any? {|t| token === t}
@@ -530,8 +554,8 @@ module RDF::Turtle
530
554
  # Skip that token to get something reasonable to start the next production with
531
555
  @lexer.shift
532
556
  ensure
533
- log_info("#{production}(finish)")
534
- @options[:log_depth] -= 1
557
+ log_info("#{production}(finish)", depth: options[:depth])
558
+ @options[:depth] -= 1
535
559
  @prod_stack.pop
536
560
  end
537
561
 
@@ -554,7 +578,8 @@ module RDF::Turtle
554
578
  lineno: lineno,
555
579
  token: options[:token],
556
580
  production: options[:production],
557
- exception: SyntaxError)
581
+ depth: options[:depth],
582
+ exception: SyntaxError,)
558
583
  end
559
584
 
560
585
  # Used for internal error recovery
@@ -587,7 +612,7 @@ module RDF::Turtle
587
612
  # @option options [Symbol] :production (nil)
588
613
  # @option options [String] :token (nil)
589
614
  # @option options [Integer] :lineno (nil)
590
- def initialize(message, options = {})
615
+ def initialize(message, **options)
591
616
  @production = options[:production]
592
617
  @token = options[:token]
593
618
  @lineno = options[:lineno] || (@token.lineno if @token.respond_to?(:lineno))
@@ -3,7 +3,7 @@ require 'rdf/turtle/terminals'
3
3
  module RDF::Turtle
4
4
  ##
5
5
  # Streaming writer interface
6
- # @author [Gregg Kellogg](http://greggkellogg.net/)
6
+ # @author [Gregg Kellogg](https://greggkellogg.net/)
7
7
  module StreamingWriter
8
8
  ##
9
9
  # Write out declarations
@@ -28,15 +28,15 @@ module RDF::Turtle
28
28
  if statement.subject != @streaming_subject
29
29
  @output.puts ' .' if @streaming_subject
30
30
  @streaming_subject, @streaming_predicate = statement.subject, statement.predicate
31
- @output.write "#{format_term(statement.subject, options)} "
32
- @output.write "#{format_term(statement.predicate, options)} "
31
+ @output.write "#{format_term(statement.subject, **options)} "
32
+ @output.write "#{format_term(statement.predicate, **options)} "
33
33
  elsif statement.predicate != @streaming_predicate
34
34
  @streaming_predicate = statement.predicate
35
- @output.write ";\n#{indent(1)}#{format_term(statement.predicate, options)} "
35
+ @output.write ";\n#{indent(1)}#{format_term(statement.predicate, **options)} "
36
36
  else
37
37
  @output.write ",\n#{indent(2)}"
38
38
  end
39
- @output.write("#{format_term(statement.object, options)}")
39
+ @output.write("#{format_term(statement.object, **options)}")
40
40
  end
41
41
 
42
42
  ##
@@ -54,7 +54,7 @@ module RDF::Turtle
54
54
  # end
55
55
  # end
56
56
  #
57
- # @author [Gregg Kellogg](http://greggkellogg.net/)
57
+ # @author [Gregg Kellogg](https://greggkellogg.net/)
58
58
  class Writer < RDF::Writer
59
59
  include StreamingWriter
60
60
  include RDF::Util::Logger
@@ -65,7 +65,7 @@ module RDF::Turtle
65
65
 
66
66
  ##
67
67
  # Writer options
68
- # @see http://www.rubydoc.info/github/ruby-rdf/rdf/RDF/Writer#options-class_method
68
+ # @see https://www.rubydoc.info/github/ruby-rdf/rdf/RDF/Writer#options-class_method
69
69
  def self.options
70
70
  super + [
71
71
  RDF::CLI::Option.new(
@@ -123,7 +123,7 @@ module RDF::Turtle
123
123
  # @yieldreturn [void]
124
124
  # @yield [writer]
125
125
  # @yieldparam [RDF::Writer] writer
126
- def initialize(output = $stdout, options = {}, &block)
126
+ def initialize(output = $stdout, **options, &block)
127
127
  @graph = RDF::Graph.new
128
128
  @uri_to_pname = {}
129
129
  @uri_to_prefix = {}
@@ -272,7 +272,7 @@ module RDF::Turtle
272
272
  # @param [RDF::Literal, String, #to_s] literal
273
273
  # @param [Hash{Symbol => Object}] options
274
274
  # @return [String]
275
- def format_literal(literal, options = {})
275
+ def format_literal(literal, **options)
276
276
  case literal
277
277
  when RDF::Literal
278
278
  case @options[:literal_shorthand] && literal.valid? ? literal.datatype : false
@@ -297,7 +297,7 @@ module RDF::Turtle
297
297
  # @param [RDF::URI] uri
298
298
  # @param [Hash{Symbol => Object}] options
299
299
  # @return [String]
300
- def format_uri(uri, options = {})
300
+ def format_uri(uri, **options)
301
301
  md = uri.relativize(base_uri)
302
302
  log_debug("relativize") {"#{uri.to_ntriples} => #{md.inspect}"} if md != uri.to_s
303
303
  md != uri.to_s ? "<#{md}>" : (get_pname(uri) || "<#{uri}>")
@@ -309,10 +309,21 @@ module RDF::Turtle
309
309
  # @param [RDF::Node] node
310
310
  # @param [Hash{Symbol => Object}] options
311
311
  # @return [String]
312
- def format_node(node, options = {})
312
+ def format_node(node, **options)
313
313
  options[:unique_bnodes] ? node.to_unique_base : node.to_base
314
314
  end
315
315
 
316
+ ##
317
+ # Returns an embedded triples
318
+ #
319
+ # @param [RDF::Statement] statement
320
+ # @param [Hash{Symbol => Object}] options
321
+ # @return [String]
322
+ def format_rdfstar(statement, **options)
323
+ log_debug("rdfstar") {"#{statement.to_ntriples}"}
324
+ "<<%s %s %s>>" % statement.to_a.map { |value| format_term(value, **options) }
325
+ end
326
+
316
327
  protected
317
328
  # Output @base and @prefix definitions
318
329
  def start_document
@@ -349,7 +360,7 @@ module RDF::Turtle
349
360
 
350
361
  # Add distinguished classes
351
362
  top_classes.each do |class_uri|
352
- graph.query(predicate: RDF.type, object: class_uri).
363
+ graph.query({predicate: RDF.type, object: class_uri}).
353
364
  map {|st| st.subject}.
354
365
  sort.
355
366
  uniq.
@@ -363,11 +374,11 @@ module RDF::Turtle
363
374
  # Mark as seen lists that are part of another list
364
375
  @lists.values.map(&:statements).
365
376
  flatten.each do |st|
366
- seen[st.object] if @lists.has_key?(st.object)
377
+ seen[st.object] = true if @lists.has_key?(st.object)
367
378
  end
368
379
 
369
- # List elements should not be targets for top-level serialization
370
- list_elements = @lists.values.map(&:to_a).flatten.compact
380
+ # List elements which are bnodes should not be targets for top-level serialization
381
+ list_elements = @lists.values.map(&:to_a).flatten.select(&:node?).compact
371
382
 
372
383
  # Sort subjects by resources over bnodes, ref_counts and the subject URI itself
373
384
  recursable = (@subjects.keys - list_elements).
@@ -447,7 +458,8 @@ module RDF::Turtle
447
458
  # @return [String]
448
459
  def quoted(string)
449
460
  if string.to_s.match(/[\t\n\r]/)
450
- string = string.gsub('\\', '\\\\\\\\').gsub('"""', '\\"""')
461
+ string = string.gsub('\\', '\\\\\\\\').gsub('"', '\\"')
462
+
451
463
  %("""#{string}""")
452
464
  else
453
465
  "\"#{escaped(string)}\""
@@ -456,7 +468,7 @@ module RDF::Turtle
456
468
 
457
469
  # Can subject be represented as a blankNodePropertyList?
458
470
  def blankNodePropertyList?(resource, position)
459
- resource.node? &&
471
+ !resource.statement? && resource.node? &&
460
472
  !is_valid_list?(resource) &&
461
473
  (!is_done?(resource) || position == :subject) &&
462
474
  ref_count(resource) == (position == :object ? 1 : 0)
@@ -504,12 +516,15 @@ module RDF::Turtle
504
516
  list = @lists[l]
505
517
  log_debug("do_list") {list.inspect}
506
518
  subject_done(RDF.nil)
519
+ index = 0
507
520
  list.each_statement do |st|
508
521
  next unless st.predicate == RDF.first
509
522
  log_debug {" list this: #{st.subject} first: #{st.object}[#{position}]"}
523
+ @output.write(" ") if index > 0
510
524
  path(st.object, position)
511
525
  subject_done(st.subject)
512
526
  position = :object
527
+ index += 1
513
528
  end
514
529
  end
515
530
 
@@ -519,7 +534,7 @@ module RDF::Turtle
519
534
  return false if position == :object && prop_count(node) > 0
520
535
  #log_debug("collection") {"#{node.to_ntriples}, #{position}"}
521
536
 
522
- @output.write(position == :subject ? "(" : " (")
537
+ @output.write("(")
523
538
  log_depth {do_list(node, position)}
524
539
  @output.write(')')
525
540
  end
@@ -530,16 +545,20 @@ module RDF::Turtle
530
545
 
531
546
  log_debug("blankNodePropertyList") {resource.to_ntriples}
532
547
  subject_done(resource)
533
- @output.write(position == :subject ? "\n#{indent} [" : ' [')
548
+ @output.write(position == :subject ? "\n#{indent} [" : '[')
534
549
  num_props = log_depth {predicateObjectList(resource, true)}
535
- @output.write((num_props > 1 ? "\n#{indent}" : "") + (position == :object ? ']' : '] .'))
550
+ @output.write((num_props > 1 ? "\n#{indent(2)}" : "") + (position == :object ? ']' : '] .'))
536
551
  true
537
552
  end
538
553
 
539
554
  # Default singular resource representation.
540
555
  def p_term(resource, position)
541
556
  #log_debug("p_term") {"#{resource.to_ntriples}, #{position}"}
542
- l = (position == :subject ? "" : " ") + format_term(resource, options)
557
+ l = if resource == RDF.nil
558
+ "()"
559
+ else
560
+ format_term(resource, **options)
561
+ end
543
562
  @output.write(l)
544
563
  end
545
564
 
@@ -562,7 +581,7 @@ module RDF::Turtle
562
581
  def predicate(resource)
563
582
  log_debug("predicate") {resource.to_ntriples}
564
583
  if resource == RDF.type
565
- @output.write(" a")
584
+ @output.write("a")
566
585
  else
567
586
  path(resource, :predicate)
568
587
  end
@@ -587,7 +606,7 @@ module RDF::Turtle
587
606
  # @return [Integer] the number of properties serialized
588
607
  def predicateObjectList(subject, from_bpl = false)
589
608
  properties = {}
590
- @graph.query(subject: subject) do |st|
609
+ @graph.query({subject: subject}) do |st|
591
610
  (properties[st.predicate.to_s] ||= []) << st.object
592
611
  end
593
612
 
@@ -601,6 +620,7 @@ module RDF::Turtle
601
620
  begin
602
621
  @output.write(";\n#{indent(2)}") if i > 0
603
622
  predicate(RDF::URI.intern(prop))
623
+ @output.write(" ")
604
624
  objectList(properties[prop])
605
625
  end
606
626
  end
@@ -611,8 +631,9 @@ module RDF::Turtle
611
631
  def triples(subject)
612
632
  @output.write("\n#{indent}")
613
633
  path(subject, :subject)
614
- predicateObjectList(subject)
615
- @output.write(" .")
634
+ @output.write(" ")
635
+ num_props = predicateObjectList(subject)
636
+ @output.write("#{num_props > 0 ? ' ' : ''}.")
616
637
  true
617
638
  end
618
639
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rdf-turtle
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.3
4
+ version: 3.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregg Kellogg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-22 00:00:00.000000000 Z
11
+ date: 2020-05-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rdf
@@ -16,146 +16,146 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '3.0'
19
+ version: '3.1'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 3.1.2
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - "~>"
25
28
  - !ruby/object:Gem::Version
26
- version: '3.0'
29
+ version: '3.1'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 3.1.2
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: ebnf
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - "~>"
32
38
  - !ruby/object:Gem::Version
33
- version: '1.1'
39
+ version: '1.2'
34
40
  type: :runtime
35
41
  prerelease: false
36
42
  version_requirements: !ruby/object:Gem::Requirement
37
43
  requirements:
38
44
  - - "~>"
39
45
  - !ruby/object:Gem::Version
40
- version: '1.1'
46
+ version: '1.2'
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: rspec
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
51
  - - "~>"
46
52
  - !ruby/object:Gem::Version
47
- version: '3.7'
53
+ version: '3.9'
48
54
  type: :development
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
51
57
  requirements:
52
58
  - - "~>"
53
59
  - !ruby/object:Gem::Version
54
- version: '3.7'
60
+ version: '3.9'
55
61
  - !ruby/object:Gem::Dependency
56
62
  name: rspec-its
57
63
  requirement: !ruby/object:Gem::Requirement
58
64
  requirements:
59
65
  - - "~>"
60
66
  - !ruby/object:Gem::Version
61
- version: '1.2'
67
+ version: '1.3'
62
68
  type: :development
63
69
  prerelease: false
64
70
  version_requirements: !ruby/object:Gem::Requirement
65
71
  requirements:
66
72
  - - "~>"
67
73
  - !ruby/object:Gem::Version
68
- version: '1.2'
74
+ version: '1.3'
69
75
  - !ruby/object:Gem::Dependency
70
76
  name: rdf-isomorphic
71
77
  requirement: !ruby/object:Gem::Requirement
72
78
  requirements:
73
79
  - - "~>"
74
80
  - !ruby/object:Gem::Version
75
- version: '3.0'
81
+ version: '3.1'
76
82
  type: :development
77
83
  prerelease: false
78
84
  version_requirements: !ruby/object:Gem::Requirement
79
85
  requirements:
80
86
  - - "~>"
81
87
  - !ruby/object:Gem::Version
82
- version: '3.0'
88
+ version: '3.1'
83
89
  - !ruby/object:Gem::Dependency
84
- name: rdf-spec
90
+ name: json-ld
85
91
  requirement: !ruby/object:Gem::Requirement
86
92
  requirements:
87
93
  - - "~>"
88
94
  - !ruby/object:Gem::Version
89
- version: '3.0'
95
+ version: '3.1'
90
96
  type: :development
91
97
  prerelease: false
92
98
  version_requirements: !ruby/object:Gem::Requirement
93
99
  requirements:
94
100
  - - "~>"
95
101
  - !ruby/object:Gem::Version
96
- version: '3.0'
102
+ version: '3.1'
97
103
  - !ruby/object:Gem::Dependency
98
- name: rdf-vocab
104
+ name: rdf-spec
99
105
  requirement: !ruby/object:Gem::Requirement
100
106
  requirements:
101
107
  - - "~>"
102
108
  - !ruby/object:Gem::Version
103
- version: '3.0'
109
+ version: '3.1'
104
110
  type: :development
105
111
  prerelease: false
106
112
  version_requirements: !ruby/object:Gem::Requirement
107
113
  requirements:
108
114
  - - "~>"
109
115
  - !ruby/object:Gem::Version
110
- version: '3.0'
116
+ version: '3.1'
111
117
  - !ruby/object:Gem::Dependency
112
- name: json-ld
118
+ name: rdf-vocab
113
119
  requirement: !ruby/object:Gem::Requirement
114
120
  requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '2.1'
118
- - - "<"
121
+ - - "~>"
119
122
  - !ruby/object:Gem::Version
120
- version: '4.0'
123
+ version: '3.1'
121
124
  type: :development
122
125
  prerelease: false
123
126
  version_requirements: !ruby/object:Gem::Requirement
124
127
  requirements:
125
- - - ">="
126
- - !ruby/object:Gem::Version
127
- version: '2.1'
128
- - - "<"
128
+ - - "~>"
129
129
  - !ruby/object:Gem::Version
130
- version: '4.0'
130
+ version: '3.1'
131
131
  - !ruby/object:Gem::Dependency
132
132
  name: rake
133
133
  requirement: !ruby/object:Gem::Requirement
134
134
  requirements:
135
135
  - - "~>"
136
136
  - !ruby/object:Gem::Version
137
- version: '12.0'
137
+ version: '13.0'
138
138
  type: :development
139
139
  prerelease: false
140
140
  version_requirements: !ruby/object:Gem::Requirement
141
141
  requirements:
142
142
  - - "~>"
143
143
  - !ruby/object:Gem::Version
144
- version: '12.0'
144
+ version: '13.0'
145
145
  - !ruby/object:Gem::Dependency
146
146
  name: yard
147
147
  requirement: !ruby/object:Gem::Requirement
148
148
  requirements:
149
149
  - - "~>"
150
150
  - !ruby/object:Gem::Version
151
- version: 0.9.12
151
+ version: 0.9.20
152
152
  type: :development
153
153
  prerelease: false
154
154
  version_requirements: !ruby/object:Gem::Requirement
155
155
  requirements:
156
156
  - - "~>"
157
157
  - !ruby/object:Gem::Version
158
- version: 0.9.12
158
+ version: 0.9.20
159
159
  description: RDF::Turtle is an Turtle reader/writer for the RDF.rb library suite.
160
160
  email: public-rdf-ruby@w3.org
161
161
  executables: []
@@ -175,7 +175,7 @@ files:
175
175
  - lib/rdf/turtle/terminals.rb
176
176
  - lib/rdf/turtle/version.rb
177
177
  - lib/rdf/turtle/writer.rb
178
- homepage: http://ruby-rdf.github.com/rdf-turtle
178
+ homepage: https://github.com/ruby-rdf/rdf-turtle
179
179
  licenses:
180
180
  - Unlicense
181
181
  metadata: {}
@@ -187,15 +187,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
187
187
  requirements:
188
188
  - - ">="
189
189
  - !ruby/object:Gem::Version
190
- version: 2.2.2
190
+ version: '2.4'
191
191
  required_rubygems_version: !ruby/object:Gem::Requirement
192
192
  requirements:
193
193
  - - ">="
194
194
  - !ruby/object:Gem::Version
195
195
  version: '0'
196
196
  requirements: []
197
- rubyforge_project:
198
- rubygems_version: 2.7.6
197
+ rubygems_version: 3.1.3
199
198
  signing_key:
200
199
  specification_version: 4
201
200
  summary: Turtle reader/writer for Ruby.