sparql 1.1.5 → 1.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +36 -32
  3. data/VERSION +1 -1
  4. data/bin/sparql +8 -6
  5. data/lib/sparql.rb +4 -2
  6. data/lib/sparql/algebra.rb +74 -4
  7. data/lib/sparql/algebra/aggregate.rb +1 -1
  8. data/lib/sparql/algebra/evaluatable.rb +1 -1
  9. data/lib/sparql/algebra/expression.rb +24 -16
  10. data/lib/sparql/algebra/extensions.rb +37 -9
  11. data/lib/sparql/algebra/operator.rb +75 -12
  12. data/lib/sparql/algebra/operator/add.rb +41 -19
  13. data/lib/sparql/algebra/operator/and.rb +2 -2
  14. data/lib/sparql/algebra/operator/asc.rb +1 -1
  15. data/lib/sparql/algebra/operator/ask.rb +1 -1
  16. data/lib/sparql/algebra/operator/base.rb +1 -1
  17. data/lib/sparql/algebra/operator/bgp.rb +1 -1
  18. data/lib/sparql/algebra/operator/bnode.rb +1 -1
  19. data/lib/sparql/algebra/operator/clear.rb +63 -0
  20. data/lib/sparql/algebra/operator/coalesce.rb +1 -1
  21. data/lib/sparql/algebra/operator/concat.rb +3 -3
  22. data/lib/sparql/algebra/operator/construct.rb +2 -2
  23. data/lib/sparql/algebra/operator/copy.rb +64 -0
  24. data/lib/sparql/algebra/operator/create.rb +49 -0
  25. data/lib/sparql/algebra/operator/dataset.rb +6 -31
  26. data/lib/sparql/algebra/operator/delete.rb +55 -0
  27. data/lib/sparql/algebra/operator/delete_data.rb +41 -0
  28. data/lib/sparql/algebra/operator/delete_where.rb +57 -0
  29. data/lib/sparql/algebra/operator/distinct.rb +1 -1
  30. data/lib/sparql/algebra/operator/drop.rb +66 -0
  31. data/lib/sparql/algebra/operator/exists.rb +2 -2
  32. data/lib/sparql/algebra/operator/exprlist.rb +1 -1
  33. data/lib/sparql/algebra/operator/extend.rb +3 -3
  34. data/lib/sparql/algebra/operator/filter.rb +2 -2
  35. data/lib/sparql/algebra/operator/graph.rb +39 -5
  36. data/lib/sparql/algebra/operator/group.rb +5 -5
  37. data/lib/sparql/algebra/operator/group_concat.rb +1 -1
  38. data/lib/sparql/algebra/operator/if.rb +3 -3
  39. data/lib/sparql/algebra/operator/in.rb +1 -1
  40. data/lib/sparql/algebra/operator/insert.rb +54 -0
  41. data/lib/sparql/algebra/operator/insert_data.rb +41 -0
  42. data/lib/sparql/algebra/operator/join.rb +2 -2
  43. data/lib/sparql/algebra/operator/lcase.rb +1 -1
  44. data/lib/sparql/algebra/operator/left_join.rb +2 -2
  45. data/lib/sparql/algebra/operator/load.rb +48 -0
  46. data/lib/sparql/algebra/operator/minus.rb +2 -2
  47. data/lib/sparql/algebra/operator/modify.rb +53 -0
  48. data/lib/sparql/algebra/operator/move.rb +67 -0
  49. data/lib/sparql/algebra/operator/notexists.rb +1 -1
  50. data/lib/sparql/algebra/operator/notin.rb +2 -2
  51. data/lib/sparql/algebra/operator/or.rb +2 -2
  52. data/lib/sparql/algebra/operator/order.rb +3 -3
  53. data/lib/sparql/algebra/operator/plus.rb +14 -8
  54. data/lib/sparql/algebra/operator/prefix.rb +1 -1
  55. data/lib/sparql/algebra/operator/project.rb +1 -1
  56. data/lib/sparql/algebra/operator/reduced.rb +1 -1
  57. data/lib/sparql/algebra/operator/replace.rb +1 -1
  58. data/lib/sparql/algebra/operator/slice.rb +1 -1
  59. data/lib/sparql/algebra/operator/strafter.rb +1 -1
  60. data/lib/sparql/algebra/operator/strbefore.rb +2 -2
  61. data/lib/sparql/algebra/operator/strdt.rb +1 -1
  62. data/lib/sparql/algebra/operator/strlang.rb +1 -1
  63. data/lib/sparql/algebra/operator/substr.rb +2 -2
  64. data/lib/sparql/algebra/operator/ucase.rb +1 -1
  65. data/lib/sparql/algebra/operator/union.rb +1 -1
  66. data/lib/sparql/algebra/operator/update.rb +44 -0
  67. data/lib/sparql/algebra/operator/using.rb +40 -0
  68. data/lib/sparql/algebra/operator/with.rb +72 -0
  69. data/lib/sparql/algebra/update.rb +56 -0
  70. data/lib/sparql/extensions.rb +8 -8
  71. data/lib/sparql/grammar.rb +31 -8
  72. data/lib/sparql/grammar/meta.rb +3758 -3273
  73. data/lib/sparql/grammar/parser11.rb +240 -46
  74. data/lib/sparql/grammar/terminals11.rb +5 -5
  75. data/lib/sparql/results.rb +26 -26
  76. metadata +38 -30
