sparql 3.2.1 → 3.2.3

Sign up to get free protection for your applications and to get access to all the features.
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