sparql 3.2.1 → 3.2.3

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +57 -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 +35 -7
  9. data/lib/sparql/algebra/extensions.rb +18 -18
  10. data/lib/sparql/algebra/operator/adjust.rb +69 -0
  11. data/lib/sparql/algebra/operator/bgp.rb +1 -1
  12. data/lib/sparql/algebra/operator/construct.rb +1 -1
  13. data/lib/sparql/algebra/operator/dataset.rb +10 -0
  14. data/lib/sparql/algebra/operator/day.rb +2 -2
  15. data/lib/sparql/algebra/operator/delete.rb +1 -1
  16. data/lib/sparql/algebra/operator/delete_data.rb +1 -1
  17. data/lib/sparql/algebra/operator/delete_where.rb +1 -1
  18. data/lib/sparql/algebra/operator/extend.rb +32 -2
  19. data/lib/sparql/algebra/operator/group.rb +34 -6
  20. data/lib/sparql/algebra/operator/hours.rb +2 -2
  21. data/lib/sparql/algebra/operator/insert.rb +1 -1
  22. data/lib/sparql/algebra/operator/insert_data.rb +1 -1
  23. data/lib/sparql/algebra/operator/join.rb +3 -3
  24. data/lib/sparql/algebra/operator/left_join.rb +3 -3
  25. data/lib/sparql/algebra/operator/minus.rb +1 -1
  26. data/lib/sparql/algebra/operator/minutes.rb +2 -2
  27. data/lib/sparql/algebra/operator/modify.rb +21 -0
  28. data/lib/sparql/algebra/operator/month.rb +2 -2
  29. data/lib/sparql/algebra/operator/path_opt.rb +9 -65
  30. data/lib/sparql/algebra/operator/path_plus.rb +18 -10
  31. data/lib/sparql/algebra/operator/path_range.rb +178 -0
  32. data/lib/sparql/algebra/operator/path_star.rb +7 -4
  33. data/lib/sparql/algebra/operator/path_zero.rb +110 -0
  34. data/lib/sparql/algebra/operator/plus.rb +7 -5
  35. data/lib/sparql/algebra/operator/project.rb +42 -1
  36. data/lib/sparql/algebra/operator/seconds.rb +2 -2
  37. data/lib/sparql/algebra/operator/seq.rb +3 -3
  38. data/lib/sparql/algebra/operator/sequence.rb +10 -0
  39. data/lib/sparql/algebra/operator/subtract.rb +9 -5
  40. data/lib/sparql/algebra/operator/table.rb +11 -2
  41. data/lib/sparql/algebra/operator/timezone.rb +2 -2
  42. data/lib/sparql/algebra/operator/triple.rb +51 -0
  43. data/lib/sparql/algebra/operator/tz.rb +2 -2
  44. data/lib/sparql/algebra/operator/using.rb +2 -2
  45. data/lib/sparql/algebra/operator/year.rb +2 -2
  46. data/lib/sparql/algebra/operator.rb +27 -10
  47. data/lib/sparql/algebra/query.rb +5 -3
  48. data/lib/sparql/algebra.rb +22 -3
  49. data/lib/sparql/grammar/meta.rb +1367 -267
  50. data/lib/sparql/grammar/parser11.rb +826 -328
  51. data/lib/sparql/grammar/terminals11.rb +2 -2
  52. data/lib/sparql/grammar.rb +6 -4
  53. data/lib/sparql/results.rb +3 -2
  54. data/lib/sparql/server.rb +93 -0
  55. data/lib/sparql.rb +8 -5
  56. metadata +39 -17
@@ -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,8 +194,11 @@ 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
203
  query = data[:query].first if data[:query]
201
204
 
@@ -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,30 @@ module SPARQL::Grammar
703
916
  end
704
917
  end
705
918
 
706
- # [60] Bind ::= 'BIND' '(' Expression 'AS' Var ')'
919
+ # [60] Bind ::= 'BIND' '(' Expression 'AS' Var ')'
920
+ #
921
+ # Input from `data` is TODO.
922
+ # Output to prod_data is TODO.
707
923
  production(:Bind) do |input, data, callback|
708
924
  add_prod_datum :extend, [data[:Expression].unshift(data[:Var].first)]
709
925
  end
710
926
 
711
- # [61] InlineData ::= 'VALUES' DataBlock
927
+ # [61] InlineData ::= 'VALUES' DataBlock
928
+ #
929
+ # Input from `data` is TODO.
930
+ # Output to prod_data is TODO.
712
931
  production(:InlineData) do |input, data, callback|
713
932
  debug("InlineData") {"vars: #{data[:Var].inspect}, row: #{data[:row].inspect}"}
714
933
  add_prod_datum :query, SPARQL::Algebra::Expression.for(:table,
715
- data[:Var].unshift(:vars),
934
+ Array(data[:Var]).unshift(:vars),
716
935
  *data[:row]
717
936
  )
718
937
  end
719
938
 
720
- # [63] InlineDataOneVar ::= Var '{' DataBlockValue* '}'
939
+ # [63] InlineDataOneVar ::= Var '{' DataBlockValue* '}'
940
+ #
941
+ # Input from `data` is TODO.
942
+ # Output to prod_data is TODO.
721
943
  production(:InlineDataOneVar) do |input, data, callback|
722
944
  add_prod_datum :Var, data[:Var]
723
945
 
@@ -726,8 +948,11 @@ module SPARQL::Grammar
726
948
  end
727
949
  end
728
950
 
729
- # [64] InlineDataFull ::= ( NIL | '(' Var* ')' )
730
- # '{' ( '(' DataBlockValue* ')' | NIL )* '}'
951
+ # [64] InlineDataFull ::= ( NIL | '(' Var* ')' )
952
+ # '{' ( '(' DataBlockValue* ')' | NIL )* '}'
953
+ #
954
+ # Input from `data` is TODO.
955
+ # Output to prod_data is TODO.
731
956
  production(:InlineDataFull) do |input, data, callback|
732
957
  vars = data[:Var]
733
958
  add_prod_datum :Var, vars
@@ -745,7 +970,10 @@ module SPARQL::Grammar
745
970
  end
746
971
  end
747
972
 
748
- # _InlineDataFull_6 ::= '(' '(' DataBlockValue* ')' | NIL ')'
973
+ # _InlineDataFull_6 ::= '(' '(' DataBlockValue* ')' | NIL ')'
974
+ #
975
+ # Input from `data` is TODO.
976
+ # Output to prod_data is TODO.
749
977
  production(:_InlineDataFull_6) do |input, data, callback|
750
978
  if data[:DataBlockValue]
751
979
  add_prod_data :rowdata, data[:DataBlockValue].map {|v| v unless v == :undef}
@@ -754,19 +982,28 @@ module SPARQL::Grammar
754
982
  end
755
983
  end
756
984
 
757
- # [65] DataBlockValue ::= QuotedTriple | iri | RDFLiteral | NumericLiteral | BooleanLiteral | 'UNDEF'
985
+ # [65] DataBlockValue ::= QuotedTriple | iri | RDFLiteral | NumericLiteral | BooleanLiteral | 'UNDEF'
986
+ #
987
+ # Input from `data` is TODO.
988
+ # Output to prod_data is TODO.
758
989
  production(:DataBlockValue) do |input, data, callback|
759
990
  add_prod_datum :DataBlockValue, data.values.first
760
991
  end
761
992
 
762
- # [66] MinusGraphPattern ::= 'MINUS' GroupGraphPattern
993
+ # [66] MinusGraphPattern ::= 'MINUS' GroupGraphPattern
994
+ #
995
+ # Input from `data` is TODO.
996
+ # Output to prod_data is TODO.
763
997
  production(:MinusGraphPattern) do |input, data, callback|
764
998
  query = data[:query] ? data[:query].first : SPARQL::Algebra::Operator::BGP.new
765
999
  add_prod_data(:minus, query)
766
1000
  end
767
1001
 
768
- # [67] GroupOrUnionGraphPattern ::= GroupGraphPattern
1002
+ # [67] GroupOrUnionGraphPattern ::= GroupGraphPattern
769
1003
  # ( 'UNION' GroupGraphPattern )*
1004
+ #
1005
+ # Input from `data` is TODO.
1006
+ # Output to prod_data is TODO.
770
1007
  production(:GroupOrUnionGraphPattern) do |input, data, callback|
771
1008
  res = Array(data[:query]).first
772
1009
  if data[:union]
@@ -782,17 +1019,26 @@ module SPARQL::Grammar
782
1019
  end
783
1020
 
784
1021
  # ( 'UNION' GroupGraphPattern )*