@@ -63,7 +63,7 @@ module SPARQL::Grammar
63
63
  terminal(:BLANK_NODE_LABEL, BLANK_NODE_LABEL) do |prod, token, input|
64
64
  add_prod_datum(:BlankNode, bnode(token.value[2..-1]))
65
65
  end
66
- terminal(:IRIREF, IRIREF, :unescape => true) do |prod, token, input|
66
+ terminal(:IRIREF, IRIREF, unescape: true) do |prod, token, input|
67
67
  begin
68
68
  add_prod_datum(:iri, iri(token.value[1..-2]))
69
69
  rescue ArgumentError => e
@@ -74,54 +74,54 @@ module SPARQL::Grammar
74
74
  # Note that a Turtle Double may begin with a '.[eE]', so tack on a leading
75
75
  # zero if necessary
76
76
  value = token.value.sub(/\.([eE])/, '.0\1')
77
- add_prod_datum(:literal, literal(value, :datatype => RDF::XSD.double))
77
+ add_prod_datum(:literal, literal(value, datatype: RDF::XSD.double))
78
78
  end
79
79
  terminal(:DECIMAL_POSITIVE, DECIMAL_POSITIVE) do |prod, token, input|
80
80
  # Note that a Turtle Decimal may begin with a '.', so tack on a leading
81
81
  # zero if necessary
82
82
  value = token.value
83
83
  value = "0#{token.value}" if token.value[0,1] == "."
84
- add_prod_datum(:literal, literal(value, :datatype => RDF::XSD.decimal))
84
+ add_prod_datum(:literal, literal(value, datatype: RDF::XSD.decimal))
85
85
  end
86
86
  terminal(:INTEGER_POSITIVE, INTEGER_POSITIVE) do |prod, token, input|
87
- add_prod_datum(:literal, literal(token.value, :datatype => RDF::XSD.integer))
87
+ add_prod_datum(:literal, literal(token.value, datatype: RDF::XSD.integer))
88
88
  end
89
89
  terminal(:DOUBLE_NEGATIVE, DOUBLE_NEGATIVE) do |prod, token, input|
90
90
  # Note that a Turtle Double may begin with a '.[eE]', so tack on a leading
91
91
  # zero if necessary
92
92
  value = token.value.sub(/\.([eE])/, '.0\1')
93
- add_prod_datum(:literal, literal(value, :datatype => RDF::XSD.double))
93
+ add_prod_datum(:literal, literal(value, datatype: RDF::XSD.double))
94
94
  end
95
95
  terminal(:DECIMAL_NEGATIVE, DECIMAL_NEGATIVE) do |prod, token, input|
96
96
  # Note that a Turtle Decimal may begin with a '.', so tack on a leading
97
97
  # zero if necessary
98
98
  value = token.value
99
99
  value = "0#{token.value}" if token.value[0,1] == "."
100
- add_prod_datum(:literal, literal(value, :datatype => RDF::XSD.decimal))
100
+ add_prod_datum(:literal, literal(value, datatype: RDF::XSD.decimal))
101
101
  end
102
102
  terminal(:INTEGER_NEGATIVE, INTEGER_NEGATIVE) do |prod, token, input|
103
- add_prod_datum(:resource, literal(token.value, :datatype => RDF::XSD.integer))
103
+ add_prod_datum(:resource, literal(token.value, datatype: RDF::XSD.integer))
104
104
  end
105
105
  terminal(:DOUBLE, DOUBLE) do |prod, token, input|
