rdf-turtle 3.1.0 → 3.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 23a25ff951065479aaa42feb25d8646ed7e87270556e759ea10d219e24b4ac72
4
- data.tar.gz: ee4be6acf9c89792f5df29e018a3ab22c667477de4e95178517a4002da68707b
3
+ metadata.gz: 6a527c2357a49551b152847f83943ac2e215ac10b2c4c76d0727fd42a85026cd
4
+ data.tar.gz: 0d8fa400deaf2bbc4c8ea996b0a37d5ead4fbb00519cc95ac84dad58052125e9
5
5
  SHA512:
6
- metadata.gz: 34c956ae30fbbe235344fc2ada8ed41539e912022b6ec0699afde1108d98d6b83a8c3008bc131535e0f96ef9b9f481079aa58dc5f8b384b250b20b4b33b72d90
7
- data.tar.gz: 405cfd25f8899631bac219096670d36969602329c7f3ea4905f0a36a47835ee6ac8aac65c163c6b8d4cc4ce284d2e162cb00ff1e7db193c8bf072c00c84c77dd
6
+ metadata.gz: 2493ae5d441f97c947249a58a7fd8a49ce8aca6f675b08fc5b223a8f3bab2037d2004416ddca6f0ea78ad4dca9199b5c31c92f14b7068085222a7b191de44deb
7
+ data.tar.gz: c4db12c8fe5e8401f82ae472ee343474704bb19a1bf202b1e551f29be6b2a874697e046a0c6bd4a91fe0a29c3428a02fe2e7fd2dff249c44a783ee17bdc9481c
data/README.md CHANGED
@@ -19,6 +19,7 @@ Install with `gem install rdf-turtle`
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
 
@@ -133,6 +178,7 @@ A copy of the [Turtle EBNF][] and derived parser files are included in the repos
133
178
  [Backports]: https://rubygems.org/gems/backports
134
179
  [N-Triples]: https://www.w3.org/TR/rdf-testcases/#ntriples
135
180
  [Turtle]: https://www.w3.org/TR/2012/WD-turtle-20120710/
181
+ [RDF*]: https://lists.w3.org/Archives/Public/public-rdf-star/
136
182
  [Turtle doc]: https://rubydoc.info/github/ruby-rdf/rdf-turtle/master/file/README.md
137
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/VERSION CHANGED
@@ -1 +1 @@
1
- 3.1.0
1
+ 3.1.1
@@ -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)
@@ -87,7 +87,7 @@ module RDF::Turtle
87
87
  @options = {
88
88
  anon_base: "b0",
89
89
  whitespace: WS,
90
- log_depth: 0,
90
+ depth: 0,
91
91
  }.merge(@options)
92
92
  @prod_stack = []
93
93
 
@@ -185,7 +185,7 @@ module RDF::Turtle
185
185
 
186
186
  # Create a literal
187
187
  def literal(value, **options)
188
- log_debug("literal") do
188
+ log_debug("literal", depth: @options[:depth]) do
189
189
  "value: #{value.inspect}, " +
190
190
  "options: #{options.inspect}, " +
191
191
  "validate: #{validate?.inspect}, " +
@@ -221,7 +221,7 @@ module RDF::Turtle
221
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
@@ -313,6 +313,17 @@ module RDF::Turtle
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
@@ -457,7 +468,7 @@ module RDF::Turtle
457
468
 
458
469
  # Can subject be represented as a blankNodePropertyList?
459
470
  def blankNodePropertyList?(resource, position)
460
- resource.node? &&
471
+ !resource.statement? && resource.node? &&
461
472
  !is_valid_list?(resource) &&
462
473
  (!is_done?(resource) || position == :subject) &&
463
474
  ref_count(resource) == (position == :object ? 1 : 0)
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.1.0
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: 2019-12-10 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
@@ -17,6 +17,9 @@ dependencies:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
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
@@ -24,6 +27,9 @@ dependencies:
24
27
  - - "~>"
25
28
  - !ruby/object:Gem::Version
26
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
@@ -169,7 +175,7 @@ files:
169
175
  - lib/rdf/turtle/terminals.rb
170
176
  - lib/rdf/turtle/version.rb
171
177
  - lib/rdf/turtle/writer.rb
172
- homepage: https://ruby-rdf.github.com/rdf-turtle
178
+ homepage: https://github.com/ruby-rdf/rdf-turtle
173
179
  licenses:
174
180
  - Unlicense
175
181
  metadata: {}
@@ -188,7 +194,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
188
194
  - !ruby/object:Gem::Version
189
195
  version: '0'
190
196
  requirements: []
191
- rubygems_version: 3.0.6
197
+ rubygems_version: 3.1.3
192
198
  signing_key:
193
199
  specification_version: 4
194
200
  summary: Turtle reader/writer for Ruby.