sparql 3.2.0 → 3.2.4

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 (92) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +59 -38
  3. data/VERSION +1 -1
  4. data/bin/sparql +2 -31
  5. data/lib/rack/sparql/conneg.rb +22 -1
  6. data/lib/sinatra/sparql/extensions.rb +1 -1
  7. data/lib/sinatra/sparql.rb +57 -12
  8. data/lib/sparql/algebra/expression.rb +63 -10
  9. data/lib/sparql/algebra/extensions.rb +39 -35
  10. data/lib/sparql/algebra/operator/abs.rb +1 -1
  11. data/lib/sparql/algebra/operator/adjust.rb +69 -0
  12. data/lib/sparql/algebra/operator/alt.rb +1 -1
  13. data/lib/sparql/algebra/operator/avg.rb +3 -1
  14. data/lib/sparql/algebra/operator/bgp.rb +9 -1
  15. data/lib/sparql/algebra/operator/clear.rb +13 -3
  16. data/lib/sparql/algebra/operator/construct.rb +1 -1
  17. data/lib/sparql/algebra/operator/count.rb +36 -6
  18. data/lib/sparql/algebra/operator/create.rb +5 -4
  19. data/lib/sparql/algebra/operator/dataset.rb +29 -11
  20. data/lib/sparql/algebra/operator/day.rb +2 -2
  21. data/lib/sparql/algebra/operator/delete.rb +3 -1
  22. data/lib/sparql/algebra/operator/delete_data.rb +1 -1
  23. data/lib/sparql/algebra/operator/delete_where.rb +1 -1
  24. data/lib/sparql/algebra/operator/distinct.rb +2 -2
  25. data/lib/sparql/algebra/operator/divide.rb +1 -1
  26. data/lib/sparql/algebra/operator/drop.rb +15 -6
  27. data/lib/sparql/algebra/operator/encode_for_uri.rb +2 -4
  28. data/lib/sparql/algebra/operator/exprlist.rb +3 -1
  29. data/lib/sparql/algebra/operator/extend.rb +73 -5
  30. data/lib/sparql/algebra/operator/filter.rb +6 -1
  31. data/lib/sparql/algebra/operator/function_call.rb +64 -0
  32. data/lib/sparql/algebra/operator/graph.rb +57 -7
  33. data/lib/sparql/algebra/operator/group.rb +105 -6
  34. data/lib/sparql/algebra/operator/group_concat.rb +25 -1
  35. data/lib/sparql/algebra/operator/hours.rb +2 -2
  36. data/lib/sparql/algebra/operator/if.rb +10 -10
  37. data/lib/sparql/algebra/operator/insert.rb +3 -1
  38. data/lib/sparql/algebra/operator/insert_data.rb +1 -1
  39. data/lib/sparql/algebra/operator/is_blank.rb +1 -2
  40. data/lib/sparql/algebra/operator/is_iri.rb +1 -2
  41. data/lib/sparql/algebra/operator/is_literal.rb +1 -2
  42. data/lib/sparql/algebra/operator/is_numeric.rb +1 -2
  43. data/lib/sparql/algebra/operator/join.rb +39 -5
  44. data/lib/sparql/algebra/operator/lcase.rb +2 -3
  45. data/lib/sparql/algebra/operator/left_join.rb +27 -9
  46. data/lib/sparql/algebra/operator/max.rb +3 -1
  47. data/lib/sparql/algebra/operator/min.rb +4 -2
  48. data/lib/sparql/algebra/operator/minus.rb +46 -6
  49. data/lib/sparql/algebra/operator/minutes.rb +2 -2
  50. data/lib/sparql/algebra/operator/modify.rb +21 -0
  51. data/lib/sparql/algebra/operator/month.rb +2 -2
  52. data/lib/sparql/algebra/operator/multiply.rb +1 -1
  53. data/lib/sparql/algebra/operator/notoneof.rb +12 -3
  54. data/lib/sparql/algebra/operator/order.rb +44 -0
  55. data/lib/sparql/algebra/operator/path_opt.rb +9 -65
  56. data/lib/sparql/algebra/operator/path_plus.rb +18 -10
  57. data/lib/sparql/algebra/operator/path_range.rb +178 -0
  58. data/lib/sparql/algebra/operator/path_star.rb +7 -4
  59. data/lib/sparql/algebra/operator/path_zero.rb +110 -0
  60. data/lib/sparql/algebra/operator/plus.rb +8 -6
  61. data/lib/sparql/algebra/operator/project.rb +64 -5
  62. data/lib/sparql/algebra/operator/reduced.rb +3 -3
  63. data/lib/sparql/algebra/operator/regex.rb +1 -1
  64. data/lib/sparql/algebra/operator/reverse.rb +12 -1
  65. data/lib/sparql/algebra/operator/sample.rb +3 -1
  66. data/lib/sparql/algebra/operator/seconds.rb +2 -2
  67. data/lib/sparql/algebra/operator/seq.rb +4 -4
  68. data/lib/sparql/algebra/operator/sequence.rb +14 -1
  69. data/lib/sparql/algebra/operator/service.rb +86 -0
  70. data/lib/sparql/algebra/operator/strlang.rb +1 -2
  71. data/lib/sparql/algebra/operator/subtract.rb +10 -6
  72. data/lib/sparql/algebra/operator/sum.rb +9 -7
  73. data/lib/sparql/algebra/operator/table.rb +50 -7
  74. data/lib/sparql/algebra/operator/timezone.rb +2 -2
  75. data/lib/sparql/algebra/operator/triple.rb +51 -0
  76. data/lib/sparql/algebra/operator/tz.rb +2 -2
  77. data/lib/sparql/algebra/operator/ucase.rb +1 -1
  78. data/lib/sparql/algebra/operator/update.rb +22 -1
  79. data/lib/sparql/algebra/operator/using.rb +18 -1
  80. data/lib/sparql/algebra/operator/with.rb +1 -1
  81. data/lib/sparql/algebra/operator/year.rb +2 -2
  82. data/lib/sparql/algebra/operator.rb +69 -22
  83. data/lib/sparql/algebra/query.rb +5 -3
  84. data/lib/sparql/algebra.rb +42 -6
  85. data/lib/sparql/grammar/meta.rb +1367 -267
  86. data/lib/sparql/grammar/parser11.rb +842 -331
  87. data/lib/sparql/grammar/terminals11.rb +2 -2
  88. data/lib/sparql/grammar.rb +6 -4
  89. data/lib/sparql/results.rb +3 -2
  90. data/lib/sparql/server.rb +93 -0
  91. data/lib/sparql.rb +8 -5
  92. metadata +49 -13
@@ -15,7 +15,7 @@ module SPARQL::Grammar
15
15
 
16
16
  # Builtin functions