1022
+ #
1023
+ # Input from `data` is TODO.
1024
+ # Output to prod_data is TODO.
785
1025
  production(:_GroupOrUnionGraphPattern_1) do |input, data, callback|
786
1026
  input[:union] = Array(data[:union]).unshift(data[:query].first)
787
1027
  end
788
1028
 
789
- # [68] Filter ::= 'FILTER' Constraint
1029
+ # [68] Filter ::= 'FILTER' Constraint
1030
+ #
1031
+ # Input from `data` is TODO.
1032
+ # Output to prod_data is TODO.
790
1033
  production(:Filter) do |input, data, callback|
791
1034
  add_prod_datum(:filter, data[:Constraint])
792
1035
  end
793
1036
 
794
- # [69] Constraint ::= BrackettedExpression | BuiltInCall
1037
+ # [69] Constraint ::= BrackettedExpression | BuiltInCall
795
1038
  # | FunctionCall
1039
+ #
1040
+ # Input from `data` is TODO.
1041
+ # Output to prod_data is TODO.
796
1042
  production(:Constraint) do |input, data, callback|
797
1043
  if data[:Expression]
798
1044
  # Resolve expression to the point it is either an atom or an s-exp
@@ -804,28 +1050,41 @@ module SPARQL::Grammar
804
1050
  end
805
1051
  end
806
1052
 
807
- # [70] FunctionCall ::= iri ArgList
1053
+ # [70] FunctionCall ::= iri ArgList
1054
+ #
1055
+ # Input from `data` is TODO.
1056
+ # Output to prod_data is TODO.
808
1057
  production(:FunctionCall) do |input, data, callback|
809
1058
  add_prod_data(:Function, SPARQL::Algebra::Operator::FunctionCall.new(data[:iri], *data[:ArgList]))
810
1059
  end
811
1060
 
812
- # [71] ArgList ::= NIL
1061
+ # [71] ArgList ::= NIL
813
1062
  # | '(' 'DISTINCT'? Expression ( ',' Expression )* ')'
1063
+ #
1064
+ # Input from `data` is TODO.
1065
+ # Output to prod_data is TODO.
814
1066
  production(:ArgList) do |input, data, callback|
815
1067
  data.values.each {|v| add_prod_datum(:ArgList, v)}
816
1068
  end
817
1069
 
818
- # [72] ExpressionList ::= NIL
1070
+ # [72] ExpressionList ::= NIL
819
1071
  # | '(' Expression ( ',' Expression )* ')'
1072
+ #
1073
+ # Input from `data` is TODO.
1074
+ # Output to prod_data is TODO.
820
1075
  production(:ExpressionList) do |input, data, callback|
821
1076
  data.values.each {|v| add_prod_datum(:ExpressionList, v)}
822
1077
  end
823
1078
 
824
- # [73] ConstructTemplate ::= '{' ConstructTriples? '}'
1079
+ # [73] ConstructTemplate ::= '{' ConstructTriples? '}'
825
1080
  start_production(:ConstructTemplate) do |input, data, callback|
826
1081
  # Generate BNodes instead of non-distinguished variables
827
1082
  self.gen_bnodes
828
1083
  end
1084
+
1085
+ #
1086
+ # Input from `data` is TODO.
1087
+ # Output to prod_data is TODO.
829
1088
  production(:ConstructTemplate) do |input, data, callback|
830
1089
  # Generate BNodes instead of non-distinguished variables
831
1090
  self.gen_bnodes(false)
@@ -833,13 +1092,13 @@ module SPARQL::Grammar
833
1092
  add_prod_datum(:ConstructTemplate, data[:ConstructTemplate])
834
1093
  end
835
1094
 
836
- # [75] TriplesSameSubject ::= VarOrTermOrQuotedTP PropertyListNotEmpty
837
- # | TriplesNode PropertyList
1095
+ # [75] TriplesSameSubject ::= VarOrTermOrQuotedTP PropertyListNotEmpty
1096
+ # | TriplesNode PropertyList
838
1097
  production(:TriplesSameSubject) do |input, data, callback|
839
1098
  add_prod_datum(:pattern, data[:pattern])
840
1099
  end
841
1100
 
842
- # [77] PropertyListNotEmpty ::= Verb ObjectList
1101
+ # [77] PropertyListNotEmpty ::= Verb ObjectList
843
1102
  # ( ';' ( Verb ObjectList )? )*
844
1103
  start_production(:PropertyListNotEmpty) do |input, data, callback|
845
1104
  subject = input[:VarOrTermOrQuotedTP] || input[:TriplesNode] || input[:GraphNode]
@@ -850,47 +1109,58 @@ module SPARQL::Grammar
850
1109
  add_prod_datum(:pattern, data[:pattern])
851
1110
  end
852
1111
 
853
- # [78] Verb ::= VarOrIri | 'a'
1112
+ # [78] Verb ::= VarOrIri | 'a'
1113
+ #
1114
+ # Output to input is `:Verb`.
854
1115
  production(:Verb) do |input, data, callback|
855
1116
  input[:Verb] = data.values.first
856
1117
  end
857
1118
 
858
- # [79] ObjectList ::= Object ( ',' Object )*
1119
+ # [79] ObjectList ::= Object ( ',' Object )*
1120
+ #
1121
+ # Adds `:Subject`, `:Verb`, and `:VerbPath` from input to data with error checking.
859
1122
  start_production(:ObjectList) do |input, data, callback|
860
1123
  # 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]
1124
+ data[:Subject] = input[:Subject]
1125
+ error(nil, "Expected Subject", production: :ObjectList) if !input[:Subject] && validate?
1126
+ error(nil, "Expected Verb", production: :ObjectList) if !(input[:Verb] || input[:VerbPath]) && validate?
1127
+ data[:Verb] = input[:Verb] if input[:Verb]
1128
+ data[:VerbPath] = input[:VerbPath] if input[:VerbPath]
866
1129
  end
867
1130
  production(:ObjectList) do |input, data, callback|
868
1131
  add_prod_datum(:pattern, data[:pattern])
869
- add_prod_datum(:path, data[:path])
870
1132
  end
871
1133
 
872
- # [80] Object ::= GraphNode AnnotationPattern?
1134
+ # [80] Object ::= GraphNode AnnotationPattern?
1135
+ #
1136
+ # Sets `:Subject` and `:Verb` in data from input.
873
1137
  start_production(:Object) do |input, data, callback|
874
1138
  data[:Subject] = Array(input[:Subject]).first
875
1139
  data[:Verb] = Array(input[:Verb]).first
876
1140
  end
1141
+
1142
+ #
1143
+ # Input from `data` is `:Subject`, `:Verb` or `:VerbPath`, and `GraphNode`.
1144
+ # Output to prod_data is `:pattern`, either from `:Subject`, `:Verb`, and `GraphNode` or a new path if `VerbPath` is present instead of `Verb`.
877
1145
  production(:Object) do |input, data, callback|
878
1146
  object = data[:GraphNode]
879
1147
  add_prod_datum(:pattern, data[:pattern])
880
1148
  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,
1149
+ if input[:Verb]
1150
+ add_pattern(:Object, subject: input[:Subject], predicate: input[:Verb], object: object)
1151
+ elsif input[:VerbPath]
1152
+ add_prod_datum(:pattern,
885
1153
  SPARQL::Algebra::Expression(:path,
886
- prod_data[:Subject].first,
887
- prod_data[:VerbPath],
1154
+ input[:Subject].first,
1155
+ input[:VerbPath],
888
1156
  object.first))
889
1157
  end
890
1158
  end
891
1159
  end
1160
+
1161
+ # AnnotationPattern?
892
1162
  start_production(:_Object_1) do |input, data, callback|
893
- pattern = RDF::Query::Pattern.new(input[:Subject], input[:Verb], input[:GraphNode].first)
1163
+ pattern = RDF::Query::Pattern.new(input[:Subject], input[:Verb], input[:GraphNode].first, quoted: true)
894
1164
  error("ObjectPath", "Expected Verb",
895
1165
  production: :_Object_1) unless input[:Verb]
896
1166
  data[:TriplesNode] = [pattern]
@@ -899,13 +1169,17 @@ module SPARQL::Grammar
899
1169
  add_prod_datum(:pattern, data[:pattern])
900
1170
  end
901
1171
 
902
- # [81] TriplesSameSubjectPath ::= VarOrTermOrQuotedTP PropertyListPathNotEmpty | TriplesNode PropertyListPath
1172
+ # [81] TriplesSameSubjectPath ::= VarOrTermOrQuotedTP PropertyListPathNotEmpty | TriplesNode PropertyListPath
903
1173
  production(:TriplesSameSubjectPath) do |input, data, callback|