106
106
  # Note that a Turtle Double may begin with a '.[eE]', so tack on a leading
107
107
  # zero if necessary
108
108
  value = token.value.sub(/\.([eE])/, '.0\1')
109
- add_prod_datum(:literal, literal(value, :datatype => RDF::XSD.double))
109
+ add_prod_datum(:literal, literal(value, datatype: RDF::XSD.double))
110
110
  end
111
111
  terminal(:DECIMAL, DECIMAL) do |prod, token, input|
112
112
  # Note that a Turtle Decimal may begin with a '.', so tack on a leading
113
113
  # zero if necessary
114
114
  value = token.value
115
115
  #value = "0#{token.value}" if token.value[0,1] == "."
116
- add_prod_datum(:literal, literal(value, :datatype => RDF::XSD.decimal))
116
+ add_prod_datum(:literal, literal(value, datatype: RDF::XSD.decimal))
117
117
  end
118
118
  terminal(:INTEGER, INTEGER) do |prod, token, input|
119
- add_prod_datum(:literal, literal(token.value, :datatype => RDF::XSD.integer))
119
+ add_prod_datum(:literal, literal(token.value, datatype: RDF::XSD.integer))
120
120
  end
121
121
  terminal(:LANGTAG, LANGTAG) do |prod, token, input|
122
122
  add_prod_datum(:language, token.value[1..-1])
123
123
  end
124
- terminal(:PNAME_LN, PNAME_LN, :unescape => true) do |prod, token, input|
124
+ terminal(:PNAME_LN, PNAME_LN, unescape: true) do |prod, token, input|
125
125
  prefix, suffix = token.value.split(":", 2)
126
126
  add_prod_datum(:PrefixedName, ns(prefix, suffix))
127
127
  end
@@ -132,16 +132,16 @@ module SPARQL::Grammar
132
132
  # [4] PrefixDecl := 'PREFIX' PNAME_NS IRI_REF";
133
133
  add_prod_datum(:prefix, prefix && prefix.to_sym)
134
134
  end
135
- terminal(:STRING_LITERAL_LONG1, STRING_LITERAL_LONG1, :unescape => true) do |prod, token, input|
135
+ terminal(:STRING_LITERAL_LONG1, STRING_LITERAL_LONG1, unescape: true) do |prod, token, input|
136
136
  add_prod_datum(:string, token.value[3..-4])
137
137
  end
138
- terminal(:STRING_LITERAL_LONG2, STRING_LITERAL_LONG2, :unescape => true) do |prod, token, input|
138
+ terminal(:STRING_LITERAL_LONG2, STRING_LITERAL_LONG2, unescape: true) do |prod, token, input|
139
139
  add_prod_datum(:string, token.value[3..-4])
140
140
  end
141
- terminal(:STRING_LITERAL1, STRING_LITERAL1, :unescape => true) do |prod, token, input|
141
+ terminal(:STRING_LITERAL1, STRING_LITERAL1, unescape: true) do |prod, token, input|
142
142
  add_prod_datum(:string, token.value[1..-2])
143
143
  end
144
- terminal(:STRING_LITERAL2, STRING_LITERAL2, :unescape => true) do |prod, token, input|
144
+ terminal(:STRING_LITERAL2, STRING_LITERAL2, unescape: true) do |prod, token, input|
145
145
  add_prod_datum(:string, token.value[1..-2])
146
146
  end
147
147
  terminal(:VAR1, VAR1) do |prod, token, input|
@@ -152,7 +152,7 @@ module SPARQL::Grammar
152
152
  end
153
153
 
154
154
  # Keyword terminals
155
- terminal(nil, STR_EXPR, :map => STR_MAP) do |prod, token, input|
155
+ terminal(nil, STR_EXPR, map: STR_MAP) do |prod, token, input|
156
156
  case token.value
157
157
  when '+', '-'
158
158
  case prod
@@ -174,11 +174,11 @@ module SPARQL::Grammar
174
174
  when /ASC|DESC/ then add_prod_datum(:OrderDirection, token.value.downcase.to_sym)
175
175
  when /DISTINCT|REDUCED/ then add_prod_datum(:DISTINCT_REDUCED, token.value.downcase.to_sym)