17
17
  BUILTINS = %w{
18
- ABS BNODE CEIL COALESCE CONCAT
18
+ ABS ADJUST BNODE CEIL COALESCE CONCAT
19
19
  CONTAINS DATATYPE DAY ENCODE_FOR_URI
20
20
  FLOOR HOURS IF IRI LANGMATCHES LANG LCASE
21
21
  MD5 MINUTES MONTH NOW RAND ROUND SECONDS
@@ -119,7 +119,7 @@ module SPARQL::Grammar
119
119
  input[:literal] = literal(token.value, datatype: RDF::XSD.integer)
120
120
  end
121
121
  terminal(:LANGTAG, LANGTAG) do |prod, token, input|
122
- add_prod_datum(:language, token.value[1..-1])
122
+ input[:language] = token.value[1..-1]
123
123
  end
124
124
  terminal(:PNAME_LN, PNAME_LN, unescape: true) do |prod, token, input|
125
125
  prefix, suffix = token.value.split(":", 2)
@@ -177,7 +177,7 @@ module SPARQL::Grammar
177
177
  when /ASC|DESC/ then input[:OrderDirection] = token.value.downcase.to_sym
178
178
  when /DISTINCT|REDUCED/ then input[:DISTINCT_REDUCED] = token.value.downcase.to_sym
179
179
  when %r{
180
- ABS|ALL|AVG|BNODE|BOUND|CEIL|COALESCE|CONCAT
180
+ ABS|ADJUST|ALL|AVG|BNODE|BOUND|CEIL|COALESCE|CONCAT
181
181
  |CONTAINS|COUNT|DATATYPE|DAY|DEFAULT|ENCODE_FOR_URI|EXISTS
182
182
  |FLOOR|HOURS|IF|GRAPH|GROUP_CONCAT|IRI|LANGMATCHES|LANG|LCASE
183
183
  |MAX|MD5|MINUTES|MIN|MONTH|NAMED|NOW|RAND|REPLACE|ROUND|SAMPLE|SECONDS|SEPARATOR
@@ -194,10 +194,13 @@ module SPARQL::Grammar
194
194
  end
195
195
 
196
196
  # Productions
197
- # [2] Query ::= Prologue
198
- # ( SelectQuery | ConstructQuery | DescribeQuery | AskQuery )
197
+
198
+ # [2] Query ::= Prologue ( SelectQuery | ConstructQuery | DescribeQuery | AskQuery )
199
+ #
200
+ # Inputs from `data` are `:query` and potentially `:PrefixDecl`.
201
+ # Output to prod_data is the Queryable object.
199
202
  production(:Query) do |input, data, callback|
200
- query = data[:query].first
203
+ query = data[:query].first if data[:query]
201
204
 
202
205
  # Add prefix
203
206
  if data[:PrefixDecl]
@@ -213,7 +216,10 @@ module SPARQL::Grammar
213
216
  add_prod_datum(:query, query)
214
217
  end
215
218
 
216
- # [4] Prologue ::= ( BaseDecl | PrefixDecl )*
219
+ # [4] Prologue ::= ( BaseDecl | PrefixDecl )*
220
+ #
221
+ # Inputs from `data` are `:PrefixDecl` and `:BaseDecl`.
222
+ # Output to prod_data is the same, if `#resolve_iris?` is `false`.
217
223
  production(:Prologue) do |input, data, callback|
218
224
  unless resolve_iris?
219
225
  # Only output if we're not resolving URIs internally
@@ -222,7 +228,10 @@ module SPARQL::Grammar
222
228
  end
223
229
  end
224
230
 
225
- # [5] BaseDecl ::= 'BASE' IRI_REF
231
+ # [5] BaseDecl ::= 'BASE' IRI_REF
232
+ #
233
+ # Input from `data` is `:BaseDecl`.
234
+ # Output to prod_data is the same, if `#resolve_iris?` is `false`.
226
235
  production(:BaseDecl) do |input, data, callback|
227
236
  iri = data[:iri]
228
237
  debug("BaseDecl") {"Defined base as #{iri}"}
@@ -230,7 +239,10 @@ module SPARQL::Grammar
230
239
  add_prod_datum(:BaseDecl, iri) unless resolve_iris?
231
240
  end
232
241
 
233
- # [6] PrefixDecl ::= 'PREFIX' PNAME_NS IRI_REF
242
+ # [6] PrefixDecl ::= 'PREFIX' PNAME_NS IRI_REF
243
+ #
244
+ # Inputs from `data` are `:iri`, and `:prefix`.
245
+ # Output to prod_data is the `:PrefixDecl`, and `Operator::Prefix`, unless there is no `:iri`.
234
246
  production(:PrefixDecl) do |input, data, callback|
235
247
  if data[:iri]
236
248
  pfx = data[:prefix]
@@ -240,21 +252,41 @@ module SPARQL::Grammar
240
252
  end
241
253
  end
242
254
 
243
- # [7] SelectQuery ::= SelectClause DatasetClause* WhereClause SolutionModifier
255
+ # [7] SelectQuery ::= SelectClause DatasetClause* WhereClause SolutionModifier
256
+ #
257
+ # Inputs from `data` are merged into a Queryable object.
258
+ # Output to prod_data is `:query`.
244
259
  production(:SelectQuery) do |input, data, callback|
245
260
  query = merge_modifiers(data)
246
261
  add_prod_datum :query, query
247
262
  end
248
263
 
249
- # [8] SubSelect ::= SelectClause WhereClause SolutionModifier
264
+ # [8] SubSelect ::= SelectClause WhereClause SolutionModifier
265
+ #
266
+ # Inputs from `data` are merged into a Queryable object.
267
+ # Output to prod_data is `:query`.
250
268
  production(:SubSelect) do |input, data, callback|
251
269
  query = merge_modifiers(data)
252
270
  add_prod_datum :query, query
253
271
  end
254
272
 
255
- # [9] SelectClause ::= 'SELECT' ( 'DISTINCT' | 'REDUCED' )? ( ( Var | ( '(' Expression 'AS' Var ')' ) )+ | '*' )
256
-
273
+ # [9] SelectClause ::= 'SELECT' ( 'DISTINCT' | 'REDUCED' )? ( ( Var | ( '(' Expression 'AS' Var ')' ) )+ | '*' )
274
+ # [9.2] _SelectClause_2 ::= ( ( Var | ( '(' Expression 'AS' Var ')' ) )+ | '*' )
275
+ #
276
+ # Inputs from `data` are `:Expression` and `:Var`.
277
+ # Output to prod_data is `:Var`.
278
+ production(:_SelectClause_2) do |input, data, callback|
279
+ if data[:MultiplicativeExpression]
280
+ add_prod_datum :Var, %i(*)
281
+ else
282
+ add_prod_datum :extend, data[:extend]
283
+ add_prod_datum :Var, data[:Var]
284
+ end
285
+ end
257
286
  # [9.8] _SelectClause_8 ::= ( '(' Expression 'AS' Var ')' )
287
+ #
288
+ # Inputs from `data` are `:Expression` and `:Var`.
289
+ # Output to prod_data is `:extend`.
258
290
  production(:_SelectClause_8) do |input, data, callback|
259
291
  add_prod_datum :extend, [data[:Expression].unshift(data[:Var].first)]
260
292
  end
@@ -267,6 +299,10 @@ module SPARQL::Grammar
267
299
  # 'WHERE' '{' TriplesTemplate? '}'
268
300
  # SolutionModifier
269
301
  # )
302
+ #
303
+ # Inputs from `data` are `:pattern` and optionally `:ConstructTemplate`.
304
+ # If there is no `:query` in data, one is constructed by creating a BGP from all values of `:pattern`.
305
+ # Output to prod_data is `:query` made by creating a Operator::Construct using any `:ConstructTemplate` or `:pattern` and the query with merged modifiers.
270
306
  production(:ConstructQuery) do |input, data, callback|
271
307
  data[:query] ||= [SPARQL::Algebra::Operator::BGP.new(*data[:pattern])]
272
308
  query = merge_modifiers(data)
@@ -274,44 +310,64 @@ module SPARQL::Grammar
274
310
  add_prod_datum :query, SPARQL::Algebra::Expression[:construct, template, query]
275
311
  end
276
312
 
277
- # [11] DescribeQuery ::= 'DESCRIBE' ( VarOrIri+ | '*' )
278
- # DatasetClause* WhereClause? SolutionModifier
313
+ # [11] DescribeQuery ::= 'DESCRIBE' ( VarOrIri+ | '*' )
314
+ # DatasetClause* WhereClause? SolutionModifier
315
+ #
316
+ # Inputs from `data` are merged into a Queryable object.
317
+ # Outputs are created using any `:VarOrIri` in data is used as an argument, along with the Queryable object to create an `Operator::Describe` object, which is added to `:query` in prod datea.
279
318
  production(:DescribeQuery) do |input, data, callback|
280
319
  query = merge_modifiers(data)
281
320
  to_describe = Array(data[:VarOrIri])
282
321
  add_prod_datum :query, SPARQL::Algebra::Expression[:describe, to_describe, query]
283
322
  end
284
323
 
285
- # [12] AskQuery ::= 'ASK' DatasetClause* WhereClause
324
+ # [12] AskQuery ::= 'ASK' DatasetClause* WhereClause
325
+ #
326
+ # Inputs from `data` are merged into a Queryable object.
327
+ # Output to prod_data is `:query` made by creating a Operator::Ask using the query with merged modifiers.
286
328
  production(:AskQuery) do |input, data, callback|
287
329
  query = merge_modifiers(data)
288
330
  add_prod_datum :query, SPARQL::Algebra::Expression[:ask, query]
289
331
  end
290
332
 
291
- # [14] DefaultGraphClause ::= SourceSelector
333
+ # [14] DefaultGraphClause ::= SourceSelector
334
+ #
335
+ # Input from `data` is `:iri`.
336
+ # Output to prod_data is `:dataset` taken from `:iri`.
292
337
  production(:DefaultGraphClause) do |input, data, callback|
293
338
  add_prod_datum :dataset, data[:iri]
294
339
  end
295
340
 
296
- # [15] NamedGraphClause ::= 'NAMED' SourceSelector
341
+ # [15] NamedGraphClause ::= 'NAMED' SourceSelector
342
+ #
343
+ # Input from `data` is `:iri`.
344
+ # Output to prod_data is `:dataset` taken from `:iri`.
297
345
  production(:NamedGraphClause) do |input, data, callback|
298
346
  add_prod_data :dataset, [:named, data[:iri]]
299
347
  end
300
348
 
301
- # [18] SolutionModifier ::= GroupClause? HavingClause? OrderClause? LimitOffsetClauses?
349
+ # [18] SolutionModifier ::= GroupClause? HavingClause? OrderClause? LimitOffsetClauses?
302
350
 
303
- # [19] GroupClause ::= 'GROUP' 'BY' GroupCondition+
351
+ # [19] GroupClause ::= 'GROUP' 'BY' GroupCondition+
352
+ #
353
+ # Input from `data` is `:GroupCondition`.
354
+ # Output to prod_data is `:group` taken from `:GroupCondition`.
304
355
  production(:GroupClause) do |input, data, callback|
305
356
  add_prod_data :group, data[:GroupCondition]
306
357
  end
307
358
 
308
- # [20] GroupCondition ::= BuiltInCall | FunctionCall
309
- # | '(' Expression ( 'AS' Var )? ')' | Var
359
+ # [20] GroupCondition ::= BuiltInCall | FunctionCall
360
+ # | '(' Expression ( 'AS' Var )? ')' | Var
361
+ #
362
+ # Output to prod_data is `:GroupCondition` taken from first value in data.
310
363
  production(:GroupCondition) do |input, data, callback|
311
364
  add_prod_datum :GroupCondition, data.values.first
312
365
  end
313
366
 
314
367
  # _GroupCondition_1 ::= '(' Expression ( 'AS' Var )? ')'
368
+ #
369
+ # Input from `data` is `:Expression` and optionally `:Var`.
370
+ # Output to prod_data is `:GroupCondition` taken from `:Expression` prepended by any value of `:Var`.
315
371
  production(:_GroupCondition_1) do |input, data, callback|
316
372
  cond = if data[:Var]
317
373
  [data[:Expression].unshift(data[:Var].first)]
@@ -321,12 +377,18 @@ module SPARQL::Grammar
321
377
  add_prod_datum(:GroupCondition, cond)
322
378
  end
323
379
 
324
- # [21] HavingClause ::= 'HAVING' HavingCondition+
380
+ # [21] HavingClause ::= 'HAVING' HavingCondition+
381
+ #
382
+ # Input from `data` is TODO.
383
+ # Output to prod_data is TODO.
325
384
  production(:HavingClause) do |input, data, callback|
326
385
  add_prod_datum(:having, data[:Constraint])
327
386
  end
328
387
 
329
- # [23] OrderClause ::= 'ORDER' 'BY' OrderCondition+
388
+ # [23] OrderClause ::= 'ORDER' 'BY' OrderCondition+
389
+ #
390
+ # Input from `data` is TODO.
391
+ # Output to prod_data is TODO.
330
392
  production(:OrderClause) do |input, data, callback|
331
393
  if res = data[:OrderCondition]
332
394
  res = [res] if [:asc, :desc].include?(res[0]) # Special case when there's only one condition and it's ASC (x) or DESC (x)
@@ -334,9 +396,12 @@ module SPARQL::Grammar
334
396
  end
335
397
  end
336
398
 
337
- # [24] OrderCondition ::= ( ( 'ASC' | 'DESC' )
338
- # BrackettedExpression )
339
- # | ( Constraint | Var )
399
+ # [24] OrderCondition ::= ( ( 'ASC' | 'DESC' )
400
+ # BrackettedExpression )
401
+ # | ( Constraint | Var )
402
+ #
403
+ # Input from `data` is TODO.
404
+ # Output to prod_data is TODO.
340
405
  production(:OrderCondition) do |input, data, callback|
341
406
  if data[:OrderDirection]
342
407
  add_prod_datum(:OrderCondition, SPARQL::Algebra::Expression(data[:OrderDirection], *data[:Expression]))
@@ -345,8 +410,11 @@ module SPARQL::Grammar
345
410
  end
346
411
  end
347
412
 
348
- # [25] LimitOffsetClauses ::= LimitClause OffsetClause?
349
- # | OffsetClause LimitClause?
413
+ # [25] LimitOffsetClauses ::= LimitClause OffsetClause?
414
+ # | OffsetClause LimitClause?
415
+ #
416
+ # Input from `data` is TODO.
417
+ # Output to prod_data is TODO.
350
418
  production(:LimitOffsetClauses) do |input, data, callback|
351
419
  if data[:limit] || data[:offset]
352
420
  limit = data[:limit] ? data[:limit].last : :_
@@ -355,17 +423,26 @@ module SPARQL::Grammar
355
423
  end
356
424
  end
357
425
 
358
- # [26] LimitClause ::= 'LIMIT' INTEGER
426
+ # [26] LimitClause ::= 'LIMIT' INTEGER
427
+ #
428
+ # Input from `data` is TODO.
429
+ # Output to prod_data is TODO.
359
430
  production(:LimitClause) do |input, data, callback|
360
431
  add_prod_datum(:limit, data[:literal])
361
432
  end
362
433
 
363
- # [27] OffsetClause ::= 'OFFSET' INTEGER
434
+ # [27] OffsetClause ::= 'OFFSET' INTEGER
435
+ #
436
+ # Input from `data` is TODO.
437
+ # Output to prod_data is TODO.
364
438
  production(:OffsetClause) do |input, data, callback|
365
439
  add_prod_datum(:offset, data[:literal])
366
440
  end
367
441
 
368
- # [28] ValuesClause ::= ( 'VALUES' DataBlock )?
442
+ # [28] ValuesClause ::= ( 'VALUES' DataBlock )?
443
+ #
444
+ # Input from `data` is TODO.
445
+ # Output to prod_data is TODO.
369
446
  production(:ValuesClause) do |input, data, callback|
370
447
  debug("ValuesClause") {"vars: #{data[:Var].inspect}, row: #{data[:row].inspect}"}
371
448
  if data[:row]
@@ -378,7 +455,10 @@ module SPARQL::Grammar
378
455
  end
379
456
  end
380
457
 
381
- # [29] Update ::= Prologue (Update1 (";" Update)? )?
458
+ # [29] Update ::= Prologue (Update1 (";" Update)? )?
459
+ #
460
+ # Input from `data` is TODO.
461
+ # Output to prod_data is TODO.
382
462
  production(:Update) do |input, data, callback|
383
463
  update = data[:update] || SPARQL::Algebra::Expression(:update)
384
464
 
@@ -396,6 +476,10 @@ module SPARQL::Grammar
396
476
  # Don't use update operator twice, if we can help it
397
477
  input[:update] = update
398
478
  end
479
+
480
+ #
481
+ # Input from `data` is TODO.
482
+ # Output to prod_data is TODO.
399
483
  production(:_Update_3) do |input, data, callback|
400
484
  if data[:update]
401
485
  if input[:update].is_a?(SPARQL::Algebra::Operator::Update)
@@ -407,12 +491,19 @@ module SPARQL::Grammar
407
491
  end
408
492
  end
409
493
 
410
- # [30] Update1 ::= Load | Clear | Drop | Add | Move | Copy | Create | InsertData | DeleteData | DeleteWhere | Modify
494
+ # [30] Update1 ::= Load | Clear | Drop | Add | Move | Copy
495
+ # | Create | InsertData | DeleteData | DeleteWhere | Modify
496
+ #
497
+ # Input from `data` is TODO.
498
+ # Output to prod_data is TODO.
411
499
  production(:Update1) do |input, data, callback|
412
500
  input[:update] = SPARQL::Algebra::Expression.for(:update, data[:update_op])
413
501
  end
414
502
 
415
- # [31] Load ::= "LOAD" "SILENT"? iri ("INTO" GraphRef)?
503
+ # [31] Load ::= "LOAD" "SILENT"? iri ("INTO" GraphRef)?
504
+ #
505
+ # Input from `data` is TODO.
506
+ # Output to prod_data is TODO.
416
507
  production(:Load) do |input, data, callback|
417
508
  args = []
418
509
  args << :silent if data[:silent]
@@ -420,11 +511,18 @@ module SPARQL::Grammar
420
511
  args << data[:into] if data[:into]
421
512
  input[:update_op] = SPARQL::Algebra::Expression(:load, *args)
422
513
  end
514
+
515
+ #
516
+ # Input from `data` is TODO.
517
+ # Output to prod_data is TODO.
423
518
  production(:_Load_2) do |input, data, callback|
424
519
  input[:into] = data[:iri]
425
520
  end
426
521
 
427
- # [32] Clear ::= "CLEAR" "SILENT"? GraphRefAll
522
+ # [32] Clear ::= "CLEAR" "SILENT"? GraphRefAll
523
+ #
524
+ # Input from `data` is TODO.
525
+ # Output to prod_data is TODO.
428
526
  production(:Clear) do |input, data, callback|
429
527
  args = []
430
528
  %w(silent default named all).map(&:to_sym).each do |s|
@@ -434,7 +532,10 @@ module SPARQL::Grammar
434
532
  input[:update_op] = SPARQL::Algebra::Expression(:clear, *args)
435
533
  end
436
534
 
437
- # [33] Drop ::= "DROP" "SILENT"? GraphRefAll
535
+ # [33] Drop ::= "DROP" "SILENT"? GraphRefAll
536
+ #
537
+ # Input from `data` is TODO.
538
+ # Output to prod_data is TODO.
438
539
  production(:Drop) do |input, data, callback|
439
540
  args = []
440
541
  %w(silent default named all).map(&:to_sym).each do |s|
@@ -444,7 +545,10 @@ module SPARQL::Grammar
444
545
  input[:update_op] = SPARQL::Algebra::Expression(:drop, *args)
445
546
  end
446
547
 
447
- # [34] Create ::= "CREATE" "SILENT"? GraphRef
548
+ # [34] Create ::= "CREATE" "SILENT"? GraphRef
549
+ #
550
+ # Input from `data` is TODO.
551
+ # Output to prod_data is TODO.
448
552
  production(:Create) do |input, data, callback|
449
553
  args = []
450
554
  args << :silent if data[:silent]
@@ -452,7 +556,10 @@ module SPARQL::Grammar
452
556
  input[:update_op] = SPARQL::Algebra::Expression(:create, *args)
453
557
  end
454
558
 
455
- # [35] Add ::= "ADD" "SILENT"? GraphOrDefault "TO" GraphOrDefault
559
+ # [35] Add ::= "ADD" "SILENT"? GraphOrDefault "TO" GraphOrDefault
560
+ #
561
+ # Input from `data` are `GraphOrDefault` and optionally `:silent`.
562
+ # Output to input is `:update_op` with an `Operator::Add` object.
456
563
  production(:Add) do |input, data, callback|
457
564
  args = []
458
565
  args << :silent if data[:silent]
@@ -460,7 +567,10 @@ module SPARQL::Grammar
460
567
  input[:update_op] = SPARQL::Algebra::Expression(:add, *args)
461
568
  end
462
569
 
463
- # [36] Move ::= "MOVE" "SILENT"? GraphOrDefault "TO" GraphOrDefault
570
+ # [36] Move ::= "MOVE" "SILENT"? GraphOrDefault "TO" GraphOrDefault
571
+ #
572
+ # Input from `data` is TODO.
573
+ # Output to prod_data is TODO.
464
574
  production(:Move) do |input, data, callback|
465
575
  args = []
466
576
  args << :silent if data[:silent]
@@ -468,7 +578,10 @@ module SPARQL::Grammar
468
578
  input[:update_op] = SPARQL::Algebra::Expression(:move, *args)
469
579
  end
470
580
 
471
- # [37] Copy ::= "COPY" "SILENT"? GraphOrDefault "TO" GraphOrDefault
581
+ # [37] Copy ::= "COPY" "SILENT"? GraphOrDefault "TO" GraphOrDefault
582
+ #
583
+ # Input from `data` is TODO.
584
+ # Output to prod_data is TODO.
472
585
  production(:Copy) do |input, data, callback|
473
586
  args = []
474
587
  args << :silent if data[:silent]
@@ -476,40 +589,59 @@ module SPARQL::Grammar
476
589
  input[:update_op] = SPARQL::Algebra::Expression(:copy, *args)
477
590
  end
478
591
 
479
- # [38] InsertData ::= "INSERT DATA" QuadData
592
+ # [38] InsertData ::= "INSERT DATA" QuadData
480
593
  start_production(:InsertData) do |input, data, callback|
481
594
  # Freeze existing bnodes, so that if an attempt is made to re-use such a node, and error is raised
482
595
  self.freeze_bnodes
483
596
  end
597
+
598
+ #
599
+ # Input from `data` is TODO.
600
+ # Output to prod_data is TODO.
484
601
  production(:InsertData) do |input, data, callback|
485
602
  input[:update_op] = SPARQL::Algebra::Expression(:insertData, data[:pattern])
486
603
  end
487
604
 
488
- # [39] DeleteData ::= "DELETE DATA" QuadData
605
+ # [39] DeleteData ::= "DELETE DATA" QuadData
489
606
  start_production(:DeleteData) do |input, data, callback|
490
607
  # 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.
491
608
  self.gen_bnodes
492
609
  end
610
+ #
611
+ # Input from `data` is TODO.
612
+ # Output to prod_data is TODO.
493
613
  production(:DeleteData) do |input, data, callback|
494
614
  raise Error, "DeleteData contains BNode operands: #{data[:pattern].to_sse}" if Array(data[:pattern]).any?(&:node?)
495
615
  input[:update_op] = SPARQL::Algebra::Expression(:deleteData, Array(data[:pattern]))
496
616
  end
497
617
 
498
- # [40] DeleteWhere ::= "DELETE WHERE" QuadPattern
618
+ # [40] DeleteWhere ::= "DELETE WHERE" QuadPattern
499
619
  start_production(:DeleteWhere) do |input, data, callback|
500
620
  # 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.
501
621
  self.gen_bnodes
502
622
  end
623
+
624
+ #
625
+ # Input from `data` is TODO.
626
+ # Output to prod_data is TODO.
503
627
  production(:DeleteWhere) do |input, data, callback|
504
628
  raise Error, "DeleteWhere contains BNode operands: #{data[:pattern].to_sse}" if Array(data[:pattern]).any?(&:node?)
505
629
  self.gen_bnodes(false)
506
630
  input[:update_op] = SPARQL::Algebra::Expression(:deleteWhere, Array(data[:pattern]))
507
631
  end
508
632
 
509
- # [41] Modify ::= ("WITH" iri)? ( DeleteClause InsertClause? | InsertClause) UsingClause* "WHERE" GroupGraphPattern
633
+ # [41] Modify ::= ("WITH" iri)? ( DeleteClause InsertClause? | InsertClause) UsingClause* "WHERE" GroupGraphPattern
510
634
  start_production(:Modify) do |input, data, callback|
511
635
  self.clear_bnode_cache
512
636
  end
637
+
638
+ #
639
+ # Input from `data` are:
640
+ # * `:query` from `GroupGraphPattern`,
641
+ # * optionally `:using` from `UsingClause`,
642
+ # * either `:delete` or `:insert` or both from `DeleteClause` and `InsertClause`, and
643
+ # * optionally `:iri` from `WITH`
644
+ # Output to input is `:update_op`.
513
645
  production(:Modify) do |input, data, callback|
514
646
  query = data[:query].first if data[:query]
515
647
  query = SPARQL::Algebra::Expression.for(:using, data[:using], query) if data[:using]
@@ -518,36 +650,53 @@ module SPARQL::Grammar
518
650
  input[:update_op] = SPARQL::Algebra::Expression(:modify, *operands)
519
651
  end
520
652
 
521
- # [42] DeleteClause ::= "DELETE" QuadPattern
653
+ # [42] DeleteClause ::= "DELETE" QuadPattern
654
+ #
655
+ # 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.
522
656
  start_production(:DeleteClause) do |input, data, callback|
523
- # 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.
524
657
  self.gen_bnodes
525
658
  end
659
+
660
+ #
661
+ # Input from `data` is TODO.
662
+ # Output to prod_data is TODO.
526
663
  production(:DeleteClause) do |input, data, callback|
527
664
  raise Error, "DeleteClause contains BNode operands: #{Array(data[:pattern]).to_sse}" if Array(data[:pattern]).any?(&:node?)
528
665
  self.gen_bnodes(false)
529
666
  input[:delete] = SPARQL::Algebra::Expression(:delete, Array(data[:pattern]))
530
667
  end
531
668
 
532
- # [43] InsertClause ::= "INSERT" QuadPattern
669
+ # [43] InsertClause ::= "INSERT" QuadPattern
670
+ #
671
+ # Generate BNodes instead of non-distinguished variables.
533
672
  start_production(:InsertClause) do |input, data, callback|
534
- # Generate BNodes instead of non-distinguished variables.
535
673
  self.gen_bnodes
536
674
  end
675
+
676
+ #
677
+ # Input from `data` is TODO.
678
+ # Output to prod_data is TODO.
537
679
  production(:InsertClause) do |input, data, callback|
538
680
  self.gen_bnodes(false)
539
681
  input[:insert] = SPARQL::Algebra::Expression(:insert, Array(data[:pattern]))
540
682
  end
541
683
 
542
- # [44] UsingClause ::= "USING" ( iri | "NAMED" iri)
684
+ # [44] UsingClause ::= "USING" ( iri | "NAMED" iri)
543
685
  production(:UsingClause) do |input, data, callback|
544
686
  add_prod_data(:using, data[:iri])
545
687
  end
688
+
689
+ #
690
+ # Input from `data` is TODO.
691
+ # Output to prod_data is TODO.
546
692
  production(:_UsingClause_2) do |input, data, callback|
547
693
  input[:iri] = [:named, data[:iri]]
548
694
  end
549
695
 
550
- # [45] GraphOrDefault ::= "DEFAULT" | "GRAPH"? iri
696
+ # [45] GraphOrDefault ::= "DEFAULT" | "GRAPH"? iri
697
+ #
698
+ # Input from `data` is TODO.
699
+ # Output to prod_data is TODO.
551
700
  production(:GraphOrDefault) do |input, data, callback|
552
701
  if data[:default]
553
702
  add_prod_datum(:GraphOrDefault, :default)
@@ -556,17 +705,24 @@ module SPARQL::Grammar
556
705
  end
557
706
  end
558
707
 
559
- # [46] GraphRef ::= "GRAPH" iri
708
+ # [46] GraphRef ::= "GRAPH" iri
709
+ #
710
+ # Input from `data` is TODO.
711
+ # Output to prod_data is TODO.
560
712
  production(:GraphRef) do |input, data, callback|
561
713
  input[:iri] = data[:iri]
562
714
  end
563
715
 
564
- # [49] QuadData ::= "{" Quads "}"
716
+ # [49] QuadData ::= "{" Quads "}"
565
717
  # QuadData is like QuadPattern, except without BNodes
566
718
  start_production(:QuadData) do |input, data, callback|
567
719
  # Generate BNodes instead of non-distinguished variables
568
720
  self.gen_bnodes
569
721
  end
722
+
723
+ #
724
+ # Input from `data` is TODO.
725
+ # Output to prod_data is TODO.
570
726
  production(:QuadData) do |input, data, callback|
571
727
  # Transform using statements instead of patterns, and verify there are no variables
572
728
  raise Error, "QuadData contains variable operands: #{Array(data[:pattern]).to_sse}" if Array(data[:pattern]).any?(&:variable?)
@@ -574,17 +730,26 @@ module SPARQL::Grammar
574
730
  input[:pattern] = Array(data[:pattern])
575
731
  end
576
732
 
577
- # [51] QuadsNotTriples ::= "GRAPH" VarOrIri "{" TriplesTemplate? "}"
733
+ # [51] QuadsNotTriples ::= "GRAPH" VarOrIri "{" TriplesTemplate? "}"
734
+ #
735
+ # Input from `data` is TODO.
736
+ # Output to prod_data is TODO.
578
737
  production(:QuadsNotTriples) do |input, data, callback|
579
738
  add_prod_datum(:pattern, [SPARQL::Algebra::Expression.for(:graph, data[:VarOrIri].last, Array(data[:pattern]))])
580
739
  end
581
740
 
582
- # [52] TriplesTemplate ::= TriplesSameSubject ("." TriplesTemplate? )?
741
+ # [52] TriplesTemplate ::= TriplesSameSubject ("." TriplesTemplate? )?
742
+ #
743
+ # Input from `data` is TODO.
744
+ # Output to prod_data is TODO.
583
745
  production(:TriplesTemplate) do |input, data, callback|
584
746
  add_prod_datum(:pattern, Array(data[:pattern]))
585
747
  end
586
748
 
587
- # [54] GroupGraphPatternSub ::= TriplesBlock? (GraphPatternNotTriples "."? TriplesBlock? )*
749
+ # [54] GroupGraphPatternSub ::= TriplesBlock? (GraphPatternNotTriples "."? TriplesBlock? )*
750
+ #
751
+ # Input from `data` is TODO.
752
+ # Output to prod_data is TODO.
588
753
  production(:GroupGraphPatternSub) do |input, data, callback|
589
754
  debug("GroupGraphPatternSub") {"q #{data[:query].inspect}"}
590
755
 
@@ -608,48 +773,90 @@ module SPARQL::Grammar
608
773
  add_prod_datum(:query, res)
609
774
  end
610
775
 
611
- # [55] TriplesBlock ::= TriplesSameSubjectPath
612
- # ( '.' TriplesBlock? )?
776
+ # [55] TriplesBlock ::= TriplesSameSubjectPath
777
+ # ( '.' TriplesBlock? )?
778
+ #
779
+ # Input from `data` is `:pattern` and `:query`. Input from input is also `:pattern`
780
+ # Patterns are sequenced and segmented into RDF::Query::Pattern and Operator::Path.
781
+ # Output to prod_data is `:query` either a BGP, a Join, a Sequence, or a combination of any of these. Any path element results in a Sequence.
613
782
  production(:TriplesBlock) do |input, data, callback|
614
- if !Array(data[:pattern]).empty?
615
- query = SPARQL::Algebra::Operator::BGP.new
616
- Array(data[:pattern]).each {|p| query << p}
617
-
618
- # Append triples from ('.' TriplesBlock? )?
619
- Array(data[:query]).each do |q|
620
- if q.respond_to?(:patterns)
621
- query += q
622
- else
623
- query = SPARQL::Algebra::Operator::Join.new(query, q)
783
+ raise "TriplesBlock without pattern" if Array(data[:pattern]).empty?
784
+
785
+ lhs = Array(input.delete(:query)).first
786
+
787
+ # Sequence is existing patterns, plus new patterns, plus patterns from TriplesBlock?
788
+ sequence = []
789
+ unless lhs.nil? || lhs.empty?
790
+ if lhs.is_a?(SPARQL::Algebra::Operator::Sequence)
791
+ sequence += lhs.operands
792
+ else
793
+ sequence << lhs
794
+ end
795
+ end
796
+
797
+ sequence += data[:pattern]
798
+
799
+ # Append triples from ('.' TriplesBlock? )?
800
+ Array(data[:query]).each do |q|
801
+ if q.is_a?(SPARQL::Algebra::Operator::Sequence)
802
+ q.operands.each do |op|
803
+ sequence += op.respond_to?(:patterns) ? op.patterns : [op]
624
804
  end
805
+ elsif q.respond_to?(:patterns)
806
+ sequence += q.patterns
807
+ else
808
+ sequence << q
625
809
  end
626
- if (lhs = (input.delete(:query) || []).first) && !lhs.empty?
627
- query = SPARQL::Algebra::Operator::Join.new(lhs, query)
810
+ end
811
+
812
+ # Merge runs of patterns into BGPs
813
+ patterns = []
814
+ new_seq = []
815
+ sequence.each do |element|
816
+ case element
817
+ when RDF::Query::Pattern
818
+ patterns << element
819
+ when RDF::Queryable
820
+ patterns += element.patterns
821
+ else
822
+ new_seq << SPARQL::Algebra::Expression.for(:bgp, *patterns) unless patterns.empty?
823
+ patterns = []
824
+ new_seq << element
628
825
  end
629
- if data[:path]
630
- query = SPARQL::Algebra::Operator::Join.new(query, Array(data[:path]).first)
826
+ end
827
+ new_seq << SPARQL::Algebra::Expression.for(:bgp, *patterns) unless patterns.empty?
828
+
829
+ # Optionally create a sequence, if there are enough gathered.
830
+ # FIXME: Join?
831
+ query = if new_seq.length > 1
832
+ if new_seq.any? {|e| e.is_a?(SPARQL::Algebra::Operator::Path)}
833
+ SPARQL::Algebra::Expression.for(:sequence, *new_seq)
834
+ else
835
+ SPARQL::Algebra::Expression.for(:join, *new_seq)
631
836
  end
632
- add_prod_datum(:query, query)
633
- elsif !Array(data[:query]).empty?
634
- # Join query and path
635
- add_prod_datum(:query, SPARQL::Algebra::Operator::Join.new(data[:path].first, data[:query].first))
636
- elsif data[:path]
637
- add_prod_datum(:query, data[:path])
837
+ else
838
+ new_seq.first
638
839
  end
840
+
841
+ add_prod_datum(:query, query)
639
842
  end
640
843
 
641
- # [56] GraphPatternNotTriples ::= GroupOrUnionGraphPattern
642
- # | OptionalGraphPattern
643
- # | MinusGraphPattern
644
- # | GraphGraphPattern
645
- # | ServiceGraphPattern
646
- # | Filter | Bind
844
+ # [56] GraphPatternNotTriples ::= GroupOrUnionGraphPattern
845
+ # | OptionalGraphPattern
846
+ # | MinusGraphPattern
847
+ # | GraphGraphPattern
848
+ # | ServiceGraphPattern
849
+ # | Filter | Bind
647
850
  start_production(:GraphPatternNotTriples) do |input, data, callback|
648
851
  # Modifies previous graph
649
- data[:input_query] = input.delete(:query) || [SPARQL::Algebra::Operator::BGP.new]
852
+ data[:input_query] = input.delete(:query)
650
853
  end
854
+
855
+ #
856
+ # Input from `data` is TODO.
857
+ # Output to prod_data is TODO.
651
858
  production(:GraphPatternNotTriples) do |input, data, callback|
652
- lhs = Array(data[:input_query]).first
859
+ lhs = Array(data[:input_query]).first || SPARQL::Algebra::Operator::BGP.new
653
860
 
654
861
  # Filter trickls up to GroupGraphPatternSub
655
862
  add_prod_datum(:filter, data[:filter])
@@ -679,7 +886,10 @@ module SPARQL::Grammar
679
886
  end
680
887
  end
681
888
 
682
- # [57] OptionalGraphPattern ::= 'OPTIONAL' GroupGraphPattern
889
+ # [57] OptionalGraphPattern ::= 'OPTIONAL' GroupGraphPattern
890
+ #
891
+ # Input from `data` is TODO.
892
+ # Output to prod_data is TODO.
683
893
  production(:OptionalGraphPattern) do |input, data, callback|
684
894
  expr = nil
685
895
  query = data[:query] ? data[:query].first : SPARQL::Algebra::Operator::BGP.new
@@ -692,7 +902,10 @@ module SPARQL::Grammar
692
902
  end
693
903
  end
694
904
 
695
- # [58] GraphGraphPattern ::= 'GRAPH' VarOrIri GroupGraphPattern
905
+ # [58] GraphGraphPattern ::= 'GRAPH' VarOrIri GroupGraphPattern
906
+ #
907
+ # Input from `data` is TODO.
908
+ # Output to prod_data is TODO.
696
909
  production(:GraphGraphPattern) do |input, data, callback|
697
910
  name = (data[:VarOrIri]).last
698
911
  bgp = data[:query] ? data[:query].first : SPARQL::Algebra::Operator::BGP.new
@@ -703,21 +916,43 @@ module SPARQL::Grammar
703
916
  end
704
917
  end
705
918
 
706
- # [60] Bind ::= 'BIND' '(' Expression 'AS' Var ')'
919
+ # [59] ServiceGraphPattern ::= 'SERVICE' 'SILENT'? VarOrIri GroupGraphPattern
920
+ #
921
+ # Input from `data` is TODO.
922
+ # Output to prod_data is TODO.
923
+ production(:ServiceGraphPattern) do |input, data, callback|
924
+ args = []
925
+ args << :silent if data[:silent]
926
+ args << (data[:VarOrIri]).last
927
+ args << data.fetch(:query, [SPARQL::Algebra::Operator::BGP.new]).first
928
+ service = SPARQL::Algebra::Expression.for(:service, *args)
929
+ add_prod_data(:query, service)
930
+ end
931
+
932
+ # [60] Bind ::= 'BIND' '(' Expression 'AS' Var ')'
933
+ #
934
+ # Input from `data` is TODO.
935
+ # Output to prod_data is TODO.
707
936
  production(:Bind) do |input, data, callback|
708
937
  add_prod_datum :extend, [data[:Expression].unshift(data[:Var].first)]
709
938
  end
710
939
 
711
- # [61] InlineData ::= 'VALUES' DataBlock
940
+ # [61] InlineData ::= 'VALUES' DataBlock
941
+ #
942
+ # Input from `data` is TODO.
943
+ # Output to prod_data is TODO.
712
944
  production(:InlineData) do |input, data, callback|
713
945
  debug("InlineData") {"vars: #{data[:Var].inspect}, row: #{data[:row].inspect}"}
714
946
  add_prod_datum :query, SPARQL::Algebra::Expression.for(:table,
715
- data[:Var].unshift(:vars),
947
+ Array(data[:Var]).unshift(:vars),
716
948
  *data[:row]
717
949
  )
718
950
  end
719
951
 
720
- # [63] InlineDataOneVar ::= Var '{' DataBlockValue* '}'
952
+ # [63] InlineDataOneVar ::= Var '{' DataBlockValue* '}'
953
+ #
954
+ # Input from `data` is TODO.
955
+ # Output to prod_data is TODO.
721
956
  production(:InlineDataOneVar) do |input, data, callback|
722
957
  add_prod_datum :Var, data[:Var]
723
958
 
@@ -726,8 +961,11 @@ module SPARQL::Grammar
726
961
  end
727
962
  end
728
963
 
729
- # [64] InlineDataFull ::= ( NIL | '(' Var* ')' )
730
- # '{' ( '(' DataBlockValue* ')' | NIL )* '}'
964
+ # [64] InlineDataFull ::= ( NIL | '(' Var* ')' )
965
+ # '{' ( '(' DataBlockValue* ')' | NIL )* '}'
966
+ #
967
+ # Input from `data` is TODO.
968
+ # Output to prod_data is TODO.
731
969
  production(:InlineDataFull) do |input, data, callback|
732
970
  vars = data[:Var]
733
971
  add_prod_datum :Var, vars
@@ -745,7 +983,10 @@ module SPARQL::Grammar
745
983
  end
746
984
  end
747
985
 
748
- # _InlineDataFull_6 ::= '(' '(' DataBlockValue* ')' | NIL ')'
986
+ # _InlineDataFull_6 ::= '(' '(' DataBlockValue* ')' | NIL ')'
987
+ #
988
+ # Input from `data` is TODO.
989
+ # Output to prod_data is TODO.
749
990
  production(:_InlineDataFull_6) do |input, data, callback|
750
991
  if data[:DataBlockValue]
751
992
  add_prod_data :rowdata, data[:DataBlockValue].map {|v| v unless v == :undef}
@@ -754,19 +995,28 @@ module SPARQL::Grammar
754
995
  end
755
996
  end
756
997
 
757
- # [65] DataBlockValue ::= QuotedTriple | iri | RDFLiteral | NumericLiteral | BooleanLiteral | 'UNDEF'
998
+ # [65] DataBlockValue ::= QuotedTriple | iri | RDFLiteral | NumericLiteral | BooleanLiteral | 'UNDEF'
999
+ #
1000
+ # Input from `data` is TODO.
1001
+ # Output to prod_data is TODO.
758
1002
  production(:DataBlockValue) do |input, data, callback|
759
1003
  add_prod_datum :DataBlockValue, data.values.first
760
1004
  end
761
1005
 
762
- # [66] MinusGraphPattern ::= 'MINUS' GroupGraphPattern
1006
+ # [66] MinusGraphPattern ::= 'MINUS' GroupGraphPattern
1007
+ #
1008
+ # Input from `data` is TODO.
1009
+ # Output to prod_data is TODO.
763
1010
  production(:MinusGraphPattern) do |input, data, callback|
764
1011
  query = data[:query] ? data[:query].first : SPARQL::Algebra::Operator::BGP.new
765
1012
  add_prod_data(:minus, query)
766
1013
  end
767
1014
 
768
- # [67] GroupOrUnionGraphPattern ::= GroupGraphPattern
1015
+ # [67] GroupOrUnionGraphPattern ::= GroupGraphPattern
769
1016
  # ( 'UNION' GroupGraphPattern )*
1017
+ #
1018
+ # Input from `data` is TODO.
1019
+ # Output to prod_data is TODO.
770
1020
  production(:GroupOrUnionGraphPattern) do |input, data, callback|
771
1021
  res = Array(data[:query]).first
772
1022
  if data[:union]
@@ -782,17 +1032,26 @@ module SPARQL::Grammar
782
1032
  end
783
1033
 
784
1034
  # ( 'UNION' GroupGraphPattern )*
1035
+ #
1036
+ # Input from `data` is TODO.
1037
+ # Output to prod_data is TODO.
785
1038
  production(:_GroupOrUnionGraphPattern_1) do |input, data, callback|
786
1039
  input[:union] = Array(data[:union]).unshift(data[:query].first)
787
1040
  end
788
1041
 
789
- # [68] Filter ::= 'FILTER' Constraint
1042
+ # [68] Filter ::= 'FILTER' Constraint
1043
+ #
1044
+ # Input from `data` is TODO.
1045
+ # Output to prod_data is TODO.
790
1046
  production(:Filter) do |input, data, callback|
791
1047
  add_prod_datum(:filter, data[:Constraint])
792
1048
  end
793
1049
 
794
- # [69] Constraint ::= BrackettedExpression | BuiltInCall
1050
+ # [69] Constraint ::= BrackettedExpression | BuiltInCall
795
1051
  # | FunctionCall
1052
+ #
1053
+ # Input from `data` is TODO.
1054
+ # Output to prod_data is TODO.
796
1055
  production(:Constraint) do |input, data, callback|
797
1056
  if data[:Expression]
798
1057
  # Resolve expression to the point it is either an atom or an s-exp
@@ -804,28 +1063,41 @@ module SPARQL::Grammar
804
1063
  end
805
1064
  end
806
1065
 
807
- # [70] FunctionCall ::= iri ArgList
1066
+ # [70] FunctionCall ::= iri ArgList
1067
+ #
1068
+ # Input from `data` is TODO.
1069
+ # Output to prod_data is TODO.
808
1070
  production(:FunctionCall) do |input, data, callback|
809
- add_prod_data(:Function, Array(data[:iri]) + data[:ArgList])
1071
+ add_prod_data(:Function, SPARQL::Algebra::Operator::FunctionCall.new(data[:iri], *data[:ArgList]))
810
1072
  end
811
1073
 
812
- # [71] ArgList ::= NIL
1074
+ # [71] ArgList ::= NIL
813
1075
  # | '(' 'DISTINCT'? Expression ( ',' Expression )* ')'
1076
+ #
1077
+ # Input from `data` is TODO.
1078
+ # Output to prod_data is TODO.
814
1079
  production(:ArgList) do |input, data, callback|
815
1080
  data.values.each {|v| add_prod_datum(:ArgList, v)}
816
1081
  end
817
1082
 
818
- # [72] ExpressionList ::= NIL
1083
+ # [72] ExpressionList ::= NIL
819
1084
  # | '(' Expression ( ',' Expression )* ')'
1085
+ #
1086
+ # Input from `data` is TODO.
1087
+ # Output to prod_data is TODO.
820
1088
  production(:ExpressionList) do |input, data, callback|
821
1089
  data.values.each {|v| add_prod_datum(:ExpressionList, v)}
822
1090
  end
823
1091
 
824
- # [73] ConstructTemplate ::= '{' ConstructTriples? '}'
1092
+ # [73] ConstructTemplate ::= '{' ConstructTriples? '}'
825
1093
  start_production(:ConstructTemplate) do |input, data, callback|
826
1094
  # Generate BNodes instead of non-distinguished variables
827
1095
  self.gen_bnodes
828
1096
  end
1097
+
1098
+ #
1099
+ # Input from `data` is TODO.
1100
+ # Output to prod_data is TODO.
829
1101
  production(:ConstructTemplate) do |input, data, callback|
830
1102
  # Generate BNodes instead of non-distinguished variables
831
1103
  self.gen_bnodes(false)
@@ -833,13 +1105,13 @@ module SPARQL::Grammar
833
1105
  add_prod_datum(:ConstructTemplate, data[:ConstructTemplate])
834
1106
  end
835
1107
 
836
- # [75] TriplesSameSubject ::= VarOrTermOrQuotedTP PropertyListNotEmpty
837
- # | TriplesNode PropertyList
1108
+ # [75] TriplesSameSubject ::= VarOrTermOrQuotedTP PropertyListNotEmpty
1109
+ # | TriplesNode PropertyList
838
1110
  production(:TriplesSameSubject) do |input, data, callback|
839
1111
  add_prod_datum(:pattern, data[:pattern])
840
1112
  end
841
1113
 
842
- # [77] PropertyListNotEmpty ::= Verb ObjectList
1114
+ # [77] PropertyListNotEmpty ::= Verb ObjectList
843
1115
  # ( ';' ( Verb ObjectList )? )*
844
1116
  start_production(:PropertyListNotEmpty) do |input, data, callback|
845
1117
  subject = input[:VarOrTermOrQuotedTP] || input[:TriplesNode] || input[:GraphNode]
@@ -850,47 +1122,58 @@ module SPARQL::Grammar
850
1122
  add_prod_datum(:pattern, data[:pattern])
851
1123
  end
852
1124
 
853
- # [78] Verb ::= VarOrIri | 'a'
1125
+ # [78] Verb ::= VarOrIri | 'a'
1126
+ #
1127
+ # Output to input is `:Verb`.
854
1128
  production(:Verb) do |input, data, callback|
855
1129
  input[:Verb] = data.values.first
856
1130
  end
857
1131
 
858
- # [79] ObjectList ::= Object ( ',' Object )*
1132
+ # [79] ObjectList ::= Object ( ',' Object )*
1133
+ #
1134
+ # Adds `:Subject`, `:Verb`, and `:VerbPath` from input to data with error checking.
859
1135
  start_production(:ObjectList) do |input, data, callback|
860
1136
  # Called after Verb. The prod_data stack should have Subject and Verb elements
861
- data[:Subject] = prod_data[:Subject]
862
- error(nil, "Expected Subject", production: :ObjectList) if !prod_data[:Subject] && validate?
863
- error(nil, "Expected Verb", production: :ObjectList) if !(prod_data[:Verb] || prod_data[:VerbPath]) && validate?
864
- data[:Verb] = prod_data[:Verb] if prod_data[:Verb]
865
- data[:VerbPath] = prod_data[:VerbPath] if prod_data[:VerbPath]
1137
+ data[:Subject] = input[:Subject]
1138
+ error(nil, "Expected Subject", production: :ObjectList) if !input[:Subject] && validate?
1139
+ error(nil, "Expected Verb", production: :ObjectList) if !(input[:Verb] || input[:VerbPath]) && validate?
1140
+ data[:Verb] = input[:Verb] if input[:Verb]
1141
+ data[:VerbPath] = input[:VerbPath] if input[:VerbPath]
866
1142
  end
867
1143
  production(:ObjectList) do |input, data, callback|
868
1144
  add_prod_datum(:pattern, data[:pattern])
869
- add_prod_datum(:path, data[:path])
870
1145
  end
871
1146
 
872
- # [80] Object ::= GraphNode AnnotationPattern?
1147
+ # [80] Object ::= GraphNode AnnotationPattern?
1148
+ #
1149
+ # Sets `:Subject` and `:Verb` in data from input.
873
1150
  start_production(:Object) do |input, data, callback|
874
1151
  data[:Subject] = Array(input[:Subject]).first
875
1152
  data[:Verb] = Array(input[:Verb]).first
876
1153
  end
1154
+
1155
+ #
1156
+ # Input from `data` is `:Subject`, `:Verb` or `:VerbPath`, and `GraphNode`.
1157
+ # Output to prod_data is `:pattern`, either from `:Subject`, `:Verb`, and `GraphNode` or a new path if `VerbPath` is present instead of `Verb`.
877
1158
  production(:Object) do |input, data, callback|
878
1159
  object = data[:GraphNode]
879
1160
  add_prod_datum(:pattern, data[:pattern])
880
1161
  if object
881
- if prod_data[:Verb]
882
- add_pattern(:Object, subject: prod_data[:Subject], predicate: prod_data[:Verb], object: object)
883
- elsif prod_data[:VerbPath]
884
- add_prod_datum(:path,
1162
+ if input[:Verb]
1163
+ add_pattern(:Object, subject: input[:Subject], predicate: input[:Verb], object: object)
1164
+ elsif input[:VerbPath]
1165
+ add_prod_datum(:pattern,
885
1166
  SPARQL::Algebra::Expression(:path,
886
- prod_data[:Subject].first,
887
- prod_data[:VerbPath],
1167
+ input[:Subject].first,
1168
+ input[:VerbPath],
888
1169
  object.first))
889
1170
  end
890
1171
  end
891
1172
  end
1173
+
1174
+ # AnnotationPattern?
892
1175
  start_production(:_Object_1) do |input, data, callback|
893
- pattern = RDF::Query::Pattern.new(input[:Subject], input[:Verb], input[:GraphNode].first)
1176
+ pattern = RDF::Query::Pattern.new(input[:Subject], input[:Verb], input[:GraphNode].first, quoted: true)
894
1177
  error("ObjectPath", "Expected Verb",
895
1178
  production: :_Object_1) unless input[:Verb]
896
1179
  data[:TriplesNode] = [pattern]
@@ -899,13 +1182,17 @@ module SPARQL::Grammar
899
1182
  add_prod_datum(:pattern, data[:pattern])
900
1183
  end
901
1184
 
902
- # [81] TriplesSameSubjectPath ::= VarOrTermOrQuotedTP PropertyListPathNotEmpty | TriplesNode PropertyListPath
1185
+ # [81] TriplesSameSubjectPath ::= VarOrTermOrQuotedTP PropertyListPathNotEmpty | TriplesNode PropertyListPath
903
1186
  production(:TriplesSameSubjectPath) do |input, data, callback|
904
1187
  add_prod_datum(:pattern, data[:pattern])
905
- add_prod_datum(:path, data[:path])
906
1188
  end
907
1189
 
908
- # [83] PropertyListPathNotEmpty ::= ( VerbPath | VerbSimple ) ObjectList ( ';' ( ( VerbPath | VerbSimple ) ObjectList )? )*
1190
+ # [83] PropertyListPathNotEmpty ::= ( VerbPath | VerbSimple ) ObjectList
1191
+ # ( ';' ( ( VerbPath | VerbSimple )
1192
+ # ObjectList )? )*
1193
+ #
1194
+ # Sets `:Subject` in data from either `:VarOrTermOrQuotedTP`,
1195
+ # `:TriplesNode`, or `:GraphNode` in input with error checking.
909
1196
  start_production(:PropertyListPathNotEmpty) do |input, data, callback|
910
1197
  subject = input[:VarOrTermOrQuotedTP] || input[:TriplesNode] || input[:GraphNode]
911
1198
  error(nil, "Expected VarOrTermOrQuotedTP, got nothing", production: :PropertyListPathNotEmpty) if validate? && !subject
@@ -913,10 +1200,13 @@ module SPARQL::Grammar
913
1200
  end
914
1201
  production(:PropertyListPathNotEmpty) do |input, data, callback|
915
1202
  add_prod_datum(:pattern, data[:pattern])
916
- add_prod_datum(:path, data[:path])
917
1203
  end
918
1204
 
919
- # [84] VerbPath ::= Path
1205
+ # [84] VerbPath ::= Path
1206
+ #
1207
+ # Input from `data` is `:Path` or `:iri`.
1208
+ # Output to prod_data is either `:VerbPath` or `:Verb`.
1209
+ # If `:VerbPath` is added, then any existing `:Verb` is removed.
920
1210
  production(:VerbPath) do |input, data, callback|
921
1211
  if data[:Path]
922
1212
  input.delete(:Verb)
@@ -926,70 +1216,80 @@ module SPARQL::Grammar
926
1216
  end
927
1217
  end
928
1218
 
929
- # [85] VerbSimple ::= Var
1219
+ # [85] VerbSimple ::= Var
930
1220
  production(:VerbSimple) do |input, data, callback|
931
1221
  input[:Verb] = data.values.flatten.first
932
1222
  end
933
1223
 
934
- # [86] ObjectListPath ::= ObjectPath ("," ObjectPath)*
1224
+ # [86] ObjectListPath ::= ObjectPath ("," ObjectPath)*
1225
+ #
1226
+ # Addes `:Subject` from input to data with error checking.
1227
+ # Also adds either `:Verb` or `:VerbPath`
935
1228
  start_production(:ObjectListPath) do |input, data, callback|
936
1229
  # Called after Verb. The prod_data stack should have Subject and Verb elements
937
- data[:Subject] = prod_data[:Subject]
938
- error(nil, "Expected Subject", production: :ObjectListPath) if !prod_data[:Subject] && validate?
939
- error(nil, "Expected Verb", production: :ObjectListPath) if !(prod_data[:Verb] || prod_data[:VerbPath]) && validate?
940
- if prod_data[:Verb]
941
- data[:Verb] = Array(prod_data[:Verb]).last
1230
+ data[:Subject] = input[:Subject]
1231
+ error(nil, "Expected Subject", production: :ObjectListPath) if !input[:Subject] && validate?
1232
+ error(nil, "Expected Verb", production: :ObjectListPath) if !(input[:Verb] || input[:VerbPath]) && validate?
1233
+ if input[:Verb]
1234
+ data[:Verb] = Array(input[:Verb]).last
942
1235
  else
943
- data[:VerbPath] = prod_data[:VerbPath]
1236
+ data[:VerbPath] = input[:VerbPath]
944
1237
  end
945
1238
  end
1239
+
1240
+ #
1241
+ # Input from `data` is TODO.
1242
+ # Output to prod_data is TODO.
946
1243
  production(:ObjectListPath) do |input, data, callback|
947
1244
  add_prod_datum(:pattern, data[:pattern])
948
- add_prod_datum(:path, data[:path])
949
1245
  end
950
1246
 
951
- # [87] ObjectPath ::= GraphNodePath AnnotationPatternPath?
1247
+ # [87] ObjectPath ::= GraphNodePath AnnotationPatternPath?
1248
+ #
1249
+ # Adds `:Subject` and `:Verb` to data from input.
952
1250
  start_production(:ObjectPath) do |input, data, callback|
953
1251
  data[:Subject] = Array(input[:Subject]).first
954
1252
  data[:Verb] = Array(input[:Verb]).first
955
1253
  end
1254
+
1255
+ # Input from `data` `:Subject`, either `:Verb` or `:VerbPath`, `:GraphNode` from GraphNodePath is used as the object, and `:pattern`.
1256
+ # Output to prod_data is either a pattern including `:Subject`, `:Verb` and `:GraphNode`, or an `Object::Path` using `:VerbPath` instead of `:Verb`. Also, any `:pattern` from data is sent to prod_ddata
956
1257
  production(:ObjectPath) do |input, data, callback|
957
- object = data[:VarOrTermOrQuotedTP] || data[:TriplesNode] || data[:GraphNode]
958
- if object
959
- if prod_data[:Verb]
960
- if data[:pattern] && data[:path]
961
- # Generate a sequence (for collection of paths)
962
- data[:pattern].unshift(RDF::Query::Pattern.new(prod_data[:Subject].first, prod_data[:Verb], object.first))
963
- bgp = SPARQL::Algebra::Expression[:bgp, data[:pattern]]
964
- add_prod_datum(:path, SPARQL::Algebra::Expression[:sequence, bgp, *data[:path]])
965
- elsif data[:path]
966
- # AnnotationPatternPath case
967
- add_prod_datum(:path, data[:path])
968
- else
969
- add_pattern(:Object, subject: prod_data[:Subject], predicate: prod_data[:Verb], object: object)
970
- add_prod_datum(:pattern, data[:pattern])
971
- end
972
- else
973
- add_prod_datum(:path,
974
- SPARQL::Algebra::Expression(:path,
975
- Array(prod_data[:Subject]).first,
976
- prod_data[:VerbPath],
977
- object.first))
978
- end
1258
+ subject = data[:Subject]
1259
+ verb = data[:Verb]
1260
+ object = Array(data[:GraphNode]).first
1261
+ if verb
1262
+ add_prod_datum(:pattern, RDF::Query::Pattern.new(subject, verb, object))
1263
+ else
1264
+ add_prod_datum(:pattern, SPARQL::Algebra::Expression(:path,
1265
+ subject,
1266
+ input[:VerbPath],
1267
+ object))
979
1268
  end
1269
+ add_prod_datum(:pattern, data[:pattern])
980
1270
  end
1271
+
1272
+ # AnnotationPatternPath?
1273
+ #
1274
+ # Create `:TriplesNode` in data used as the subject of annotations
981
1275
  start_production(:_ObjectPath_1) do |input, data, callback|
982
- pattern = RDF::Query::Pattern.new(input[:Subject], input[:Verb], input[:GraphNode].first)
983
1276
  error("ObjectPath", "Expected Verb",
984
1277
  production: :_ObjectPath_1) unless input[:Verb]
1278
+ pattern = RDF::Query::Pattern.new(input[:Subject], input[:Verb], input[:GraphNode].first, quoted: true)
985
1279
  data[:TriplesNode] = [pattern]
986
1280
  end
1281
+
1282
+ #
1283
+ # Input from `data` is `:pattern`.
1284
+ # Output to prod_data is `:pattern`.
987
1285
  production(:_ObjectPath_1) do |input, data, callback|
988
1286
  add_prod_datum(:pattern, data[:pattern])
989
1287
  end
990
1288
 
991
- # [88] Path ::= PathAlternative
992
- # output is a :Path or :iri
1289
+ # [88] Path ::= PathAlternative
1290
+ #
1291
+ # Input from data is `:Path`
1292
+ # Output to input is either `:iri` or `:Path`, depending on if `:Path` is an IRI or not.
993
1293
  production(:Path) do |input, data, callback|
994
1294
  if data[:Path].is_a?(RDF::URI)
995
1295
  input[:iri] = data[:Path]
@@ -998,7 +1298,10 @@ module SPARQL::Grammar
998
1298
  end
999
1299
  end
1000
1300
 
1001
- # [89] PathAlternative ::= PathSequence ( '|' PathSequence )*
1301
+ # [89] PathAlternative ::= PathSequence ( '|' PathSequence )*
1302
+ #
1303
+ # Input from `data` is `:PathSequence` containing one or more path objects.
1304
+ # Output to prod_data is `:Path`, containing a nested sequence of `Algebra::Alt` connecting the elements from `:PathSequence`, unless there is only one such element, in which case it is added directly.
1002
1305
  production(:PathAlternative) do |input, data, callback|
1003
1306
  lhs = Array(data[:PathSequence]).shift
1004
1307
  while data[:PathSequence] && !data[:PathSequence].empty?
@@ -1009,11 +1312,17 @@ module SPARQL::Grammar
1009
1312
  end
1010
1313
 
1011
1314
  # ( '|' PathSequence )*
1315
+ #
1316
+ # Input from `data` is `:PathSequence`.
1317
+ # Output to prod_data is `:PathSequence` which is accumulated.
1012
1318
  production(:_PathAlternative_1) do |input, data, callback|
1013
1319
  input[:PathSequence] += data[:PathSequence]
1014
1320
  end
1015
1321
 
1016
- # [90] PathSequence ::= PathEltOrInverse ( '/' PathEltOrInverse )*
1322
+ # [90] PathSequence ::= PathEltOrInverse ( '/' PathEltOrInverse )*
1323
+ #
1324
+ # Input from `data` is `:PathSequence` containing one or more path objects.
1325
+ # Output to prod_data is `:Path`, containing a nested sequence of `Algebra::Seq` connecting the elements from `:PathSequence`, unless there is only one such element, in which case it is added directly.
1017
1326
  production(:PathSequence) do |input, data, callback|
1018
1327
  lhs = data[:PathEltOrInverse].shift
1019
1328
  while data[:PathEltOrInverse] && !data[:PathEltOrInverse].empty?
@@ -1024,22 +1333,39 @@ module SPARQL::Grammar
1024
1333
  end
1025
1334
 
1026
1335
  # ( '/' PathEltOrInverse )*
1336
+ #
1337
+ # Input from `data` is `:PathSequence`.
1338
+ # Output to prod_data is `:PathSequence` which is accumulated.
1027
1339
  production(:_PathSequence_1) do |input, data, callback|
1028
1340
  input[:PathEltOrInverse] += data[:PathEltOrInverse]
1029
1341
  end
1030
1342
 
1031
- # [91] PathElt ::= PathPrimary PathMod?
1343
+ # [91] PathElt ::= PathPrimary PathMod?
1344
+ #
1345
+ # Input from `data` is `:PathMod` and `:PathPrimary`.
1346
+ # Output to prod_data is `:Path` a possibly modified `:PathPrimary`.
1032
1347
  production(:PathElt) do |input, data, callback|
1033
1348
  path_mod = data.delete(:PathMod) if data.has_key?(:PathMod)
1034
1349
  path_mod ||= data.delete(:MultiplicativeExpression) if data.has_key?(:MultiplicativeExpression)
1035
1350
  path_mod = path_mod.first if path_mod
1036
1351
 
1037
- res = data[:PathPrimary]
1038
- res = SPARQL::Algebra::Expression("path#{path_mod}", res) if path_mod
1352
+ res = case path_mod
1353
+ when SPARQL::Algebra::Expression
1354
+ # Path range :p{m,n}
1355
+ path_mod.operands[2] = data[:PathPrimary]
1356
+ path_mod
1357
+ when nil
1358
+ data[:PathPrimary]
1359
+ else
1360
+ SPARQL::Algebra::Expression("path#{path_mod}", data[:PathPrimary])
1361
+ end
1039
1362
  input[:Path] = res
1040
1363
  end
1041
1364
 
1042
- # [92] PathEltOrInverse ::= PathElt | '^' PathElt
1365
+ # [92] PathEltOrInverse ::= PathElt | '^' PathElt
1366
+ #
1367
+ # Input from `data` is `:reverse` and `:Path`.
1368
+ # Output to prod_data is `:Path` a possibly reversed `:Path`.
1043
1369
  production(:PathEltOrInverse) do |input, data, callback|
1044
1370
  res = if data[:reverse]
1045
1371
  SPARQL::Algebra::Expression(:reverse, data[:Path])
@@ -1049,7 +1375,44 @@ module SPARQL::Grammar
1049
1375
  input[:PathEltOrInverse] = [res]
1050
1376
  end
1051
1377
 
1052
- # [94] PathPrimary ::= iri | 'a' | '!' PathNegatedPropertySet | '(' Path ')'
1378
+ # [93] PathMod ::= '*' | '?' | '+' | '{' INTEGER? (',' INTEGER?)? '}'
1379
+ # '{' INTEGER? (',' INTEGER?)? '}'
1380
+ start_production(:_PathMod_1) do |input, data, callback|
1381
+ data[:pathRange] = [nil]
1382
+ end
1383
+ production(:_PathMod_1) do |input, data, callback|
1384
+ raise Error, "expect property range to have integral elements" if data[:pathRange].all?(&:nil?)
1385
+ min, max = data[:pathRange]
1386
+ min ||= 0
1387
+ max = min if data[:pathRange].length == 1
1388
+ max ||= :*
1389
+
1390
+ # Last operand added in :PathElt
1391
+ add_prod_data(:PathMod, SPARQL::Algebra::Expression(:pathRange, min, max, RDF.nil))
1392
+ end
1393
+
1394
+ # INTEGER?
1395
+ production(:_PathMod_2) do |input, data, callback|
1396
+ input[:pathRange][0] = data[:literal].object
1397
+ end
1398
+
1399
+ # (',' INTEGER?)
1400
+ start_production(:_PathMod_4) do |input, data, callback|
1401
+ data[:pathRange] = [nil, nil]
1402
+ end
1403
+ production(:_PathMod_4) do |input, data, callback|
1404
+ input[:pathRange][1] ||= data.fetch(:pathRange, [0, nil])[1]
1405
+ end
1406
+
1407
+ # INTEGER?
1408
+ production(:_PathMod_5) do |input, data, callback|
1409
+ input[:pathRange][1] = data[:literal].object
1410
+ end
1411
+
1412
+ # [94] PathPrimary ::= iri | 'a' | '!' PathNegatedPropertySet | '(' Path ')'
1413
+ #
1414
+ # Input from `data` is one of `:Verb`, `:iri`, `:PathNegatedPropertySet`, or `:Path`.
1415
+ # Output to prod_data is `:PathPrimary`.
1053
1416
  production(:PathPrimary) do |input, data, callback|
1054
1417
  input[:PathPrimary] = case
1055
1418
  when data[:Verb] then data[:Verb]
@@ -1059,90 +1422,128 @@ module SPARQL::Grammar
1059
1422
  end
1060
1423
  end
1061
1424
 
1062
- # [95] PathNegatedPropertySet ::= PathOneInPropertySet | '(' ( PathOneInPropertySet ( '|' PathOneInPropertySet )* )? ')'
1425
+ # [95] PathNegatedPropertySet ::= PathOneInPropertySet | '(' ( PathOneInPropertySet ( '|' PathOneInPropertySet )* )? ')'
1426
+ #
1427
+ # Input from `data` is TODO.
1428
+ # Output to prod_data is TODO.
1063
1429
  production(:PathNegatedPropertySet) do |input, data, callback|
1064
1430
  input[:Path] = SPARQL::Algebra::Expression(:notoneof, *Array(data[:Path]))
1065
1431
  end
1066
1432
 
1067
1433
  # ( '|' PathOneInPropertySet )* )?
1434
+ #
1435
+ # Input from `data` is TODO.
1436
+ # Output to prod_data is TODO.
1068
1437
  production(:_PathNegatedPropertySet_4) do |input, data, callback|
1069
1438
  add_prod_datum(:Path, data[:Path])
1070
1439
  end
1071
1440
 
1072
- # [96] PathOneInPropertySet ::= iri | 'a' | '^' ( iri | 'a' )
1441
+ # [96] PathOneInPropertySet ::= iri | 'a' | '^' ( iri | 'a' )
1442
+ #
1443
+ # Input from `data` is TODO.
1444
+ # Output to prod_data is TODO.
1073
1445
  production(:PathOneInPropertySet) do |input, data, callback|
1074
1446
  term = (Array(data[:iri]) || data[:Verb]).first
1075
1447
  term = SPARQL::Algebra::Expression(:reverse, term) if data[:reverse]
1076
1448
  input[:Path] = [term]
1077
1449
  end
1078
1450
 
1079
- # [98] TriplesNode ::= Collection | BlankNodePropertyList
1451
+ # [98] TriplesNode ::= Collection | BlankNodePropertyList
1080
1452
  start_production(:TriplesNode) do |input, data, callback|
1081
1453
  # Called after Verb. The prod_data stack should have Subject and Verb elements
1082
1454
  data[:TriplesNode] = bnode
1083
1455
  end
1456
+
1457
+ #
1458
+ # Input from `data` is TODO.
1459
+ # Output to prod_data is TODO.
1084
1460
  production(:TriplesNode) do |input, data, callback|
1085
1461
  add_prod_datum(:pattern, data[:pattern])
1086
1462
  add_prod_datum(:TriplesNode, data[:TriplesNode])
1087
1463
  end
1088
1464
 
1089
- # [100] TriplesNodePath ::= CollectionPath | BlankNodePropertyListPath
1465
+ # [100] TriplesNodePath ::= CollectionPath | BlankNodePropertyListPath
1090
1466
  start_production(:TriplesNodePath) do |input, data, callback|
1091
1467
  # Called after Verb. The prod_data stack should have Subject and Verb elements
1092
1468
  data[:TriplesNode] = bnode
1093
1469
  end
1470
+
1471
+ #
1472
+ # Input from `data` is TODO.
1473
+ # Output to prod_data is TODO.
1094
1474
  production(:TriplesNodePath) do |input, data, callback|
1095
1475
  add_prod_datum(:pattern, data[:pattern])
1096
- add_prod_datum(:path, data[:path])
1097
1476
  add_prod_datum(:TriplesNode, data[:TriplesNode])
1098
1477
  end
1099
1478
 
1100
- # [102] Collection ::= '(' GraphNode+ ')'
1479
+ # [102] Collection ::= '(' GraphNode+ ')'
1101
1480
  start_production(:Collection) do |input, data, callback|
1102
1481
  # Tells the TriplesNode production to collect and not generate statements
1103
- data[:Collection] = prod_data[:TriplesNode]
1482
+ data[:Collection] = input[:TriplesNode]
1104
1483
  end
1484
+
1485
+ #
1486
+ # Input from `data` is TODO.
1487
+ # Output to prod_data is TODO.
1105
1488
  production(:Collection) do |input, data, callback|
1106
1489
  expand_collection(data)
1107
1490
  end
1108
1491
 
1109
- # [103] CollectionPath ::= "(" GraphNodePath+ ")"
1492
+ # [103] CollectionPath ::= "(" GraphNodePath+ ")"
1110
1493
  start_production(:CollectionPath) do |input, data, callback|
1111
1494
  # Tells the TriplesNode production to collect and not generate statements
1112
- data[:Collection] = prod_data[:TriplesNode]
1495
+ data[:Collection] = input[:TriplesNode]
1113
1496
  end
1497
+
1498
+ #
1499
+ # Input from `data` is TODO.
1500
+ # Output to prod_data is TODO.
1114
1501
  production(:CollectionPath) do |input, data, callback|
1115
1502
  expand_collection(data)
1116
- add_prod_datum(:path, data[:path])
1117
1503
  end
1118
1504
 
1119
- # [104] GraphNode ::= VarOrTermOrQuotedTP | TriplesNode
1505
+ # [104] GraphNode ::= VarOrTermOrQuotedTP | TriplesNode
1506
+ #
1507
+ # Input from `data` is TODO.
1508
+ # Output to prod_data is TODO.
1120
1509
  production(:GraphNode) do |input, data, callback|
1121
1510
  term = data[:VarOrTermOrQuotedTP] || data[:TriplesNode]
1122
1511
  add_prod_datum(:pattern, data[:pattern])
1123
1512
  add_prod_datum(:GraphNode, term)
1124
1513
  end
1125
1514
 
1126
- # [105] GraphNodePath ::= VarOrTermOrQuotedTP | TriplesNodePath
1515
+ # [105] GraphNodePath ::= VarOrTermOrQuotedTP | TriplesNodePath
1516
+ #
1517
+ # Input from `data` is either `:VarOrTermOrQUotedTP` or `:TriplesNode`.
1518
+ # Additionally, `:pattern`. Also, `:pattern` and `:path`.
1519
+ # Output to prod_data is `:GraphNode`, along with any `:path` and `:pattern`.
1127
1520
  production(:GraphNodePath) do |input, data, callback|
1128
1521
  term = data[:VarOrTermOrQuotedTP] || data[:TriplesNode]
1129
1522
  add_prod_datum(:pattern, data[:pattern])
1130
- add_prod_datum(:path, data[:path])
1131
1523
  add_prod_datum(:GraphNode, term)
1132
1524
  end
1133
1525
 
1134
- # [106s] VarOrTermOrQuotedTP ::= Var | GraphTerm | EmbTP
1526
+ # [106s] VarOrTermOrQuotedTP ::= Var | GraphTerm | QuotedTP
1527
+ #
1528
+ # Input from `data` is TODO.
1529
+ # Output to prod_data is TODO.
1135
1530
  production(:VarOrTermOrQuotedTP) do |input, data, callback|
1136
1531
  data.values.each {|v| add_prod_datum(:VarOrTermOrQuotedTP, v)}
1137
1532
  end
1138
1533
 
1139
- # [107] VarOrIri ::= Var | iri
1534
+ # [107] VarOrIri ::= Var | iri
1535
+ #
1536
+ # Input from `data` is TODO.
1537
+ # Output to prod_data is TODO.
1140
1538
  production(:VarOrIri) do |input, data, callback|
1141
1539
  data.values.each {|v| add_prod_datum(:VarOrIri, v)}
1142
1540
  end
1143
1541
 
1144
- # [109] GraphTerm ::= iri | RDFLiteral | NumericLiteral
1145
- # | BooleanLiteral | BlankNode | NIL
1542
+ # [109] GraphTerm ::= iri | RDFLiteral | NumericLiteral
1543
+ # | BooleanLiteral | BlankNode | NIL
1544
+ #
1545
+ # Input from `data` is one of `:iri`, `:literal`, `:BlankNode`, or `:NIL`.
1546
+ # Output to prod_data is `:GraphTerm` created from the data.
1146
1547
  production(:GraphTerm) do |input, data, callback|
1147
1548
  add_prod_datum(:GraphTerm,
1148
1549
  data[:iri] ||
@@ -1151,42 +1552,60 @@ module SPARQL::Grammar
1151
1552
  data[:NIL])
1152
1553
  end
1153
1554
 
1154
- # [110] Expression ::= ConditionalOrExpression
1555
+ # [110] Expression ::= ConditionalOrExpression
1556
+ #
1557
+ # Input from `data` is TODO.
1558
+ # Output to prod_data is TODO.
1155
1559
  production(:Expression) do |input, data, callback|
1156
1560
  add_prod_datum(:Expression, data[:Expression])
1157
1561
  end
1158
1562
 
1159
- # [111] ConditionalOrExpression ::= ConditionalAndExpression
1160
- # ( '||' ConditionalAndExpression )*
1563
+ # [111] ConditionalOrExpression ::= ConditionalAndExpression
1564
+ # ( '||' ConditionalAndExpression )*
1565
+ #
1566
+ # Input from `data` is TODO.
1567
+ # Output to prod_data is TODO.
1161
1568
  production(:ConditionalOrExpression) do |input, data, callback|
1162
1569
  add_operator_expressions(:_OR, data)
1163
1570
  end
1164
1571
 
1165
1572
  # ( '||' ConditionalAndExpression )*
1573
+ #
1574
+ # Input from `data` is TODO.
1575
+ # Output to prod_data is TODO.
1166
1576
  production(:_ConditionalOrExpression_1) do |input, data, callback|
1167
1577
  accumulate_operator_expressions(:ConditionalOrExpression, :_OR, data)
1168
1578
  end
1169
1579
 
1170
- # [112] ConditionalAndExpression ::= ValueLogical ( '&&' ValueLogical )*
1580
+ # [112] ConditionalAndExpression ::= ValueLogical ( '&&' ValueLogical )*
1581
+ #
1582
+ # Input from `data` is TODO.
1583
+ # Output to prod_data is TODO.
1171
1584
  production(:ConditionalAndExpression) do |input, data, callback|
1172
1585
  add_operator_expressions(:_AND, data)
1173
1586
  end
1174
1587
 
1175
1588
  # ( '||' ConditionalAndExpression )*
1589
+ #
1590
+ # Input from `data` is TODO.
1591
+ # Output to prod_data is TODO.
1176
1592
  production(:_ConditionalAndExpression_1) do |input, data, callback|
1177
1593
  accumulate_operator_expressions(:ConditionalAndExpression, :_AND, data)
1178
1594
  end
1179
1595
 
1180
- # [114] RelationalExpression ::= NumericExpression
1181
- # ( '=' NumericExpression
1182
- # | '!=' NumericExpression
1183
- # | '<' NumericExpression
1184
- # | '>' NumericExpression
1185
- # | '<=' NumericExpression
1186
- # | '>=' NumericExpression
1187
- # | 'IN' ExpressionList
1188
- # | 'NOT' 'IN' ExpressionList
1189
- # )?
1596
+ # [114] RelationalExpression ::= NumericExpression
1597
+ # ( '=' NumericExpression
1598
+ # | '!=' NumericExpression
1599
+ # | '<' NumericExpression
1600
+ # | '>' NumericExpression
1601
+ # | '<=' NumericExpression
1602
+ # | '>=' NumericExpression
1603
+ # | 'IN' ExpressionList
1604
+ # | 'NOT' 'IN' ExpressionList
1605
+ # )?
1606
+ #
1607
+ # Input from `data` is TODO.
1608
+ # Output to prod_data is TODO.
1190
1609
  production(:RelationalExpression) do |input, data, callback|
1191
1610
  if data[:_Compare_Numeric]
1192
1611
  add_prod_datum(:Expression, SPARQL::Algebra::Expression.for(data[:_Compare_Numeric].insert(1, *data[:Expression])))
@@ -1203,6 +1622,9 @@ module SPARQL::Grammar
1203
1622
  end
1204
1623
 
1205
1624
  # ( '=' NumericExpression | '!=' NumericExpression | ... )?
1625
+ #
1626
+ # Input from `data` is TODO.
1627
+ # Output to prod_data is TODO.
1206
1628
  production(:_RelationalExpression_1) do |input, data, callback|
1207
1629
  if data[:RelationalExpression]
1208
1630
  add_prod_datum(:_Compare_Numeric, data[:RelationalExpression] + data[:Expression])
@@ -1214,11 +1636,17 @@ module SPARQL::Grammar
1214
1636
  end
1215
1637
 
1216
1638
  # 'IN' ExpressionList
1639
+ #
1640
+ # Input from `data` is TODO.
1641
+ # Output to prod_data is TODO.
1217
1642
  production(:_RelationalExpression_9) do |input, data, callback|
1218
1643
  add_prod_datum(:in, data[:ExpressionList])
1219
1644
  end
1220
1645
 
1221
1646
  # 'NOT' 'IN' ExpressionList
1647
+ #
1648
+ # Input from `data` is TODO.
1649
+ # Output to prod_data is TODO.
1222
1650
  production(:_RelationalExpression_10) do |input, data, callback|
1223
1651
  add_prod_datum(:notin, data[:ExpressionList])
1224
1652
  end
@@ -1226,10 +1654,14 @@ module SPARQL::Grammar
1226
1654
  # [116] AdditiveExpression ::= MultiplicativeExpression
1227
1655
  # ( '+' MultiplicativeExpression
1228
1656
  # | '-' MultiplicativeExpression
1229
- # | ( NumericLiteralPositive | NumericLiteralNegative )
1657
+ # | ( NumericLiteralPositive
1658
+ # | NumericLiteralNegative )
1230
1659
  # ( ( '*' UnaryExpression )
1231
1660
  # | ( '/' UnaryExpression ) )?
1232
1661
  # )*
1662
+ #
1663
+ # Input from `data` is TODO.
1664
+ # Output to prod_data is TODO.
1233
1665
  production(:AdditiveExpression) do |input, data, callback|
1234
1666
  add_operator_expressions(:_Add_Sub, data)
1235
1667
  end
@@ -1240,11 +1672,17 @@ module SPARQL::Grammar
1240
1672
  # ( ( '*' UnaryExpression )
1241
1673
  # | ( '/' UnaryExpression ) )?
1242
1674
  # )*
1675
+ #
1676
+ # Input from `data` is TODO.
1677
+ # Output to prod_data is TODO.
1243
1678
  production(:_AdditiveExpression_1) do |input, data, callback|
1244
1679
  accumulate_operator_expressions(:AdditiveExpression, :_Add_Sub, data)
1245
1680
  end
1246
1681
 
1247
1682
  # | ( NumericLiteralPositive | NumericLiteralNegative )
1683
+ #
1684
+ # Input from `data` is TODO.
1685
+ # Output to prod_data is TODO.
1248
1686
  production(:_AdditiveExpression_7) do |input, data, callback|
1249
1687
  lit = data[:literal]
1250
1688
  val = lit.to_s
@@ -1253,23 +1691,32 @@ module SPARQL::Grammar
1253
1691
  add_prod_datum(:Expression, [lit.class.new(val)])
1254
1692
  end
1255
1693
 
1256
- # [117] MultiplicativeExpression ::= UnaryExpression
1257
- # ( '*' UnaryExpression
1258
- # | '/' UnaryExpression )*
1694
+ # [117] MultiplicativeExpression ::= UnaryExpression
1695
+ # ( '*' UnaryExpression
1696
+ # | '/' UnaryExpression )*
1697
+ #
1698
+ # Input from `data` is TODO.
1699
+ # Output to prod_data is TODO.
1259
1700
  production(:MultiplicativeExpression) do |input, data, callback|
1260
1701
  add_operator_expressions(:_Mul_Div, data)
1261
1702
  end
1262
1703
 
1263
1704
  # ( '*' UnaryExpression
1264
1705
  # | '/' UnaryExpression )*
1706
+ #
1707
+ # Input from `data` is TODO.
1708
+ # Output to prod_data is TODO.
1265
1709
  production(:_MultiplicativeExpression_1) do |input, data, callback|
1266
1710
  accumulate_operator_expressions(:MultiplicativeExpression, :_Mul_Div, data)
1267
1711
  end
1268
1712
 
1269
- # [118] UnaryExpression ::= '!' PrimaryExpression
1270
- # | '+' PrimaryExpression
1271
- # | '-' PrimaryExpression
1272
- # | PrimaryExpression
1713
+ # [118] UnaryExpression ::= '!' PrimaryExpression
1714
+ # | '+' PrimaryExpression
1715
+ # | '-' PrimaryExpression
1716
+ # | PrimaryExpression
1717
+ #
1718
+ # Input from `data` is TODO.
1719
+ # Output to prod_data is TODO.
1273
1720
  production(:UnaryExpression) do |input, data, callback|
1274
1721
  case data[:UnaryExpression]
1275
1722
  when ["!"]
@@ -1286,11 +1733,14 @@ module SPARQL::Grammar
1286
1733
  end
1287
1734
  end
1288
1735
 
1289
- # [119] PrimaryExpression ::= BrackettedExpression | BuiltInCall
1290
- # | iriOrFunction | RDFLiteral
1291
- # | NumericLiteral | BooleanLiteral
1292
- # | Var
1293
- # | ExprQuotedTP
1736
+ # [119] PrimaryExpression ::= BrackettedExpression | BuiltInCall
1737
+ # | iriOrFunction | RDFLiteral
1738
+ # | NumericLiteral | BooleanLiteral
1739
+ # | Var
1740
+ # | ExprQuotedTP
1741
+ #
1742
+ # Input from `data` is TODO.
1743
+ # Output to prod_data is TODO.
1294
1744
  production(:PrimaryExpression) do |input, data, callback|
1295
1745
  if data[:Expression]
1296
1746
  add_prod_datum(:Expression, data[:Expression])
@@ -1312,62 +1762,65 @@ module SPARQL::Grammar
1312
1762
  add_prod_datum(:UnaryExpression, data[:UnaryExpression])
1313
1763
  end
1314
1764
 
1315
- # [121] BuiltInCall ::= Aggregate
1316
- # | 'STR' '(' Expression ')'
1317
- # | 'LANG' '(' Expression ')'
1318
- # | 'LANGMATCHES' '(' Expression ',' Expression ')'
1319
- # | 'DATATYPE' '(' Expression ')'
1320
- # | 'BOUND' '(' Var ')'
1321
- # | 'IRI' '(' Expression ')'
1322
- # | 'URI' '(' Expression ')'
1323
- # | 'BNODE' ( '(' Expression ')' | NIL )
1324
- # | 'RAND' NIL
1325
- # | 'ABS' '(' Expression ')'
1326
- # | 'CEIL' '(' Expression ')'
1327
- # | 'FLOOR' '(' Expression ')'
1328
- # | 'ROUND' '(' Expression ')'
1329
- # | 'CONCAT' ExpressionList
1330
- # | SubstringExpression
1331
- # | 'STRLEN' '(' Expression ')'
1332
- # | StrReplaceExpression
1333
- # | 'UCASE' '(' Expression ')'
1334
- # | 'LCASE' '(' Expression ')'
1335
- # | 'ENCODE_FOR_URI' '(' Expression ')'
1336
- # | 'CONTAINS' '(' Expression ',' Expression ')'
1337
- # | 'STRSTARTS' '(' Expression ',' Expression ')'
1338
- # | 'STRENDS' '(' Expression ',' Expression ')'
1339
- # | 'STRBEFORE' '(' Expression ',' Expression ')'
1340
- # | 'STRAFTER' '(' Expression ',' Expression ')'
1341
- # | 'YEAR' '(' Expression ')'
1342
- # | 'MONTH' '(' Expression ')'
1343
- # | 'DAY' '(' Expression ')'
1344
- # | 'HOURS' '(' Expression ')'
1345
- # | 'MINUTES' '(' Expression ')'
1346
- # | 'SECONDS' '(' Expression ')'
1347
- # | 'TIMEZONE' '(' Expression ')'
1348
- # | 'TZ' '(' Expression ')'
1349
- # | 'NOW' NIL
1350
- # | 'UUID' NIL
1351
- # | 'STRUUID' NIL
1352
- # | 'MD5' '(' Expression ')'
1353
- # | 'SHA1' '(' Expression ')'
1354
- # | 'SHA224' '(' Expression ')'
1355
- # | 'SHA256' '(' Expression ')'
1356
- # | 'SHA384' '(' Expression ')'
1357
- # | 'SHA512' '(' Expression ')'
1358
- # | 'COALESCE' ExpressionList
1359
- # | 'IF' '(' Expression ',' Expression ',' Expression ')'
1360
- # | 'STRLANG' '(' Expression ',' Expression ')'
1361
- # | 'STRDT' '(' Expression ',' Expression ')'
1362
- # | 'sameTerm' '(' Expression ',' Expression ')'
1363
- # | 'isIRI' '(' Expression ')'
1364
- # | 'isURI' '(' Expression ')'
1365
- # | 'isBLANK' '(' Expression ')'
1366
- # | 'isLITERAL' '(' Expression ')'
1367
- # | 'isNUMERIC' '(' Expression ')'
1368
- # | RegexExpression
1369
- # | ExistsFunc
1370
- # | NotExistsFunc
1765
+ # [121] BuiltInCall ::= Aggregate
1766
+ # | 'STR' '(' Expression ')'
1767
+ # | 'LANG' '(' Expression ')'
1768
+ # | 'LANGMATCHES' '(' Expression ',' Expression ')'
1769
+ # | 'DATATYPE' '(' Expression ')'
1770
+ # | 'BOUND' '(' Var ')'
1771
+ # | 'IRI' '(' Expression ')'
1772
+ # | 'URI' '(' Expression ')'
1773
+ # | 'BNODE' ( '(' Expression ')' | NIL )
1774
+ # | 'RAND' NIL
1775
+ # | 'ABS' '(' Expression ')'
1776
+ # | 'CEIL' '(' Expression ')'
1777
+ # | 'FLOOR' '(' Expression ')'
1778
+ # | 'ROUND' '(' Expression ')'
1779
+ # | 'CONCAT' ExpressionList
1780
+ # | SubstringExpression
1781
+ # | 'STRLEN' '(' Expression ')'
1782
+ # | StrReplaceExpression
1783
+ # | 'UCASE' '(' Expression ')'
1784
+ # | 'LCASE' '(' Expression ')'
1785
+ # | 'ENCODE_FOR_URI' '(' Expression ')'
1786
+ # | 'CONTAINS' '(' Expression ',' Expression ')'
1787
+ # | 'STRSTARTS' '(' Expression ',' Expression ')'
1788
+ # | 'STRENDS' '(' Expression ',' Expression ')'
1789
+ # | 'STRBEFORE' '(' Expression ',' Expression ')'
1790
+ # | 'STRAFTER' '(' Expression ',' Expression ')'
1791
+ # | 'YEAR' '(' Expression ')'
1792
+ # | 'MONTH' '(' Expression ')'
1793
+ # | 'DAY' '(' Expression ')'
1794
+ # | 'HOURS' '(' Expression ')'
1795
+ # | 'MINUTES' '(' Expression ')'
1796
+ # | 'SECONDS' '(' Expression ')'
1797
+ # | 'TIMEZONE' '(' Expression ')'
1798
+ # | 'TZ' '(' Expression ')'
1799
+ # | 'NOW' NIL
1800
+ # | 'UUID' NIL
1801
+ # | 'STRUUID' NIL
1802
+ # | 'MD5' '(' Expression ')'
1803
+ # | 'SHA1' '(' Expression ')'
1804
+ # | 'SHA224' '(' Expression ')'
1805
+ # | 'SHA256' '(' Expression ')'
1806
+ # | 'SHA384' '(' Expression ')'
1807
+ # | 'SHA512' '(' Expression ')'
1808
+ # | 'COALESCE' ExpressionList
1809
+ # | 'IF' '(' Expression ',' Expression ',' Expression ')'
1810
+ # | 'STRLANG' '(' Expression ',' Expression ')'
1811
+ # | 'STRDT' '(' Expression ',' Expression ')'
1812
+ # | 'sameTerm' '(' Expression ',' Expression ')'
1813
+ # | 'isIRI' '(' Expression ')'
1814
+ # | 'isURI' '(' Expression ')'
1815
+ # | 'isBLANK' '(' Expression ')'
1816
+ # | 'isLITERAL' '(' Expression ')'
1817
+ # | 'isNUMERIC' '(' Expression ')'
1818
+ # | RegexExpression
1819
+ # | ExistsFunc
1820
+ # | NotExistsFunc
1821
+ #
1822
+ # Input from `data` is TODO.
1823
+ # Output to prod_data is TODO.
1371
1824
  production(:BuiltInCall) do |input, data, callback|
1372
1825
  input[:BuiltInCall] = if builtin = data.keys.detect {|k| BUILTINS.include?(k)}
1373
1826
  SPARQL::Algebra::Expression.for(
@@ -1384,45 +1837,63 @@ module SPARQL::Grammar
1384
1837
  end
1385
1838
  end
1386
1839
 
1387
- # [122] RegexExpression ::= 'REGEX' '(' Expression ',' Expression
1388
- # ( ',' Expression )? ')'
1840
+ # [122] RegexExpression ::= 'REGEX' '(' Expression ',' Expression
1841
+ # ( ',' Expression )? ')'
1842
+ #
1843
+ # Input from `data` is TODO.
1844
+ # Output to prod_data is TODO.
1389
1845
  production(:RegexExpression) do |input, data, callback|
1390
1846
  add_prod_datum(:regex, data[:Expression])
1391
1847
  end
1392
1848
 
1393
- # [123] SubstringExpression ::= 'SUBSTR'
1394
- # '(' Expression ',' Expression
1395
- # ( ',' Expression )? ')'
1849
+ # [123] SubstringExpression ::= 'SUBSTR'
1850
+ # '(' Expression ',' Expression
1851
+ # ( ',' Expression )? ')'
1852
+ #
1853
+ # Input from `data` is TODO.
1854
+ # Output to prod_data is TODO.
1396
1855
  production(:SubstringExpression) do |input, data, callback|
1397
1856
  add_prod_datum(:substr, data[:Expression])
1398
1857
  end
1399
1858
 
1400
- # [124] StrReplaceExpression ::= 'REPLACE'
1401
- # '(' Expression ','
1402
- # Expression ',' Expression
1403
- # ( ',' Expression )? ')'
1859
+ # [124] StrReplaceExpression ::= 'REPLACE'
1860
+ # '(' Expression ','
1861
+ # Expression ',' Expression
1862
+ # ( ',' Expression )? ')'
1863
+ #
1864
+ # Input from `data` is TODO.
1865
+ # Output to prod_data is TODO.
1404
1866
  production(:StrReplaceExpression) do |input, data, callback|
1405
1867
  add_prod_datum(:replace, data[:Expression])
1406
1868
  end
1407
1869
 
1408
- # [125] ExistsFunc ::= 'EXISTS' GroupGraphPattern
1870
+ # [125] ExistsFunc ::= 'EXISTS' GroupGraphPattern
1871
+ #
1872
+ # Input from `data` is TODO.
1873
+ # Output to prod_data is TODO.
1409
1874
  production(:ExistsFunc) do |input, data, callback|
1410
1875
  add_prod_datum(:exists, data[:query])
1411
1876
  end
1412
1877
 
1413
- # [126] NotExistsFunc ::= 'NOT' 'EXISTS' GroupGraphPattern
1878
+ # [126] NotExistsFunc ::= 'NOT' 'EXISTS' GroupGraphPattern
1879
+ #
1880
+ # Input from `data` is TODO.
1881
+ # Output to prod_data is TODO.
1414
1882
  production(:NotExistsFunc) do |input, data, callback|
1415
1883
  add_prod_datum(:notexists, data[:query])
1416
1884
  end
1417
1885
 
1418
- # [127] Aggregate ::= 'COUNT' '(' 'DISTINCT'? ( '*' | Expression ) ')'
1419
- # | 'SUM' '(' 'DISTINCT'? Expression ')'
1420
- # | 'MIN' '(' 'DISTINCT'? Expression ')'
1421
- # | 'MAX' '(' 'DISTINCT'? Expression ')'
1422
- # | 'AVG' '(' 'DISTINCT'? Expression ')'
1423
- # | 'SAMPLE' '(' 'DISTINCT'? Expression ')'
1424
- # | 'GROUP_CONCAT' '(' 'DISTINCT'? Expression
1425
- # ( ';' 'SEPARATOR' '=' String )? ')'
1886
+ # [127] Aggregate ::= 'COUNT' '(' 'DISTINCT'? ( '*' | Expression ) ')'
1887
+ # | 'SUM' '(' 'DISTINCT'? Expression ')'
1888
+ # | 'MIN' '(' 'DISTINCT'? Expression ')'
1889
+ # | 'MAX' '(' 'DISTINCT'? Expression ')'
1890
+ # | 'AVG' '(' 'DISTINCT'? Expression ')'
1891
+ # | 'SAMPLE' '(' 'DISTINCT'? Expression ')'
1892
+ # | 'GROUP_CONCAT' '(' 'DISTINCT'? Expression
1893
+ # ( ';' 'SEPARATOR' '=' String )? ')'
1894
+ #
1895
+ # Input from `data` is TODO.
1896
+ # Output to prod_data is TODO.
1426
1897
  production(:Aggregate) do |input, data, callback|
1427
1898
  if aggregate_rule = data.keys.detect {|k| AGGREGATE_RULES.include?(k)}
1428
1899
  parts = [aggregate_rule]
@@ -1433,30 +1904,39 @@ module SPARQL::Grammar
1433
1904
  end
1434
1905
  end
1435
1906
 
1436
- # [128] iriOrFunction ::= iri ArgList?
1907
+ # [128] iriOrFunction ::= iri ArgList?
1908
+ #
1909
+ # Input from `data` is TODO.
1910
+ # Output to prod_data is TODO.
1437
1911
  production(:iriOrFunction) do |input, data, callback|
1438
1912
  if data.has_key?(:ArgList)
1439
1913
  # Function is (func arg1 arg2 ...)
1440
- add_prod_data(:Function, Array(data[:iri]) + data[:ArgList])
1914
+ add_prod_data(:Function, SPARQL::Algebra::Operator::FunctionCall.new(data[:iri], *data[:ArgList]))
1441
1915
  else
1442
1916
  input[:iri] = data[:iri]
1443
1917
  end
1444
1918
  end
1445
1919
 
1446
- # [129] RDFLiteral ::= String ( LANGTAG | ( '^^' iri ) )?
1920
+ # [129] RDFLiteral ::= String ( LANGTAG | ( '^^' iri ) )?
1921
+ #
1922
+ # Input from `data` is TODO.
1923
+ # Output to prod_data is TODO.
1447
1924
  production(:RDFLiteral) do |input, data, callback|
1448
1925
  if data[:string]
1449
1926
  lit = data.dup
1450
1927
  str = lit.delete(:string)
1451
1928
  lit[:datatype] = lit.delete(:iri) if lit[:iri]
1452
- lit[:language] = lit.delete(:language).last.downcase if lit[:language]
1929
+ lit[:language] = lit.delete(:language).downcase if lit[:language]
1453
1930
  input[:literal] = RDF::Literal.new(str, **lit) if str
1454
1931
  end
1455
1932
  end
1456
1933
 
1457
- # [132] NumericLiteralPositive ::= INTEGER_POSITIVE
1458
- # | DECIMAL_POSITIVE
1459
- # | DOUBLE_POSITIVE
1934
+ # [132] NumericLiteralPositive ::= INTEGER_POSITIVE
1935
+ # | DECIMAL_POSITIVE
1936
+ # | DOUBLE_POSITIVE
1937
+ #
1938
+ # Input from `data` is TODO.
1939
+ # Output to prod_data is TODO.
1460
1940
  production(:NumericLiteralPositive) do |input, data, callback|
1461
1941
  num = data.values.flatten.last
1462
1942
  input[:literal] = num
@@ -1465,9 +1945,12 @@ module SPARQL::Grammar
1465
1945
  add_prod_datum(:UnaryExpression, data[:UnaryExpression])
1466
1946
  end
1467
1947
 
1468
- # [133] NumericLiteralNegative ::= INTEGER_NEGATIVE
1469
- # | DECIMAL_NEGATIVE
1470
- # | DOUBLE_NEGATIVE
1948
+ # [133] NumericLiteralNegative ::= INTEGER_NEGATIVE
1949
+ # | DECIMAL_NEGATIVE
1950
+ # | DOUBLE_NEGATIVE
1951
+ #
1952
+ # Input from `data` is TODO.
1953
+ # Output to prod_data is TODO.
1471
1954
  production(:NumericLiteralNegative) do |input, data, callback|
1472
1955
  num = data.values.flatten.last
1473
1956
  input[:literal] = num
@@ -1477,61 +1960,81 @@ module SPARQL::Grammar
1477
1960
  end
1478
1961
 
1479
1962
  # [174] QuotedTP ::= '<<' qtSubjectOrObject Verb qtSubjectOrObject '>>'
1963
+ #
1964
+ # Input from `data` is `:qtSubjectOrObject` from which subject and object are extracted and `:Verb` from which predicate is extracted.
1965
+ # Output to prod_data is `:QuotedTP` containing subject, predicate, and object.
1480
1966
  production(:QuotedTP) do |input, data, callback|
1481
1967
  subject, object = data[:qtSubjectOrObject]
1482
1968
  predicate = data[:Verb]
1483
1969
  add_pattern(:QuotedTP,
1484
1970
  subject: subject,
1485
1971
  predicate: predicate,
1486
- object: object)
1972
+ object: object,
1973
+ quoted: true)
1487
1974
  end
1488
1975
 
1489
1976
  # [175] QuotedTriple ::= '<<' DataValueTerm (iri | 'a') DataValueTerm '>>'
1977
+ #
1978
+ # Input from `data` is TODO.
1979
+ # Output to prod_data is TODO.
1490
1980
  production(:QuotedTriple) do |input, data, callback|
1491
1981
  subject, object = data[:DataValueTerm]
1492
1982
  predicate = data[:iri]
1493
1983
  add_pattern(:QuotedTriple,
1494
1984
  subject: subject,
1495
1985
  predicate: predicate,
1496
- object: object)
1986
+ object: object,
1987
+ quoted: true)
1497
1988
  end
1498
1989
 
1499
- # [176] qtSubjectOrObject ::= Var | BlankNode | iri | RDFLiteral
1500
- # | NumericLiteral | BooleanLiteral | QuotedTP
1990
+ # [176] qtSubjectOrObject ::= Var | BlankNode | iri | RDFLiteral
1991
+ # | NumericLiteral | BooleanLiteral | QuotedTP
1992
+ #
1993
+ # Input from `data` is TODO.
1994
+ # Output to prod_data is TODO.
1501
1995
  production(:qtSubjectOrObject) do |input, data, callback|
1502
1996
  data.values.each {|v| add_prod_datum(:qtSubjectOrObject, v)}
1503
1997
  end
1504
1998
 
1505
- # [177] DataValueTerm ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | QuotedTriple
1999
+ # [177] DataValueTerm ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | QuotedTriple
2000
+ #
2001
+ # Input from `data` is TODO.
2002
+ # Output to prod_data is TODO.
1506
2003
  production(:DataValueTerm) do |input, data, callback|
1507
2004
  add_prod_datum :DataValueTerm, data.values.first
1508
2005
  end
1509
2006
 
1510
- # [180] AnnotationPatternPath ::= '{|' PropertyListPathNotEmpty '|}'
2007
+ # [180] AnnotationPatternPath ::= '{|' PropertyListPathNotEmpty '|}'
1511
2008
  start_production(:AnnotationPatternPath) do |input, data, callback|
1512
2009
  data[:TriplesNode] = input[:TriplesNode]
1513
2010
  end
2011
+
2012
+ #
2013
+ # Add `:TriplesNode` as subject of collected patterns
2014
+ # Input from `data` is `:pattern`.
2015
+ # Output to prod_data is `:pattern`.
1514
2016
  production(:AnnotationPatternPath) do |input, data, callback|
1515
- if data[:pattern]
1516
- add_prod_datum(:pattern, data[:pattern])
1517
- elsif data[:path]
1518
- # Replace the subject in the path with the node being annotated.
1519
- data[:path].first.operands[0] = data[:TriplesNode]
1520
- add_prod_datum(:path, data[:path])
1521
- end
2017
+ add_prod_datum(:pattern, data[:pattern])
1522
2018
  end
1523
2019
 
1524
2020
  # [181] ExprQuotedTP ::= '<<' ExprVarOrTerm Verb ExprVarOrTerm '>>'
2021
+ #
2022
+ # Input from `data` is TODO.
2023
+ # Output to prod_data is TODO.
1525
2024
  production(:ExprQuotedTP) do |input, data, callback|
1526
2025
  subject, object = data[:ExprVarOrTerm]
1527
2026
  predicate = data[:Verb]
1528
2027
  add_pattern(:ExprQuotedTP,
1529
2028
  subject: subject,
1530
2029
  predicate: predicate,
1531
- object: object)
2030
+ object: object,
2031
+ quoted: true)
1532
2032
  end
1533
2033
 
1534
- # [182] ExprVarOrTerm ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | Var | ExprQuotedTP
2034
+ # [182] ExprVarOrTerm ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | Var | ExprQuotedTP
2035
+ #
2036
+ # Input from `data` is TODO.
2037
+ # Output to prod_data is TODO.
1535
2038
  production(:ExprVarOrTerm) do |input, data, callback|
1536
2039
  data.values.each {|v| add_prod_datum(:ExprVarOrTerm, v)}
1537
2040
  end
@@ -1541,20 +2044,23 @@ module SPARQL::Grammar
1541
2044
  #
1542
2045
  # @param [String, IO, StringIO, #to_s] input
1543
2046
  # @param [Hash{Symbol => Object}] options
1544
- # @option options [Hash] :prefixes (Hash.new)
1545
- # the prefix mappings to use (for acessing intermediate parser productions)
1546
- # @option options [#to_s] :base_uri (nil)
1547
- # the base URI to use when resolving relative URIs (for acessing intermediate parser productions)
2047
+ # @option options [Boolean] :all_vars (false)
2048
+ # If `true`, emits on empty `project` operator when parsing `SELECT *`, which will emit all in-scope variables, rather than just those used in solutions.
2049
+ # In the next minor release, the default for this option will change to `true`.
1548
2050
  # @option options [#to_s] :anon_base ("b0")
1549
2051
  # Basis for generating anonymous Nodes
2052
+ # @option options [#to_s] :base_uri (nil)
2053
+ # the base URI to use when resolving relative URIs (for acessing intermediate parser productions)
2054
+ # @option options [Logger, #write, #<<] :logger
2055
+ # Record error/info/debug output
2056
+ # @option options [Hash] :prefixes (Hash.new)
2057
+ # the prefix mappings to use (for acessing intermediate parser productions)
1550
2058
  # @option options [Boolean] :resolve_iris (false)
1551
2059
  # Resolve prefix and relative IRIs, otherwise, when serializing the parsed SSE
1552
2060
  # as S-Expressions, use the original prefixed and relative URIs along with `base` and `prefix`
1553
2061
  # definitions.
1554
2062
  # @option options [Boolean] :validate (false)
1555
2063
  # whether to validate the parsed statements and values
1556
- # @option options [Logger, #write, #<<] :logger
1557
- # Record error/info/debug output
1558
2064
  # @yield [parser] `self`
1559
2065
  # @yieldparam [SPARQL::Grammar::Parser] parser
1560
2066
  # @yieldreturn [void] ignored
@@ -1615,7 +2121,7 @@ module SPARQL::Grammar
1615
2121
  #
1616
2122
  # @param [Symbol, #to_s] prod The starting production for the parser.
1617
2123
  # It may be a URI from the grammar, or a symbol representing the local_name portion of the grammar URI.
1618
- # @return [Array]
2124
+ # @return [RDF::Queryable]
1619
2125
  # @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
1620
2126
  # @see https://axel.deri.ie/sparqltutorial/ESWC2007_SPARQL_Tutorial_unit2b.pdf
1621
2127
  def parse(prod = START)
@@ -1811,9 +2317,7 @@ module SPARQL::Grammar
1811
2317
  # If we have a base URI, use that when constructing a new URI
1812
2318
  value = RDF::URI(value)
1813
2319
  if base_uri && value.relative?
1814
- u = base_uri.join(value)
1815
- #u.lexical = "<#{value}>" unless resolve_iris?
1816
- #u
2320
+ base_uri.join(value)
1817
2321
  else
1818
2322
  value
1819
2323
  end
@@ -1823,10 +2327,7 @@ module SPARQL::Grammar
1823
2327
  base = prefix(prefix).to_s
1824
2328
  suffix = suffix.to_s.sub(/^\#/, "") if base.index("#")
1825
2329
  debug {"ns(#{prefix.inspect}): base: '#{base}', suffix: '#{suffix}'"}
1826
- iri = iri(base + suffix.to_s)
1827
- # Cause URI to be serialized as a lexical
1828
- #iri.lexical = "#{prefix}:#{suffix}" unless resolve_iris?
1829
- #iri
2330
+ iri(base + suffix.to_s)
1830
2331
  end
1831
2332
 
1832
2333
  # Create a literal
@@ -1869,10 +2370,12 @@ module SPARQL::Grammar
1869
2370
  # add a pattern
1870
2371
  #
1871
2372
  # @param [String] production Production generating pattern
2373
+ # @param [Boolean] quoted For quoted triple
1872
2374
  # @param [Hash{Symbol => Object}] options
1873
- def add_pattern(production, **options)
2375
+ def add_pattern(production, quoted: false, **options)
1874
2376
  progress(production, "[:pattern, #{options[:subject]}, #{options[:predicate]}, #{options[:object]}]")
1875
2377
  triple = {}
2378
+ triple[:quoted] = true if quoted
1876
2379
  options.each_pair do |r, v|
1877
2380
  if v.is_a?(Array) && v.flatten.length == 1
1878
2381
  v = v.flatten.first
@@ -1894,6 +2397,7 @@ module SPARQL::Grammar
1894
2397
  [expr, query]
1895
2398
  end
1896
2399
 
2400
+ ##
1897
2401
  # Merge query modifiers, datasets, and projections
1898
2402
  #
1899
2403
  # This includes tranforming aggregates if also used with a GROUP BY
@@ -1988,7 +2492,14 @@ module SPARQL::Grammar
1988
2492
 
1989
2493
  query = SPARQL::Algebra::Expression[:order, data[:order].first, query] unless order.empty?
1990
2494
 
1991
- query = SPARQL::Algebra::Expression[:project, vars, query] unless vars.empty?
2495
+ # If SELECT * was used, emit a projection with empty variables, vs no projection at all. Only if :all_vars is true
2496
+ query = if vars == %i(*)
2497
+ options[:all_vars] ? SPARQL::Algebra::Expression[:project, [], query] : query
2498
+ elsif !vars.empty?
2499
+ SPARQL::Algebra::Expression[:project, vars, query]
2500
+ else
2501
+ query
2502
+ end
1992
2503
 
1993
2504
  query = SPARQL::Algebra::Expression[data[:DISTINCT_REDUCED], query] if data[:DISTINCT_REDUCED]
1994
2505