904
1174
  add_prod_datum(:pattern, data[:pattern])
905
- add_prod_datum(:path, data[:path])
906
1175
  end
907
1176
 
908
- # [83] PropertyListPathNotEmpty ::= ( VerbPath | VerbSimple ) ObjectList ( ';' ( ( VerbPath | VerbSimple ) ObjectList )? )*
1177
+ # [83] PropertyListPathNotEmpty ::= ( VerbPath | VerbSimple ) ObjectList
1178
+ # ( ';' ( ( VerbPath | VerbSimple )
1179
+ # ObjectList )? )*
1180
+ #
1181
+ # Sets `:Subject` in data from either `:VarOrTermOrQuotedTP`,
1182
+ # `:TriplesNode`, or `:GraphNode` in input with error checking.
909
1183
  start_production(:PropertyListPathNotEmpty) do |input, data, callback|
910
1184
  subject = input[:VarOrTermOrQuotedTP] || input[:TriplesNode] || input[:GraphNode]
911
1185
  error(nil, "Expected VarOrTermOrQuotedTP, got nothing", production: :PropertyListPathNotEmpty) if validate? && !subject
@@ -913,10 +1187,13 @@ module SPARQL::Grammar
913
1187
  end
914
1188
  production(:PropertyListPathNotEmpty) do |input, data, callback|
915
1189
  add_prod_datum(:pattern, data[:pattern])
916
- add_prod_datum(:path, data[:path])
917
1190
  end
918
1191
 
919
- # [84] VerbPath ::= Path
1192
+ # [84] VerbPath ::= Path
1193
+ #
1194
+ # Input from `data` is `:Path` or `:iri`.
1195
+ # Output to prod_data is either `:VerbPath` or `:Verb`.
1196
+ # If `:VerbPath` is added, then any existing `:Verb` is removed.
920
1197
  production(:VerbPath) do |input, data, callback|
921
1198
  if data[:Path]
922
1199
  input.delete(:Verb)
@@ -926,70 +1203,80 @@ module SPARQL::Grammar
926
1203
  end
927
1204
  end
928
1205
 
929
- # [85] VerbSimple ::= Var
1206
+ # [85] VerbSimple ::= Var
930
1207
  production(:VerbSimple) do |input, data, callback|
931
1208
  input[:Verb] = data.values.flatten.first
932
1209
  end
933
1210
 
934
- # [86] ObjectListPath ::= ObjectPath ("," ObjectPath)*
1211
+ # [86] ObjectListPath ::= ObjectPath ("," ObjectPath)*
1212
+ #
1213
+ # Addes `:Subject` from input to data with error checking.
1214
+ # Also adds either `:Verb` or `:VerbPath`
935
1215
  start_production(:ObjectListPath) do |input, data, callback|
936
1216
  # 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
1217
+ data[:Subject] = input[:Subject]
1218
+ error(nil, "Expected Subject", production: :ObjectListPath) if !input[:Subject] && validate?
1219
+ error(nil, "Expected Verb", production: :ObjectListPath) if !(input[:Verb] || input[:VerbPath]) && validate?
1220
+ if input[:Verb]
1221
+ data[:Verb] = Array(input[:Verb]).last
942
1222
  else
943
- data[:VerbPath] = prod_data[:VerbPath]
1223
+ data[:VerbPath] = input[:VerbPath]
944
1224
  end
945
1225
  end
1226
+
1227
+ #
1228
+ # Input from `data` is TODO.
1229
+ # Output to prod_data is TODO.
946
1230
  production(:ObjectListPath) do |input, data, callback|
947
1231
  add_prod_datum(:pattern, data[:pattern])
948
- add_prod_datum(:path, data[:path])
949
1232
  end
950
1233
 
951
- # [87] ObjectPath ::= GraphNodePath AnnotationPatternPath?
1234
+ # [87] ObjectPath ::= GraphNodePath AnnotationPatternPath?
1235
+ #
1236
+ # Adds `:Subject` and `:Verb` to data from input.
952
1237
  start_production(:ObjectPath) do |input, data, callback|
953
1238
  data[:Subject] = Array(input[:Subject]).first
954
1239
  data[:Verb] = Array(input[:Verb]).first
955
1240
  end
1241
+
1242
+ # Input from `data` `:Subject`, either `:Verb` or `:VerbPath`, `:GraphNode` from GraphNodePath is used as the object, and `:pattern`.
1243
+ # 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
1244
  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
1245
+ subject = data[:Subject]
1246
+ verb = data[:Verb]
1247
+ object = Array(data[:GraphNode]).first
1248
+ if verb
1249
+ add_prod_datum(:pattern, RDF::Query::Pattern.new(subject, verb, object))
1250
+ else
1251
+ add_prod_datum(:pattern, SPARQL::Algebra::Expression(:path,
1252
+ subject,
1253
+ input[:VerbPath],
1254
+ object))
979
1255
  end
1256
+ add_prod_datum(:pattern, data[:pattern])
980
1257
  end
1258
+
1259
+ # AnnotationPatternPath?
1260
+ #
1261
+ # Create `:TriplesNode` in data used as the subject of annotations
981
1262
  start_production(:_ObjectPath_1) do |input, data, callback|
982
- pattern = RDF::Query::Pattern.new(input[:Subject], input[:Verb], input[:GraphNode].first)
983
1263
  error("ObjectPath", "Expected Verb",
984
1264
  production: :_ObjectPath_1) unless input[:Verb]
1265
+ pattern = RDF::Query::Pattern.new(input[:Subject], input[:Verb], input[:GraphNode].first, quoted: true)
985
1266
  data[:TriplesNode] = [pattern]
986
1267
  end
1268
+
1269
+ #
1270
+ # Input from `data` is `:pattern`.
1271
+ # Output to prod_data is `:pattern`.
987
1272
  production(:_ObjectPath_1) do |input, data, callback|
988
1273
  add_prod_datum(:pattern, data[:pattern])
989
1274
  end
990
1275
 
991
- # [88] Path ::= PathAlternative
992
- # output is a :Path or :iri
1276
+ # [88] Path ::= PathAlternative
1277
+ #
1278
+ # Input from data is `:Path`
1279
+ # Output to input is either `:iri` or `:Path`, depending on if `:Path` is an IRI or not.
993
1280
  production(:Path) do |input, data, callback|
994
1281
  if data[:Path].is_a?(RDF::URI)
995
1282
  input[:iri] = data[:Path]
@@ -998,7 +1285,10 @@ module SPARQL::Grammar
998
1285
  end
999
1286
  end
1000
1287
 
1001
- # [89] PathAlternative ::= PathSequence ( '|' PathSequence )*
1288
+ # [89] PathAlternative ::= PathSequence ( '|' PathSequence )*
1289
+ #
1290
+ # Input from `data` is `:PathSequence` containing one or more path objects.
1291
+ # 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
1292
  production(:PathAlternative) do |input, data, callback|
1003
1293
  lhs = Array(data[:PathSequence]).shift
1004
1294
  while data[:PathSequence] && !data[:PathSequence].empty?
@@ -1009,11 +1299,17 @@ module SPARQL::Grammar
1009
1299
  end
1010
1300
 
1011
1301
  # ( '|' PathSequence )*
1302
+ #
1303
+ # Input from `data` is `:PathSequence`.
1304
+ # Output to prod_data is `:PathSequence` which is accumulated.
1012
1305
  production(:_PathAlternative_1) do |input, data, callback|
1013
1306
  input[:PathSequence] += data[:PathSequence]
1014
1307
  end
1015
1308
 
1016
- # [90] PathSequence ::= PathEltOrInverse ( '/' PathEltOrInverse )*
1309
+ # [90] PathSequence ::= PathEltOrInverse ( '/' PathEltOrInverse )*
1310
+ #
1311
+ # Input from `data` is `:PathSequence` containing one or more path objects.
1312
+ # 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
1313
  production(:PathSequence) do |input, data, callback|
1018
1314
  lhs = data[:PathEltOrInverse].shift
1019
1315
  while data[:PathEltOrInverse] && !data[:PathEltOrInverse].empty?
@@ -1024,22 +1320,39 @@ module SPARQL::Grammar
1024
1320
  end
1025
1321
 
1026
1322
  # ( '/' PathEltOrInverse )*
1323
+ #
1324
+ # Input from `data` is `:PathSequence`.
1325
+ # Output to prod_data is `:PathSequence` which is accumulated.
1027
1326
  production(:_PathSequence_1) do |input, data, callback|
1028
1327
  input[:PathEltOrInverse] += data[:PathEltOrInverse]
1029
1328
  end
1030
1329
 