176
176
  when %r{
177
- ABS|AVG|BNODE|BOUND|CEIL|COALESCE|CONCAT
178
- |CONTAINS|COUNT|DATATYPE|DAY|ENCODE_FOR_URI|EXISTS
179
- |FLOOR|HOURS|IF|GROUP_CONCAT|IRI|LANGMATCHES|LANG|LCASE
180
- |MAX|MD5|MINUTES|MIN|MONTH|NOW|RAND|REPLACE|ROUND|SAMPLE|SECONDS|SEPARATOR
181
- |SHA1|SHA224|SHA256|SHA384|SHA512
177
+ ABS|ALL|AVG|BNODE|BOUND|CEIL|COALESCE|CONCAT
178
+ |CONTAINS|COUNT|DATATYPE|DAY|DEFAULT|ENCODE_FOR_URI|EXISTS
179
+ |FLOOR|HOURS|IF|GRAPH|GROUP_CONCAT|IRI|LANGMATCHES|LANG|LCASE
180
+ |MAX|MD5|MINUTES|MIN|MONTH|NAMED|NOW|RAND|REPLACE|ROUND|SAMPLE|SECONDS|SEPARATOR
181
+ |SHA1|SHA224|SHA256|SHA384|SHA512|SILENT
182
182
  |STRAFTER|STRBEFORE|STRDT|STRENDS|STRLANG|STRLEN|STRSTARTS|STRUUID|SUBSTR|STR|SUM
183
183
  |TIMEZONE|TZ|UCASE|UNDEF|URI|UUID|YEAR
184
184
  |isBLANK|isIRI|isURI|isLITERAL|isNUMERIC|sameTerm
@@ -193,8 +193,6 @@ module SPARQL::Grammar
193
193
  # [2] Query ::= Prologue
194
194
  # ( SelectQuery | ConstructQuery | DescribeQuery | AskQuery )
195
195
  production(:Query) do |input, data, callback|
196
- return unless data[:query]
197
-
198
196
  query = data[:query].first
199
197
 
200
198
  # Add prefix
@@ -377,8 +375,197 @@ module SPARQL::Grammar
377
375
  end
378
376
  end
379
377
 
380
- # [54] GroupGraphPatternSub ::= TriplesBlock?
381
- # ( GraphPatternNotTriples '.'? TriplesBlock? )*
378
+ # [29] Update ::= Prologue (Update1 (";" Update)? )?
379
+ production(:Update) do |input, data, callback|
380
+ update = data[:update] || SPARQL::Algebra::Expression(:update)
381
+
382
+ # Add prefix
383
+ if data[:PrefixDecl]
384
+ pfx = data[:PrefixDecl].shift
385
+ data[:PrefixDecl].each {|p| pfx.merge!(p)}
386
+ pfx.operands[1] = update
387
+ update = pfx
388
+ end
389
+
390
+ # Add base
391
+ update = SPARQL::Algebra::Expression[:base, data[:BaseDecl].first, update] if data[:BaseDecl]
392
+
393
+ # Don't use update operator twice, if we can help it
394
+ input[:update] = update
395
+ end
396
+ production(:_Update_3) do |input, data, callback|
397
+ if data[:update]
398
+ if input[:update].is_a?(SPARQL::Algebra::Operator::Update)
399
+ # Append operands
400
+ input[:update] = SPARQL::Algebra::Expression(:update, *(input[:update].operands + data[:update].operands))
401
+ else
402
+ add_prod_datum(:update, data[:update])
403
+ end
404
+ end
405
+ end
406
+
407
+ # [30] Update1 ::= Load | Clear | Drop | Add | Move | Copy | Create | InsertData | DeleteData | DeleteWhere | Modify
408
+ production(:Update1) do |input, data, callback|
409
+ input[:update] = SPARQL::Algebra::Expression.for(:update, data[:update_op])
410
+ end
411
+
412
+ # [31] Load ::= "LOAD" "SILENT"? iri ("INTO" GraphRef)?
413
+ production(:Load) do |input, data, callback|
414
+ args = []
415
+ args << :silent if data[:silent]
416
+ args += Array(data[:iri])
417
+ input[:update_op] = SPARQL::Algebra::Expression(:load, *args)
418
+ end
419
+
420
+ # [32] Clear ::= "CLEAR" "SILENT"? GraphRefAll
421
+ production(:Clear) do |input, data, callback|
422
+ args = []
423
+ %w(silent default named all).map(&:to_sym).each do |s|
424
+ args << s if data[s]
425
+ end
426
+ args += Array(data[:iri])
427
+ input[:update_op] = SPARQL::Algebra::Expression(:clear, *args)
428
+ end
429
+
430
+ # [33] Drop ::= "DROP" "SILENT"? GraphRefAll
431
+ production(:Drop) do |input, data, callback|
432
+ args = []
433
+ %w(silent default named all).map(&:to_sym).each do |s|
434
+ args << s if data[s]
435
+ end
436
+ args += Array(data[:iri])
437
+ input[:update_op] = SPARQL::Algebra::Expression(:drop, *args)
438
+ end
439
+
440
+ # [34] Create ::= "CREATE" "SILENT"? GraphRef
441
+ production(:Create) do |input, data, callback|
442
+ args = []
443
+ args << :silent if data[:silent]
444
+ args += Array(data[:iri])
445
+ input[:update_op] = SPARQL::Algebra::Expression(:create, *args)
446
+ end
447
+
448
+ # [35] Add ::= "ADD" "SILENT"? GraphOrDefault "TO" GraphOrDefault
449
+ production(:Add) do |input, data, callback|
450
+ args = []
451
+ args << :silent if data[:silent]
452
+ args += data[:GraphOrDefault]
453
+ input[:update_op] = SPARQL::Algebra::Expression(:add, *args)
454
+ end
455
+
456
+ # [36] Move ::= "MOVE" "SILENT"? GraphOrDefault "TO" GraphOrDefault
457
+ production(:Move) do |input, data, callback|
458
+ args = []
459
+ args << :silent if data[:silent]
460
+ args += data[:GraphOrDefault]
461
+ input[:update_op] = SPARQL::Algebra::Expression(:move, *args)
462
+ end
463
+
464
+ # [37] Copy ::= "COPY" "SILENT"? GraphOrDefault "TO" GraphOrDefault
465
+ production(:Copy) do |input, data, callback|
466
+ args = []
467
+ args << :silent if data[:silent]
468
+ args += data[:GraphOrDefault]
469
+ input[:update_op] = SPARQL::Algebra::Expression(:copy, *args)
470
+ end
471
+
472
+ # [38] InsertData ::= "INSERT DATA" QuadData
473
+ production(:InsertData) do |input, data, callback|
474
+ input[:update_op] = SPARQL::Algebra::Expression(:insertData, data[:pattern])
475
+ end
476
+
477
+ # [39] DeleteData ::= "DELETE DATA" QuadData
478
+ production(:DeleteData) do |input, data, callback|
479
+ raise Error, "DeleteData contains BNode operands: #{data[:pattern].to_sse}" if data[:pattern].first.has_blank_nodes?
480
+ input[:update_op] = SPARQL::Algebra::Expression(:deleteData, data[:pattern])
481
+ end
482
+
483
+ # [40] DeleteWhere ::= "DELETE WHERE" QuadPattern
484
+ start_production(:DeleteWhere) do |input, data, callback|
485
+ # Generate BNodes instead of non-distinguished variables. BNodes are not legal, but this will generate them rather than non-distinguished variables so they can be detected.
486
+ self.clear_bnode_cache
487
+ end
488
+ production(:DeleteWhere) do |input, data, callback|
489
+ raise Error, "DeleteWhere contains BNode operands: #{data[:pattern].to_sse}" if data[:pattern].first.has_blank_nodes?
490
+ self.nd_var_gen = "0"
491
+ input[:update_op] = SPARQL::Algebra::Expression(:deleteWhere, data[:pattern])
492
+ end
493
+
494
+ # [41] Modify ::= ("WITH" iri)? ( DeleteClause InsertClause? | InsertClause) UsingClause* "WHERE" GroupGraphPattern
495
+ production(:Modify) do |input, data, callback|
496
+ query = data[:query].first if data[:query]
497
+ query = SPARQL::Algebra::Expression.for(:using, data[:using], query) if data[:using]
498
+ operands = [query, data[:delete], data[:insert]].compact
499
+ operands = [SPARQL::Algebra::Expression.for(:with, data[:iri].first, *operands)] if data[:iri]
500
+ input[:update_op] = SPARQL::Algebra::Expression(:modify, *operands)
501
+ end
502
+
503
+ # [42] DeleteClause ::= "DELETE" QuadPattern
504
+ start_production(:DeleteClause) do |input, data, callback|
505
+ # Generate BNodes instead of non-distinguished variables. BNodes are not legal, but this will generate them rather than non-distinguished variables so they can be detected.
506
+ self.clear_bnode_cache
507
+ end
508
+ production(:DeleteClause) do |input, data, callback|
509
+ raise Error, "DeleteClause contains BNode operands: #{data[:pattern].to_sse}" if data[:pattern].first.has_blank_nodes?
510
+ self.nd_var_gen = "0"
511
+ input[:delete] = SPARQL::Algebra::Expression(:delete, data[:pattern])
512
+ end
513
+
514
+ # [43] InsertClause ::= "INSERT" QuadPattern
515
+ production(:InsertClause) do |input, data, callback|
516
+ input[:insert] = SPARQL::Algebra::Expression(:insert, data[:pattern])
517
+ end
518
+
519
+ # [44] UsingClause ::= "USING" ( iri | "NAMED" iri)
520
+ production(:UsingClause) do |input, data, callback|
521
+ add_prod_data(:using, data[:iri].first)
522
+ end
523
+ production(:_UsingClause_2) do |input, data, callback|
524
+ add_prod_data(:iri, [:named, data[:iri].first])
525
+ end
526
+
527
+ # [45] GraphOrDefault ::= "DEFAULT" | "GRAPH"? iri
528
+ production(:GraphOrDefault) do |input, data, callback|
529
+ if data[:default]
530
+ add_prod_datum(:GraphOrDefault, :default)
531
+ else
532
+ add_prod_data(:GraphOrDefault, data[:iri].first)
533
+ end
534
+ end
535
+
536
+ # [46] GraphRef ::= "GRAPH" iri
537
+ production(:GraphRef) do |input, data, callback|
538
+ add_prod_data(:iri, data[:iri].first)
539
+ end
540
+ # [47] GraphRefAll ::= GraphRef | "DEFAULT" | "NAMED" | "ALL"
541
+ #production(:GraphRefAll) do |input, data, callback|
542
+ # add_prod_datum(:GraphRefAll, data)
543
+ #end
544
+
545
+ # [49] QuadData ::= "{" Quads "}"
546
+ # QuadData is like QuadPattern, except without BNodes
547
+ start_production(:QuadData) do |input, data, callback|
548
+ # Generate BNodes instead of non-distinguished variables
549
+ self.clear_bnode_cache
550
+ end
551
+ production(:QuadData) do |input, data, callback|
552
+ # Transform using statements instead of patterns, and verify there are no variables
553
+ raise Error, "QuadData contains variable operands: #{data[:pattern].to_sse}" if data[:pattern].first.variable?
554
+ self.nd_var_gen = "0"
555
+ input[:pattern] = data[:pattern]
556
+ end
557
+
558
+ # [51] QuadsNotTriples ::= "GRAPH" VarOrIri "{" TriplesTemplate? "}"
559
+ production(:QuadsNotTriples) do |input, data, callback|
560
+ add_prod_datum(:pattern, [SPARQL::Algebra::Expression.for(:graph, data[:VarOrIri].last, data[:pattern])])
561
+ end
562
+
563
+ # [52] TriplesTemplate ::= TriplesSameSubject ("." TriplesTemplate? )?
564
+ production(:TriplesTemplate) do |input, data, callback|
565
+ add_prod_datum(:pattern, data[:pattern])
566
+ end
567
+
568
+ # [54] GroupGraphPatternSub ::= TriplesBlock? (GraphPatternNotTriples "."? TriplesBlock? )*
382
569
  production(:GroupGraphPatternSub) do |input, data, callback|
383
570
  debug("GroupGraphPatternSub") {"q #{data[:query].inspect}"}
384
571
 
@@ -522,7 +709,6 @@ module SPARQL::Grammar
522
709
 
523
710
  # [66] MinusGraphPattern ::= 'MINUS' GroupGraphPattern
524
711
  production(:MinusGraphPattern) do |input, data, callback|
525
- expr = nil
526
712
  query = data[:query] ? data[:query].first : SPARQL::Algebra::Operator::BGP.new
527
713
  add_prod_data(:minus, query)
528
714
  end
@@ -586,7 +772,7 @@ module SPARQL::Grammar
586
772
  # [73] ConstructTemplate ::= '{' ConstructTriples? '}'
587
773
  start_production(:ConstructTemplate) do |input, data, callback|
588
774
  # Generate BNodes instead of non-distinguished variables
589
- self.nd_var_gen = false
775
+ self.clear_bnode_cache
590
776
  end
591
777
  production(:ConstructTemplate) do |input, data, callback|
592
778
  # Generate BNodes instead of non-distinguished variables
@@ -605,7 +791,7 @@ module SPARQL::Grammar
605
791
  # ( ';' ( Verb ObjectList )? )*
606
792
  start_production(:PropertyListNotEmpty) do |input, data, callback|
607
793
  subject = input[:VarOrTerm] || input[:TriplesNode] || input[:GraphNode]
608
- error(nil, "Expected VarOrTerm or TriplesNode or GraphNode", :production => :PropertyListNotEmpty) if validate? && !subject
794
+ error(nil, "Expected VarOrTerm or TriplesNode or GraphNode", production: :PropertyListNotEmpty) if validate? && !subject
609
795
  data[:Subject] = subject
610
796
  end
611
797
  production(:PropertyListNotEmpty) do |input, data, callback|
@@ -616,8 +802,8 @@ module SPARQL::Grammar
616
802
  start_production(:ObjectList) do |input, data, callback|
617
803
  # Called after Verb. The prod_data stack should have Subject and Verb elements
618
804
  data[:Subject] = prod_data[:Subject]
619
- error(nil, "Expected Subject", :production => :ObjectList) if !prod_data[:Subject] && validate?
620
- error(nil, "Expected Verb", :production => :ObjectList) if !prod_data[:Verb] && validate?
805
+ error(nil, "Expected Subject", production: :ObjectList) if !prod_data[:Subject] && validate?
806
+ error(nil, "Expected Verb", production: :ObjectList) if !prod_data[:Verb] && validate?
621
807
  data[:Subject] = prod_data[:Subject]
622
808
  data[:Verb] = prod_data[:Verb].to_a.last
623
809
  end
@@ -629,7 +815,7 @@ module SPARQL::Grammar
629
815
  production(:Object) do |input, data, callback|
630
816
  object = data[:VarOrTerm] || data[:TriplesNode] || data[:GraphNode]
631
817
  if object
632
- add_pattern(:Object, :subject => prod_data[:Subject], :predicate => prod_data[:Verb], :object => object)
818
+ add_pattern(:Object, subject: prod_data[:Subject], predicate: prod_data[:Verb], object: object)
633
819
  add_prod_datum(:pattern, data[:pattern])
634
820
  end
635
821
  end
@@ -642,7 +828,7 @@ module SPARQL::Grammar
642
828
  # [83] PropertyListNotEmptyPath ::= ( VerbPath | VerbSimple ) ObjectList ( ';' ( ( VerbPath | VerbSimple ) ObjectList )? )*
643
829
  start_production(:PropertyListNotEmptyPath) do |input, data, callback|
644
830
  subject = input[:VarOrTerm]
645
- error(nil, "Expected VarOrTerm", :production => ::PropertyListNotEmptyPath) if validate? && !subject
831
+ error(nil, "Expected VarOrTerm", production: ::PropertyListNotEmptyPath) if validate? && !subject
646
832
  data[:Subject] = subject
647
833
  end
648
834
  production(:PropertyListNotEmptyPath) do |input, data, callback|
@@ -1064,7 +1250,7 @@ module SPARQL::Grammar
1064
1250
  else input.to_s.dup
1065
1251
  end
1066
1252
  @input.encode!(Encoding::UTF_8) if @input.respond_to?(:encode!)
1067
- @options = {:anon_base => "b0", :validate => false}.merge(options)
1253
+ @options = {anon_base: "b0", validate: false}.merge(options)
1068
1254
  @options[:debug] ||= case
1069
1255
  when options[:progress] then 2
1070
1256
  when options[:validate] then 1
@@ -1122,10 +1308,10 @@ module SPARQL::Grammar
1122
1308
  # @see http://www.w3.org/TR/sparql11-query/#sparqlAlgebra
1123
1309
  # @see http://axel.deri.ie/sparqltutorial/ESWC2007_SPARQL_Tutorial_unit2b.pdf
1124
1310
  def parse(prod = START)
1125
- ll1_parse(@input, prod.to_sym, @options.merge(:branch => BRANCH,
1126
- :first => FIRST,
1127
- :follow => FOLLOW,
1128
- :whitespace => WS)
1311
+ ll1_parse(@input, prod.to_sym, @options.merge(branch: BRANCH,
1312
+ first: FIRST,
1313
+ follow: FOLLOW,
1314
+ whitespace: WS)
1129
1315
  ) do |context, *data|
1130
1316
  case context
1131
1317
  when :trace
@@ -1152,9 +1338,11 @@ module SPARQL::Grammar
1152
1338
  nil
1153
1339
  when prod_data[:query]
1154
1340
  prod_data[:query].to_a.length == 1 ? prod_data[:query].first : prod_data[:query]
1341
+ when prod_data[:update]
1342
+ prod_data[:update]
1155
1343
  else
1156
1344
  key = prod_data.keys.first
1157
- [key] + prod_data[key] # Creates [:key, [:triple], ...]
1345
+ [key] + Array(prod_data[key]) # Creates [:key, [:triple], ...]
1158
1346
  end
1159
1347
  end
1160
1348
 
@@ -1176,7 +1364,7 @@ module SPARQL::Grammar
1176
1364
  #
1177
1365
  # @example
1178
1366
  # prefixes = {
1179
- # :dc => RDF::URI('http://purl.org/dc/terms/'),
1367
+ # dc: RDF::URI('http://purl.org/dc/terms/'),
1180
1368
  # }
1181
1369
  #
1182
1370
  # @param [Hash{Symbol => RDF::URI}] prefixes
@@ -1254,6 +1442,12 @@ module SPARQL::Grammar
1254
1442
  # Used for generating BNode labels
1255
1443
  attr_accessor :nd_var_gen
1256
1444
 
1445
+ # Reset the bnode cache, always generating new nodes, and start generating BNodes instead of non-distinguished variables
1446
+ def clear_bnode_cache
1447
+ @nd_var_gen = false
1448
+ @bnode_cache = {}
1449
+ end
1450
+
1257
1451
  # Generate a BNode identifier
1258
1452
  def bnode(id = nil)
1259
1453
  if @nd_var_gen
@@ -1334,7 +1528,7 @@ module SPARQL::Grammar
1334
1528
  "options: #{options.inspect}, " +
1335
1529
  "validate: #{validate?.inspect}, "
1336
1530
  end
1337
- RDF::Literal.new(value, options.merge(:validate => validate?))
1531
+ RDF::Literal.new(value, options.merge(validate: validate?))
1338
1532
  end
1339
1533
 
1340
1534
  # Take collection of objects and create RDF Collection using rdf:first, rdf:rest and rdf:nil
@@ -1349,16 +1543,16 @@ module SPARQL::Grammar
1349
1543
  last = list.pop
1350
1544
 
1351
1545
  list.each do |r|
1352
- add_pattern(:Collection, :subject => first, :predicate => RDF["first"], :object => r)
1546
+ add_pattern(:Collection, subject: first, predicate: RDF["first"], object: r)
1353
1547
  rest = bnode()
1354
- add_pattern(:Collection, :subject => first, :predicate => RDF["rest"], :object => rest)
1548
+ add_pattern(:Collection, subject: first, predicate: RDF["rest"], object: rest)
1355
1549
  first = rest
1356
1550
  end
1357
1551
 
1358
1552
  if last
1359
- add_pattern(:Collection, :subject => first, :predicate => RDF["first"], :object => last)
1553
+ add_pattern(:Collection, subject: first, predicate: RDF["first"], object: last)
1360
1554
  end
1361
- add_pattern(:Collection, :subject => first, :predicate => RDF["rest"], :object => RDF["nil"])
1555
+ add_pattern(:Collection, subject: first, predicate: RDF["rest"], object: RDF["nil"])
1362
1556
  end
1363
1557
 
1364
1558
  # add a pattern
@@ -1375,14 +1569,14 @@ module SPARQL::Grammar
1375
1569
  end
1376
1570
  if validate? && !v.is_a?(RDF::Term)
1377
1571
  error("add_pattern", "Expected #{r} to be a resource, but it was #{v.inspect}",
1378
- :production => production)
1572
+ production: production)
1379
1573
  end
1380
1574
  triple[r] = v
1381
1575
  end
1382
1576
  add_prod_datum(:pattern, RDF::Query::Pattern.new(triple))
1383
1577
  end
1384
1578
 
1385
- # Flatten a Data in form of :filter => [op+ bgp?], without a query into filter and query creating exprlist, if necessary
1579
+ # Flatten a Data in form of filter: [op+ bgp?], without a query into filter and query creating exprlist, if necessary
1386
1580
  # @return [Array[:expr, query]]
1387
1581
  def flatten_filter(data)
1388
1582
  query = data.pop if data.last.is_a?(SPARQL::Algebra::Query)