1031
- # [91] PathElt ::= PathPrimary PathMod?
1330
+ # [91] PathElt ::= PathPrimary PathMod?
1331
+ #
1332
+ # Input from `data` is `:PathMod` and `:PathPrimary`.
1333
+ # Output to prod_data is `:Path` a possibly modified `:PathPrimary`.
1032
1334
  production(:PathElt) do |input, data, callback|
1033
1335
  path_mod = data.delete(:PathMod) if data.has_key?(:PathMod)
1034
1336
  path_mod ||= data.delete(:MultiplicativeExpression) if data.has_key?(:MultiplicativeExpression)
1035
1337
  path_mod = path_mod.first if path_mod
1036
1338
 
1037
- res = data[:PathPrimary]
1038
- res = SPARQL::Algebra::Expression("path#{path_mod}", res) if path_mod
1339
+ res = case path_mod
1340
+ when SPARQL::Algebra::Expression
1341
+ # Path range :p{m,n}
1342
+ path_mod.operands[2] = data[:PathPrimary]
1343
+ path_mod
1344
+ when nil
1345
+ data[:PathPrimary]
1346
+ else
1347
+ SPARQL::Algebra::Expression("path#{path_mod}", data[:PathPrimary])
1348
+ end
1039
1349
  input[:Path] = res
1040
1350
  end
1041
1351
 
1042
- # [92] PathEltOrInverse ::= PathElt | '^' PathElt
1352
+ # [92] PathEltOrInverse ::= PathElt | '^' PathElt
1353
+ #
1354
+ # Input from `data` is `:reverse` and `:Path`.
1355
+ # Output to prod_data is `:Path` a possibly reversed `:Path`.
1043
1356
  production(:PathEltOrInverse) do |input, data, callback|
1044
1357
  res = if data[:reverse]
1045
1358
  SPARQL::Algebra::Expression(:reverse, data[:Path])
@@ -1049,7 +1362,44 @@ module SPARQL::Grammar
1049
1362
  input[:PathEltOrInverse] = [res]
1050
1363
  end
1051
1364
 
1052
- # [94] PathPrimary ::= iri | 'a' | '!' PathNegatedPropertySet | '(' Path ')'
1365
+ # [93] PathMod ::= '*' | '?' | '+' | '{' INTEGER? (',' INTEGER?)? '}'
1366
+ # '{' INTEGER? (',' INTEGER?)? '}'
1367
+ start_production(:_PathMod_1) do |input, data, callback|
1368
+ data[:pathRange] = [nil]
1369
+ end
1370
+ production(:_PathMod_1) do |input, data, callback|
1371
+ raise Error, "expect property range to have integral elements" if data[:pathRange].all?(&:nil?)
1372
+ min, max = data[:pathRange]
1373
+ min ||= 0
1374
+ max = min if data[:pathRange].length == 1
1375
+ max ||= :*
1376
+
1377
+ # Last operand added in :PathElt
1378
+ add_prod_data(:PathMod, SPARQL::Algebra::Expression(:pathRange, min, max, RDF.nil))
1379
+ end
1380
+
1381
+ # INTEGER?
1382
+ production(:_PathMod_2) do |input, data, callback|
1383
+ input[:pathRange][0] = data[:literal].object
1384
+ end
1385
+
1386
+ # (',' INTEGER?)
1387
+ start_production(:_PathMod_4) do |input, data, callback|
1388
+ data[:pathRange] = [nil, nil]
1389
+ end
1390
+ production(:_PathMod_4) do |input, data, callback|
1391
+ input[:pathRange][1] ||= data.fetch(:pathRange, [0, nil])[1]
1392
+ end
1393
+
1394
+ # INTEGER?
1395
+ production(:_PathMod_5) do |input, data, callback|
1396
+ input[:pathRange][1] = data[:literal].object
1397
+ end
1398
+
1399
+ # [94] PathPrimary ::= iri | 'a' | '!' PathNegatedPropertySet | '(' Path ')'
1400
+ #
1401
+ # Input from `data` is one of `:Verb`, `:iri`, `:PathNegatedPropertySet`, or `:Path`.
1402
+ # Output to prod_data is `:PathPrimary`.
1053
1403
  production(:PathPrimary) do |input, data, callback|
1054
1404
  input[:PathPrimary] = case
1055
1405
  when data[:Verb] then data[:Verb]
@@ -1059,90 +1409,128 @@ module SPARQL::Grammar
1059
1409
  end
1060
1410
  end
1061
1411
 
1062
- # [95] PathNegatedPropertySet ::= PathOneInPropertySet | '(' ( PathOneInPropertySet ( '|' PathOneInPropertySet )* )? ')'
1412
+ # [95] PathNegatedPropertySet ::= PathOneInPropertySet | '(' ( PathOneInPropertySet ( '|' PathOneInPropertySet )* )? ')'
1413
+ #
1414
+ # Input from `data` is TODO.
1415
+ # Output to prod_data is TODO.
1063
1416
  production(:PathNegatedPropertySet) do |input, data, callback|
1064
1417
  input[:Path] = SPARQL::Algebra::Expression(:notoneof, *Array(data[:Path]))
1065
1418
  end
1066
1419
 
1067
1420
  # ( '|' PathOneInPropertySet )* )?
1421
+ #
1422
+ # Input from `data` is TODO.
1423
+ # Output to prod_data is TODO.
1068
1424
  production(:_PathNegatedPropertySet_4) do |input, data, callback|
1069
1425
  add_prod_datum(:Path, data[:Path])
1070
1426
  end
1071
1427
 
1072
- # [96] PathOneInPropertySet ::= iri | 'a' | '^' ( iri | 'a' )
1428
+ # [96] PathOneInPropertySet ::= iri | 'a' | '^' ( iri | 'a' )
1429
+ #
1430
+ # Input from `data` is TODO.
1431
+ # Output to prod_data is TODO.
1073
1432
  production(:PathOneInPropertySet) do |input, data, callback|
1074
1433
  term = (Array(data[:iri]) || data[:Verb]).first
1075
1434
  term = SPARQL::Algebra::Expression(:reverse, term) if data[:reverse]
1076
1435
  input[:Path] = [term]
1077
1436
  end
1078
1437
 
1079
- # [98] TriplesNode ::= Collection | BlankNodePropertyList
1438
+ # [98] TriplesNode ::= Collection | BlankNodePropertyList
1080
1439
  start_production(:TriplesNode) do |input, data, callback|
1081
1440
  # Called after Verb. The prod_data stack should have Subject and Verb elements
1082
1441
  data[:TriplesNode] = bnode
1083
1442
  end
1443
+
1444
+ #
1445
+ # Input from `data` is TODO.
1446
+ # Output to prod_data is TODO.
1084
1447
  production(:TriplesNode) do |input, data, callback|
1085
1448
  add_prod_datum(:pattern, data[:pattern])
1086
1449
  add_prod_datum(:TriplesNode, data[:TriplesNode])
1087
1450
  end
1088
1451
 
1089
- # [100] TriplesNodePath ::= CollectionPath | BlankNodePropertyListPath
1452
+ # [100] TriplesNodePath ::= CollectionPath | BlankNodePropertyListPath
1090
1453
  start_production(:TriplesNodePath) do |input, data, callback|
1091
1454
  # Called after Verb. The prod_data stack should have Subject and Verb elements
1092
1455
  data[:TriplesNode] = bnode
1093
1456
  end
1457
+
1458
+ #
1459
+ # Input from `data` is TODO.
1460
+ # Output to prod_data is TODO.
1094
1461
  production(:TriplesNodePath) do |input, data, callback|
1095
1462
  add_prod_datum(:pattern, data[:pattern])
1096
- add_prod_datum(:path, data[:path])
1097
1463
  add_prod_datum(:TriplesNode, data[:TriplesNode])
1098
1464
  end
1099
1465
 
1100
- # [102] Collection ::= '(' GraphNode+ ')'
1466
+ # [102] Collection ::= '(' GraphNode+ ')'
1101
1467
  start_production(:Collection) do |input, data, callback|
1102
1468
  # Tells the TriplesNode production to collect and not generate statements
1103
- data[:Collection] = prod_data[:TriplesNode]
1469
+ data[:Collection] = input[:TriplesNode]
1104
1470
  end
1471
+
1472
+ #
1473
+ # Input from `data` is TODO.
1474
+ # Output to prod_data is TODO.
1105
1475
  production(:Collection) do |input, data, callback|
1106
1476
  expand_collection(data)
1107
1477
  end
1108
1478
 
1109
- # [103] CollectionPath ::= "(" GraphNodePath+ ")"
1479
+ # [103] CollectionPath ::= "(" GraphNodePath+ ")"
1110
1480
  start_production(:CollectionPath) do |input, data, callback|
1111
1481
  # Tells the TriplesNode production to collect and not generate statements
1112
- data[:Collection] = prod_data[:TriplesNode]
1482
+ data[:Collection] = input[:TriplesNode]
1113
1483
  end
1484
+
1485
+ #
1486
+ # Input from `data` is TODO.
1487
+ # Output to prod_data is TODO.
1114
1488
  production(:CollectionPath) do |input, data, callback|
1115
1489
  expand_collection(data)
1116
- add_prod_datum(:path, data[:path])
1117
1490
  end
1118
1491
 
1119
- # [104] GraphNode ::= VarOrTermOrQuotedTP | TriplesNode
1492
+ # [104] GraphNode ::= VarOrTermOrQuotedTP | TriplesNode
1493
+ #
1494
+ # Input from `data` is TODO.
1495
+ # Output to prod_data is TODO.
1120
1496
  production(:GraphNode) do |input, data, callback|
1121
1497
  term = data[:VarOrTermOrQuotedTP] || data[:TriplesNode]
1122
1498
  add_prod_datum(:pattern, data[:pattern])
1123
1499
  add_prod_datum(:GraphNode, term)
1124
1500
  end
1125
1501
 
1126
- # [105] GraphNodePath ::= VarOrTermOrQuotedTP | TriplesNodePath
1502
+ # [105] GraphNodePath ::= VarOrTermOrQuotedTP | TriplesNodePath
1503
+ #
1504
+ # Input from `data` is either `:VarOrTermOrQUotedTP` or `:TriplesNode`.
1505
+ # Additionally, `:pattern`. Also, `:pattern` and `:path`.
1506
+ # Output to prod_data is `:GraphNode`, along with any `:path` and `:pattern`.
1127
1507
  production(:GraphNodePath) do |input, data, callback|
1128
1508
  term = data[:VarOrTermOrQuotedTP] || data[:TriplesNode]
1129
1509
  add_prod_datum(:pattern, data[:pattern])
1130
- add_prod_datum(:path, data[:path])
1131
1510
  add_prod_datum(:GraphNode, term)
1132
1511
  end
1133
1512
 
1134
- # [106s] VarOrTermOrQuotedTP ::= Var | GraphTerm | EmbTP
1513
+ # [106s] VarOrTermOrQuotedTP ::= Var | GraphTerm | QuotedTP
1514
+ #
1515
+ # Input from `data` is TODO.
1516
+ # Output to prod_data is TODO.
1135
1517
  production(:VarOrTermOrQuotedTP) do |input, data, callback|
1136
1518
  data.values.each {|v| add_prod_datum(:VarOrTermOrQuotedTP, v)}
1137
1519
  end
1138
1520
 
1139
- # [107] VarOrIri ::= Var | iri
1521
+ # [107] VarOrIri ::= Var | iri
1522
+ #
1523
+ # Input from `data` is TODO.
1524
+ # Output to prod_data is TODO.
1140
1525
  production(:VarOrIri) do |input, data, callback|
1141
1526
  data.values.each {|v| add_prod_datum(:VarOrIri, v)}
1142
1527
  end
1143
1528
 
1144
- # [109] GraphTerm ::= iri | RDFLiteral | NumericLiteral
1145
- # | BooleanLiteral | BlankNode | NIL
1529
+ # [109] GraphTerm ::= iri | RDFLiteral | NumericLiteral
1530
+ # | BooleanLiteral | BlankNode | NIL
1531
+ #
1532
+ # Input from `data` is one of `:iri`, `:literal`, `:BlankNode`, or `:NIL`.
1533
+ # Output to prod_data is `:GraphTerm` created from the data.
1146
1534
  production(:GraphTerm) do |input, data, callback|
1147
1535
  add_prod_datum(:GraphTerm,
1148
1536
  data[:iri] ||
@@ -1151,42 +1539,60 @@ module SPARQL::Grammar
1151
1539
  data[:NIL])
1152
1540
  end
1153
1541
 
1154
- # [110] Expression ::= ConditionalOrExpression
1542
+ # [110] Expression ::= ConditionalOrExpression
1543
+ #
1544
+ # Input from `data` is TODO.
1545
+ # Output to prod_data is TODO.
1155
1546
  production(:Expression) do |input, data, callback|
1156
1547
  add_prod_datum(:Expression, data[:Expression])
1157
1548
  end
1158
1549
 
1159
- # [111] ConditionalOrExpression ::= ConditionalAndExpression
1160
- # ( '||' ConditionalAndExpression )*
1550
+ # [111] ConditionalOrExpression ::= ConditionalAndExpression
1551
+ # ( '||' ConditionalAndExpression )*
1552
+ #
1553
+ # Input from `data` is TODO.
1554
+ # Output to prod_data is TODO.
1161
1555
  production(:ConditionalOrExpression) do |input, data, callback|
1162
1556
  add_operator_expressions(:_OR, data)
1163
1557
  end
1164
1558
 
1165
1559
  # ( '||' ConditionalAndExpression )*
1560
+ #
1561
+ # Input from `data` is TODO.
1562
+ # Output to prod_data is TODO.
1166
1563
  production(:_ConditionalOrExpression_1) do |input, data, callback|
1167
1564
  accumulate_operator_expressions(:ConditionalOrExpression, :_OR, data)
1168
1565
  end
1169
1566
 
1170
- # [112] ConditionalAndExpression ::= ValueLogical ( '&&' ValueLogical )*
1567
+ # [112] ConditionalAndExpression ::= ValueLogical ( '&&' ValueLogical )*
1568
+ #
1569
+ # Input from `data` is TODO.
1570
+ # Output to prod_data is TODO.
1171
1571
  production(:ConditionalAndExpression) do |input, data, callback|
1172
1572
  add_operator_expressions(:_AND, data)
1173
1573
  end
1174
1574
 
1175
1575
  # ( '||' ConditionalAndExpression )*
1576
+ #
1577
+ # Input from `data` is TODO.
1578
+ # Output to prod_data is TODO.
1176
1579
  production(:_ConditionalAndExpression_1) do |input, data, callback|
1177
1580
  accumulate_operator_expressions(:ConditionalAndExpression, :_AND, data)
1178
1581
  end
1179
1582
 
1180
- # [114] RelationalExpression ::= NumericExpression
1181
- # ( '=' NumericExpression
1182
- # | '!=' NumericExpression
1183
- # | '<' NumericExpression
1184
- # | '>' NumericExpression
1185
- # | '<=' NumericExpression
1186
- # | '>=' NumericExpression
1187
- # | 'IN' ExpressionList
1188
- # | 'NOT' 'IN' ExpressionList
1189
- # )?
1583
+ # [114] RelationalExpression ::= NumericExpression
1584
+ # ( '=' NumericExpression
1585
+ # | '!=' NumericExpression
1586
+ # | '<' NumericExpression
1587
+ # | '>' NumericExpression
1588
+ # | '<=' NumericExpression
1589
+ # | '>=' NumericExpression
1590
+ # | 'IN' ExpressionList
1591
+ # | 'NOT' 'IN' ExpressionList
1592
+ # )?
1593
+ #
1594
+ # Input from `data` is TODO.
1595
+ # Output to prod_data is TODO.
1190
1596
  production(:RelationalExpression) do |input, data, callback|
1191
1597
  if data[:_Compare_Numeric]
1192
1598
  add_prod_datum(:Expression, SPARQL::Algebra::Expression.for(data[:_Compare_Numeric].insert(1, *data[:Expression])))
@@ -1203,6 +1609,9 @@ module SPARQL::Grammar
1203
1609
  end
1204
1610
 
1205
1611
  # ( '=' NumericExpression | '!=' NumericExpression | ... )?
1612
+ #
1613
+ # Input from `data` is TODO.
1614
+ # Output to prod_data is TODO.
1206
1615
  production(:_RelationalExpression_1) do |input, data, callback|
1207
1616
  if data[:RelationalExpression]
1208
1617
  add_prod_datum(:_Compare_Numeric, data[:RelationalExpression] + data[:Expression])
@@ -1214,11 +1623,17 @@ module SPARQL::Grammar
1214
1623
  end
1215
1624
 
1216
1625
  # 'IN' ExpressionList
1626
+ #
1627
+ # Input from `data` is TODO.
1628
+ # Output to prod_data is TODO.
1217
1629
  production(:_RelationalExpression_9) do |input, data, callback|
1218
1630
  add_prod_datum(:in, data[:ExpressionList])
1219
1631
  end
1220
1632
 
1221
1633
  # 'NOT' 'IN' ExpressionList
1634
+ #
1635
+ # Input from `data` is TODO.
1636
+ # Output to prod_data is TODO.
1222
1637
  production(:_RelationalExpression_10) do |input, data, callback|
1223
1638
  add_prod_datum(:notin, data[:ExpressionList])
1224
1639
  end
@@ -1226,10 +1641,14 @@ module SPARQL::Grammar
1226
1641
  # [116] AdditiveExpression ::= MultiplicativeExpression
1227
1642
  # ( '+' MultiplicativeExpression
1228
1643
  # | '-' MultiplicativeExpression
1229
- # | ( NumericLiteralPositive | NumericLiteralNegative )
1644
+ # | ( NumericLiteralPositive
1645
+ # | NumericLiteralNegative )
1230
1646
  # ( ( '*' UnaryExpression )
1231
1647
  # | ( '/' UnaryExpression ) )?
1232
1648
  # )*
1649
+ #
1650
+ # Input from `data` is TODO.
1651
+ # Output to prod_data is TODO.
1233
1652
  production(:AdditiveExpression) do |input, data, callback|
1234
1653
  add_operator_expressions(:_Add_Sub, data)
1235
1654
  end
@@ -1240,11 +1659,17 @@ module SPARQL::Grammar
1240
1659
  # ( ( '*' UnaryExpression )
1241
1660
  # | ( '/' UnaryExpression ) )?
1242
1661
  # )*
1662
+ #
1663
+ # Input from `data` is TODO.
1664
+ # Output to prod_data is TODO.
1243
1665
  production(:_AdditiveExpression_1) do |input, data, callback|
1244
1666
  accumulate_operator_expressions(:AdditiveExpression, :_Add_Sub, data)
1245
1667
  end
1246
1668
 
1247
1669
  # | ( NumericLiteralPositive | NumericLiteralNegative )
1670
+ #
1671
+ # Input from `data` is TODO.
1672
+ # Output to prod_data is TODO.
1248
1673
  production(:_AdditiveExpression_7) do |input, data, callback|
1249
1674
  lit = data[:literal]
1250
1675
  val = lit.to_s
@@ -1253,23 +1678,32 @@ module SPARQL::Grammar
1253
1678
  add_prod_datum(:Expression, [lit.class.new(val)])
1254
1679
  end
1255
1680
 
1256
- # [117] MultiplicativeExpression ::= UnaryExpression
1257
- # ( '*' UnaryExpression
1258
- # | '/' UnaryExpression )*
1681
+ # [117] MultiplicativeExpression ::= UnaryExpression
1682
+ # ( '*' UnaryExpression
1683
+ # | '/' UnaryExpression )*
1684
+ #
1685
+ # Input from `data` is TODO.
1686
+ # Output to prod_data is TODO.
1259
1687
  production(:MultiplicativeExpression) do |input, data, callback|
1260
1688
  add_operator_expressions(:_Mul_Div, data)
1261
1689
  end
1262
1690
 
1263
1691
  # ( '*' UnaryExpression
1264
1692
  # | '/' UnaryExpression )*
1693
+ #
1694
+ # Input from `data` is TODO.
1695
+ # Output to prod_data is TODO.
1265
1696
  production(:_MultiplicativeExpression_1) do |input, data, callback|
1266
1697
  accumulate_operator_expressions(:MultiplicativeExpression, :_Mul_Div, data)
1267
1698
  end
1268
1699
 
1269
- # [118] UnaryExpression ::= '!' PrimaryExpression
1270
- # | '+' PrimaryExpression
1271
- # | '-' PrimaryExpression
1272
- # | PrimaryExpression
1700
+ # [118] UnaryExpression ::= '!' PrimaryExpression
1701
+ # | '+' PrimaryExpression
1702
+ # | '-' PrimaryExpression
1703
+ # | PrimaryExpression
1704
+ #
1705
+ # Input from `data` is TODO.
1706
+ # Output to prod_data is TODO.
1273
1707
  production(:UnaryExpression) do |input, data, callback|
1274
1708
  case data[:UnaryExpression]
1275
1709
  when ["!"]
@@ -1286,11 +1720,14 @@ module SPARQL::Grammar
1286
1720
  end
1287
1721
  end
1288
1722
 
1289
- # [119] PrimaryExpression ::= BrackettedExpression | BuiltInCall
1290
- # | iriOrFunction | RDFLiteral
1291
- # | NumericLiteral | BooleanLiteral
1292
- # | Var
1293
- # | ExprQuotedTP
1723
+ # [119] PrimaryExpression ::= BrackettedExpression | BuiltInCall
1724
+ # | iriOrFunction | RDFLiteral
1725
+ # | NumericLiteral | BooleanLiteral
1726
+ # | Var
1727
+ # | ExprQuotedTP
1728
+ #
1729
+ # Input from `data` is TODO.
1730
+ # Output to prod_data is TODO.
1294
1731
  production(:PrimaryExpression) do |input, data, callback|
1295
1732
  if data[:Expression]
1296
1733
  add_prod_datum(:Expression, data[:Expression])
@@ -1312,62 +1749,65 @@ module SPARQL::Grammar
1312
1749
  add_prod_datum(:UnaryExpression, data[:UnaryExpression])
1313
1750
  end
1314
1751
 
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
1752
+ # [121] BuiltInCall ::= Aggregate
1753
+ # | 'STR' '(' Expression ')'
1754
+ # | 'LANG' '(' Expression ')'
1755
+ # | 'LANGMATCHES' '(' Expression ',' Expression ')'
1756
+ # | 'DATATYPE' '(' Expression ')'
1757
+ # | 'BOUND' '(' Var ')'
1758
+ # | 'IRI' '(' Expression ')'
1759
+ # | 'URI' '(' Expression ')'
1760
+ # | 'BNODE' ( '(' Expression ')' | NIL )
1761
+ # | 'RAND' NIL
1762
+ # | 'ABS' '(' Expression ')'
1763
+ # | 'CEIL' '(' Expression ')'
1764
+ # | 'FLOOR' '(' Expression ')'
1765
+ # | 'ROUND' '(' Expression ')'
1766
+ # | 'CONCAT' ExpressionList
1767
+ # | SubstringExpression
1768
+ # | 'STRLEN' '(' Expression ')'
1769
+ # | StrReplaceExpression
1770
+ # | 'UCASE' '(' Expression ')'
1771
+ # | 'LCASE' '(' Expression ')'
1772
+ # | 'ENCODE_FOR_URI' '(' Expression ')'
1773
+ # | 'CONTAINS' '(' Expression ',' Expression ')'
1774
+ # | 'STRSTARTS' '(' Expression ',' Expression ')'
1775
+ # | 'STRENDS' '(' Expression ',' Expression ')'
1776
+ # | 'STRBEFORE' '(' Expression ',' Expression ')'
1777
+ # | 'STRAFTER' '(' Expression ',' Expression ')'
1778
+ # | 'YEAR' '(' Expression ')'
1779
+ # | 'MONTH' '(' Expression ')'
1780
+ # | 'DAY' '(' Expression ')'
1781
+ # | 'HOURS' '(' Expression ')'
1782
+ # | 'MINUTES' '(' Expression ')'
1783
+ # | 'SECONDS' '(' Expression ')'
1784
+ # | 'TIMEZONE' '(' Expression ')'
1785
+ # | 'TZ' '(' Expression ')'
1786
+ # | 'NOW' NIL
1787
+ # | 'UUID' NIL
1788
+ # | 'STRUUID' NIL
1789
+ # | 'MD5' '(' Expression ')'
1790
+ # | 'SHA1' '(' Expression ')'
1791
+ # | 'SHA224' '(' Expression ')'
1792
+ # | 'SHA256' '(' Expression ')'
1793
+ # | 'SHA384' '(' Expression ')'
1794
+ # | 'SHA512' '(' Expression ')'
1795
+ # | 'COALESCE' ExpressionList
1796
+ # | 'IF' '(' Expression ',' Expression ',' Expression ')'
1797
+ # | 'STRLANG' '(' Expression ',' Expression ')'
1798
+ # | 'STRDT' '(' Expression ',' Expression ')'
1799
+ # | 'sameTerm' '(' Expression ',' Expression ')'
1800
+ # | 'isIRI' '(' Expression ')'
1801
+ # | 'isURI' '(' Expression ')'
1802
+ # | 'isBLANK' '(' Expression ')'
1803
+ # | 'isLITERAL' '(' Expression ')'
1804
+ # | 'isNUMERIC' '(' Expression ')'
1805
+ # | RegexExpression
1806
+ # | ExistsFunc
1807
+ # | NotExistsFunc
1808
+ #
1809
+ # Input from `data` is TODO.
1810
+ # Output to prod_data is TODO.
1371
1811
  production(:BuiltInCall) do |input, data, callback|
1372
1812
  input[:BuiltInCall] = if builtin = data.keys.detect {|k| BUILTINS.include?(k)}
1373
1813
  SPARQL::Algebra::Expression.for(
@@ -1384,45 +1824,63 @@ module SPARQL::Grammar
1384
1824
  end
1385
1825
  end
1386
1826
 
1387
- # [122] RegexExpression ::= 'REGEX' '(' Expression ',' Expression
1388
- # ( ',' Expression )? ')'
1827
+ # [122] RegexExpression ::= 'REGEX' '(' Expression ',' Expression
1828
+ # ( ',' Expression )? ')'
1829
+ #
1830
+ # Input from `data` is TODO.
1831
+ # Output to prod_data is TODO.
1389
1832
  production(:RegexExpression) do |input, data, callback|
1390
1833
  add_prod_datum(:regex, data[:Expression])
1391
1834
  end
1392
1835
 
1393
- # [123] SubstringExpression ::= 'SUBSTR'
1394
- # '(' Expression ',' Expression
1395
- # ( ',' Expression )? ')'
1836
+ # [123] SubstringExpression ::= 'SUBSTR'
1837
+ # '(' Expression ',' Expression
1838
+ # ( ',' Expression )? ')'
1839
+ #
1840
+ # Input from `data` is TODO.
1841
+ # Output to prod_data is TODO.
1396
1842
  production(:SubstringExpression) do |input, data, callback|
1397
1843
  add_prod_datum(:substr, data[:Expression])
1398
1844
  end
1399
1845
 
1400
- # [124] StrReplaceExpression ::= 'REPLACE'
1401
- # '(' Expression ','
1402
- # Expression ',' Expression
1403
- # ( ',' Expression )? ')'
1846
+ # [124] StrReplaceExpression ::= 'REPLACE'
1847
+ # '(' Expression ','
1848
+ # Expression ',' Expression
1849
+ # ( ',' Expression )? ')'
1850
+ #
1851
+ # Input from `data` is TODO.
1852
+ # Output to prod_data is TODO.
1404
1853
  production(:StrReplaceExpression) do |input, data, callback|
1405
1854
  add_prod_datum(:replace, data[:Expression])
1406
1855
  end
1407
1856
 
1408
- # [125] ExistsFunc ::= 'EXISTS' GroupGraphPattern
1857
+ # [125] ExistsFunc ::= 'EXISTS' GroupGraphPattern
1858
+ #
1859
+ # Input from `data` is TODO.
1860
+ # Output to prod_data is TODO.
1409
1861
  production(:ExistsFunc) do |input, data, callback|
1410
1862
  add_prod_datum(:exists, data[:query])
1411
1863
  end
1412
1864
 
1413
- # [126] NotExistsFunc ::= 'NOT' 'EXISTS' GroupGraphPattern
1865
+ # [126] NotExistsFunc ::= 'NOT' 'EXISTS' GroupGraphPattern
1866
+ #
1867
+ # Input from `data` is TODO.
1868
+ # Output to prod_data is TODO.
1414
1869
  production(:NotExistsFunc) do |input, data, callback|
1415
1870
  add_prod_datum(:notexists, data[:query])
1416
1871
  end
1417
1872
 
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 )? ')'
1873
+ # [127] Aggregate ::= 'COUNT' '(' 'DISTINCT'? ( '*' | Expression ) ')'
1874
+ # | 'SUM' '(' 'DISTINCT'? Expression ')'
1875
+ # | 'MIN' '(' 'DISTINCT'? Expression ')'
1876
+ # | 'MAX' '(' 'DISTINCT'? Expression ')'
1877
+ # | 'AVG' '(' 'DISTINCT'? Expression ')'
1878
+ # | 'SAMPLE' '(' 'DISTINCT'? Expression ')'
1879
+ # | 'GROUP_CONCAT' '(' 'DISTINCT'? Expression
1880
+ # ( ';' 'SEPARATOR' '=' String )? ')'
1881
+ #
1882
+ # Input from `data` is TODO.
1883
+ # Output to prod_data is TODO.
1426
1884
  production(:Aggregate) do |input, data, callback|
1427
1885
  if aggregate_rule = data.keys.detect {|k| AGGREGATE_RULES.include?(k)}
1428
1886
  parts = [aggregate_rule]
@@ -1433,7 +1891,10 @@ module SPARQL::Grammar
1433
1891
  end
1434
1892
  end
1435
1893
 
1436
- # [128] iriOrFunction ::= iri ArgList?
1894
+ # [128] iriOrFunction ::= iri ArgList?
1895
+ #
1896
+ # Input from `data` is TODO.
1897
+ # Output to prod_data is TODO.
1437
1898
  production(:iriOrFunction) do |input, data, callback|
1438
1899
  if data.has_key?(:ArgList)
1439
1900
  # Function is (func arg1 arg2 ...)
@@ -1443,20 +1904,26 @@ module SPARQL::Grammar
1443
1904
  end
1444
1905
  end
1445
1906
 
1446
- # [129] RDFLiteral ::= String ( LANGTAG | ( '^^' iri ) )?
1907
+ # [129] RDFLiteral ::= String ( LANGTAG | ( '^^' iri ) )?
1908
+ #
1909
+ # Input from `data` is TODO.
1910
+ # Output to prod_data is TODO.
1447
1911
  production(:RDFLiteral) do |input, data, callback|
1448
1912
  if data[:string]
1449
1913
  lit = data.dup
1450
1914
  str = lit.delete(:string)
1451
1915
  lit[:datatype] = lit.delete(:iri) if lit[:iri]
1452
- lit[:language] = lit.delete(:language).last.downcase if lit[:language]
1916
+ lit[:language] = lit.delete(:language).downcase if lit[:language]
1453
1917
  input[:literal] = RDF::Literal.new(str, **lit) if str
1454
1918
  end
1455
1919
  end
1456
1920
 
1457
- # [132] NumericLiteralPositive ::= INTEGER_POSITIVE
1458
- # | DECIMAL_POSITIVE
1459
- # | DOUBLE_POSITIVE
1921
+ # [132] NumericLiteralPositive ::= INTEGER_POSITIVE
1922
+ # | DECIMAL_POSITIVE
1923
+ # | DOUBLE_POSITIVE
1924
+ #
1925
+ # Input from `data` is TODO.
1926
+ # Output to prod_data is TODO.
1460
1927
  production(:NumericLiteralPositive) do |input, data, callback|
1461
1928
  num = data.values.flatten.last
1462
1929
  input[:literal] = num
@@ -1465,9 +1932,12 @@ module SPARQL::Grammar
1465
1932
  add_prod_datum(:UnaryExpression, data[:UnaryExpression])
1466
1933
  end
1467
1934
 
1468
- # [133] NumericLiteralNegative ::= INTEGER_NEGATIVE
1469
- # | DECIMAL_NEGATIVE
1470
- # | DOUBLE_NEGATIVE
1935
+ # [133] NumericLiteralNegative ::= INTEGER_NEGATIVE
1936
+ # | DECIMAL_NEGATIVE
1937
+ # | DOUBLE_NEGATIVE
1938
+ #
1939
+ # Input from `data` is TODO.
1940
+ # Output to prod_data is TODO.
1471
1941
  production(:NumericLiteralNegative) do |input, data, callback|
1472
1942
  num = data.values.flatten.last
1473
1943
  input[:literal] = num
@@ -1477,61 +1947,81 @@ module SPARQL::Grammar
1477
1947
  end
1478
1948
 
1479
1949
  # [174] QuotedTP ::= '<<' qtSubjectOrObject Verb qtSubjectOrObject '>>'
1950
+ #
1951
+ # Input from `data` is `:qtSubjectOrObject` from which subject and object are extracted and `:Verb` from which predicate is extracted.
1952
+ # Output to prod_data is `:QuotedTP` containing subject, predicate, and object.
1480
1953
  production(:QuotedTP) do |input, data, callback|
1481
1954
  subject, object = data[:qtSubjectOrObject]
1482
1955
  predicate = data[:Verb]
1483
1956
  add_pattern(:QuotedTP,
1484
1957
  subject: subject,
1485
1958
  predicate: predicate,
1486
- object: object)
1959
+ object: object,
1960
+ quoted: true)
1487
1961
  end
1488
1962
 
1489
1963
  # [175] QuotedTriple ::= '<<' DataValueTerm (iri | 'a') DataValueTerm '>>'
1964
+ #
1965
+ # Input from `data` is TODO.
1966
+ # Output to prod_data is TODO.
1490
1967
  production(:QuotedTriple) do |input, data, callback|
1491
1968
  subject, object = data[:DataValueTerm]
1492
1969
  predicate = data[:iri]
1493
1970
  add_pattern(:QuotedTriple,
1494
1971
  subject: subject,
1495
1972
  predicate: predicate,
1496
- object: object)
1973
+ object: object,
1974
+ quoted: true)
1497
1975
  end
1498
1976
 
1499
- # [176] qtSubjectOrObject ::= Var | BlankNode | iri | RDFLiteral
1500
- # | NumericLiteral | BooleanLiteral | QuotedTP
1977
+ # [176] qtSubjectOrObject ::= Var | BlankNode | iri | RDFLiteral
1978
+ # | NumericLiteral | BooleanLiteral | QuotedTP
1979
+ #
1980
+ # Input from `data` is TODO.
1981
+ # Output to prod_data is TODO.
1501
1982
  production(:qtSubjectOrObject) do |input, data, callback|
1502
1983
  data.values.each {|v| add_prod_datum(:qtSubjectOrObject, v)}
1503
1984
  end
1504
1985
 
1505
- # [177] DataValueTerm ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | QuotedTriple
1986
+ # [177] DataValueTerm ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | QuotedTriple
1987
+ #
1988
+ # Input from `data` is TODO.
1989
+ # Output to prod_data is TODO.
1506
1990
  production(:DataValueTerm) do |input, data, callback|
1507
1991
  add_prod_datum :DataValueTerm, data.values.first
1508
1992
  end
1509
1993
 
1510
- # [180] AnnotationPatternPath ::= '{|' PropertyListPathNotEmpty '|}'
1994
+ # [180] AnnotationPatternPath ::= '{|' PropertyListPathNotEmpty '|}'
1511
1995
  start_production(:AnnotationPatternPath) do |input, data, callback|
1512
1996
  data[:TriplesNode] = input[:TriplesNode]
1513
1997
  end
1998
+
1999
+ #
2000
+ # Add `:TriplesNode` as subject of collected patterns
2001
+ # Input from `data` is `:pattern`.
2002
+ # Output to prod_data is `:pattern`.
1514
2003
  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
2004
+ add_prod_datum(:pattern, data[:pattern])
1522
2005
  end
1523
2006
 
1524
2007
  # [181] ExprQuotedTP ::= '<<' ExprVarOrTerm Verb ExprVarOrTerm '>>'
2008
+ #
2009
+ # Input from `data` is TODO.
2010
+ # Output to prod_data is TODO.
1525
2011
  production(:ExprQuotedTP) do |input, data, callback|
1526
2012
  subject, object = data[:ExprVarOrTerm]
1527
2013
  predicate = data[:Verb]
1528
2014
  add_pattern(:ExprQuotedTP,
1529
2015
  subject: subject,
1530
2016
  predicate: predicate,
1531
- object: object)
2017
+ object: object,
2018
+ quoted: true)
1532
2019
  end
1533
2020
 
1534
- # [182] ExprVarOrTerm ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | Var | ExprQuotedTP
2021
+ # [182] ExprVarOrTerm ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | Var | ExprQuotedTP
2022
+ #
2023
+ # Input from `data` is TODO.
2024
+ # Output to prod_data is TODO.
1535
2025
  production(:ExprVarOrTerm) do |input, data, callback|
1536
2026
  data.values.each {|v| add_prod_datum(:ExprVarOrTerm, v)}
1537
2027
  end
@@ -1541,20 +2031,23 @@ module SPARQL::Grammar
1541
2031
  #
1542
2032
  # @param [String, IO, StringIO, #to_s] input
1543
2033
  # @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)
2034
+ # @option options [Boolean] :all_vars (false)
2035
+ # If `true`, emits on empty `project` operator when parsing `SELECT *`, which will emit all in-scope variables, rather than just those used in solutions.
2036
+ # In the next minor release, the default for this option will change to `true`.
1548
2037
  # @option options [#to_s] :anon_base ("b0")
1549
2038
  # Basis for generating anonymous Nodes
2039
+ # @option options [#to_s] :base_uri (nil)
2040
+ # the base URI to use when resolving relative URIs (for acessing intermediate parser productions)
2041
+ # @option options [Logger, #write, #<<] :logger
2042
+ # Record error/info/debug output
2043
+ # @option options [Hash] :prefixes (Hash.new)
2044
+ # the prefix mappings to use (for acessing intermediate parser productions)
1550
2045
  # @option options [Boolean] :resolve_iris (false)
1551
2046
  # Resolve prefix and relative IRIs, otherwise, when serializing the parsed SSE
1552
2047
  # as S-Expressions, use the original prefixed and relative URIs along with `base` and `prefix`
1553
2048
  # definitions.
1554
2049
  # @option options [Boolean] :validate (false)
1555
2050
  # whether to validate the parsed statements and values
1556
- # @option options [Logger, #write, #<<] :logger
1557
- # Record error/info/debug output
1558
2051
  # @yield [parser] `self`
1559
2052
  # @yieldparam [SPARQL::Grammar::Parser] parser
1560
2053
  # @yieldreturn [void] ignored
@@ -1615,7 +2108,7 @@ module SPARQL::Grammar
1615
2108
  #
1616
2109
  # @param [Symbol, #to_s] prod The starting production for the parser.
1617
2110
  # It may be a URI from the grammar, or a symbol representing the local_name portion of the grammar URI.
1618
- # @return [Array]
2111
+ # @return [RDF::Queryable]
1619
2112
  # @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
1620
2113
  # @see https://axel.deri.ie/sparqltutorial/ESWC2007_SPARQL_Tutorial_unit2b.pdf
1621
2114
  def parse(prod = START)
@@ -1811,9 +2304,7 @@ module SPARQL::Grammar
1811
2304
  # If we have a base URI, use that when constructing a new URI
1812
2305
  value = RDF::URI(value)
1813
2306
  if base_uri && value.relative?
1814
- u = base_uri.join(value)
1815
- #u.lexical = "<#{value}>" unless resolve_iris?
1816
- #u
2307
+ base_uri.join(value)
1817
2308
  else
1818
2309
  value
1819
2310
  end
@@ -1823,10 +2314,7 @@ module SPARQL::Grammar
1823
2314
  base = prefix(prefix).to_s
1824
2315
  suffix = suffix.to_s.sub(/^\#/, "") if base.index("#")
1825
2316
  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
2317
+ iri(base + suffix.to_s)
1830
2318
  end
1831
2319
 
1832
2320
  # Create a literal
@@ -1869,10 +2357,12 @@ module SPARQL::Grammar
1869
2357
  # add a pattern
1870
2358
  #
1871
2359
  # @param [String] production Production generating pattern
2360
+ # @param [Boolean] quoted For quoted triple
1872
2361
  # @param [Hash{Symbol => Object}] options
1873
- def add_pattern(production, **options)
2362
+ def add_pattern(production, quoted: false, **options)
1874
2363
  progress(production, "[:pattern, #{options[:subject]}, #{options[:predicate]}, #{options[:object]}]")
1875
2364
  triple = {}
2365
+ triple[:quoted] = true if quoted
1876
2366
  options.each_pair do |r, v|
1877
2367
  if v.is_a?(Array) && v.flatten.length == 1
1878
2368
  v = v.flatten.first
@@ -1894,6 +2384,7 @@ module SPARQL::Grammar
1894
2384
  [expr, query]
1895
2385
  end
1896
2386
 
2387
+ ##
1897
2388
  # Merge query modifiers, datasets, and projections
1898
2389
  #
1899
2390
  # This includes tranforming aggregates if also used with a GROUP BY
@@ -1988,7 +2479,14 @@ module SPARQL::Grammar
1988
2479
 
1989
2480
  query = SPARQL::Algebra::Expression[:order, data[:order].first, query] unless order.empty?
1990
2481
 
1991
- query = SPARQL::Algebra::Expression[:project, vars, query] unless vars.empty?
2482
+ # If SELECT * was used, emit a projection with empty variables, vs no projection at all. Only if :all_vars is true
2483
+ query = if vars == %i(*)
2484
+ options[:all_vars] ? SPARQL::Algebra::Expression[:project, [], query] : query
2485
+ elsif !vars.empty?
2486
+ SPARQL::Algebra::Expression[:project, vars, query]
2487
+ else
2488
+ query
2489
+ end
1992
2490
 
1993
2491
  query = SPARQL::Algebra::Expression[data[:DISTINCT_REDUCED], query] if data[:DISTINCT_REDUCED]
1994
2492