sparql 1.1.6 → 1.1.7

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.
@@ -55,17 +55,17 @@ module SPARQL::Grammar
55
55
 
56
56
  # Terminals passed to lexer. Order matters!
57
57
  terminal(:ANON, ANON) do |prod, token, input|
58
- add_prod_datum(:BlankNode, bnode)
58
+ input[:BlankNode] = bnode
59
59
  end
60
60
  terminal(:NIL, NIL) do |prod, token, input|
61
- add_prod_datum(:NIL, RDF['nil'])
61
+ input[:NIL] = RDF['nil']
62
62
  end
63
63
  terminal(:BLANK_NODE_LABEL, BLANK_NODE_LABEL) do |prod, token, input|
64
- add_prod_datum(:BlankNode, bnode(token.value[2..-1]))
64
+ input[:BlankNode] = bnode(token.value[2..-1])
65
65
  end
66
66
  terminal(:IRIREF, IRIREF, unescape: true) do |prod, token, input|
67
67
  begin
68
- add_prod_datum(:iri, iri(token.value[1..-2]))
68
+ input[:iri] = iri(token.value[1..-2])
69
69
  rescue ArgumentError => e
70
70
  raise Error, e.message
71
71
  end
@@ -74,75 +74,74 @@ module SPARQL::Grammar
74
74
  # Note that a Turtle Double may begin with a '.[eE]', so tack on a leading
75
75
  # zero if necessary
76
76
  value = token.value.sub(/\.([eE])/, '.0\1')
77
- add_prod_datum(:literal, literal(value, datatype: RDF::XSD.double))
77
+ input[:literal] = literal(value, datatype: RDF::XSD.double)
78
78
  end
79
79
  terminal(:DECIMAL_POSITIVE, DECIMAL_POSITIVE) do |prod, token, input|
80
80
  # Note that a Turtle Decimal may begin with a '.', so tack on a leading
81
81
  # zero if necessary
82
82
  value = token.value
83
83
  value = "0#{token.value}" if token.value[0,1] == "."
84
- add_prod_datum(:literal, literal(value, datatype: RDF::XSD.decimal))
84
+ input[:literal] = literal(value, datatype: RDF::XSD.decimal)
85
85
  end
86
86
  terminal(:INTEGER_POSITIVE, INTEGER_POSITIVE) do |prod, token, input|
87
- add_prod_datum(:literal, literal(token.value, datatype: RDF::XSD.integer))
87
+ input[:literal] = literal(token.value, datatype: RDF::XSD.integer)
88
88
  end
89
89
  terminal(:DOUBLE_NEGATIVE, DOUBLE_NEGATIVE) do |prod, token, input|
90
90
  # Note that a Turtle Double may begin with a '.[eE]', so tack on a leading
91
91
  # zero if necessary
92
92
  value = token.value.sub(/\.([eE])/, '.0\1')
93
- add_prod_datum(:literal, literal(value, datatype: RDF::XSD.double))
93
+ input[:literal] = literal(value, datatype: RDF::XSD.double)
94
94
  end
95
95
  terminal(:DECIMAL_NEGATIVE, DECIMAL_NEGATIVE) do |prod, token, input|
96
96
  # Note that a Turtle Decimal may begin with a '.', so tack on a leading
97
97
  # zero if necessary
98
98
  value = token.value
99
99
  value = "0#{token.value}" if token.value[0,1] == "."
100
- add_prod_datum(:literal, literal(value, datatype: RDF::XSD.decimal))
100
+ input[:literal] = literal(value, datatype: RDF::XSD.decimal)
101
101
  end
102
102
  terminal(:INTEGER_NEGATIVE, INTEGER_NEGATIVE) do |prod, token, input|
103
- add_prod_datum(:resource, literal(token.value, datatype: RDF::XSD.integer))
103
+ input[:literal] = literal(token.value, datatype: RDF::XSD.integer)
104
104
  end
105
105
  terminal(:DOUBLE, DOUBLE) do |prod, token, input|
106
106
  # Note that a Turtle Double may begin with a '.[eE]', so tack on a leading
107
107
  # zero if necessary
108
108
  value = token.value.sub(/\.([eE])/, '.0\1')
109
- add_prod_datum(:literal, literal(value, datatype: RDF::XSD.double))
109
+ input[:literal] = literal(value, datatype: RDF::XSD.double)
110
110
  end
111
111
  terminal(:DECIMAL, DECIMAL) do |prod, token, input|
112
112
  # Note that a Turtle Decimal may begin with a '.', so tack on a leading
113
113
  # zero if necessary
114
114
  value = token.value
115
115
  #value = "0#{token.value}" if token.value[0,1] == "."
116
- add_prod_datum(:literal, literal(value, datatype: RDF::XSD.decimal))
116
+ input[:literal] = literal(value, datatype: RDF::XSD.decimal)
117
117
  end
118
118
  terminal(:INTEGER, INTEGER) do |prod, token, input|
119
- add_prod_datum(:literal, literal(token.value, datatype: RDF::XSD.integer))
119
+ input[:literal] = literal(token.value, datatype: RDF::XSD.integer)
120
120
  end
121
121
  terminal(:LANGTAG, LANGTAG) do |prod, token, input|
122
122
  add_prod_datum(:language, token.value[1..-1])
123
123
  end
124
124
  terminal(:PNAME_LN, PNAME_LN, unescape: true) do |prod, token, input|
125
125
  prefix, suffix = token.value.split(":", 2)
126
- add_prod_datum(:PrefixedName, ns(prefix, suffix))
126
+ input[:iri] = ns(prefix, suffix)
127
127
  end
128
128
  terminal(:PNAME_NS, PNAME_NS) do |prod, token, input|
129
129
  prefix = token.value[0..-2]
130
130
  # [68] PrefixedName ::= PNAME_LN | PNAME_NS
131
- add_prod_datum(:PrefixedName, ns(prefix, nil))
132
- # [4] PrefixDecl := 'PREFIX' PNAME_NS IRI_REF";
133
- add_prod_datum(:prefix, prefix && prefix.to_sym)
131
+ input[:iri] = ns(prefix, nil)
132
+ input[:prefix] = prefix && prefix.to_sym
134
133
  end
135
134
  terminal(:STRING_LITERAL_LONG1, STRING_LITERAL_LONG1, unescape: true) do |prod, token, input|
136
- add_prod_datum(:string, token.value[3..-4])
135
+ input[:string] = token.value[3..-4]
137
136
  end
138
137
  terminal(:STRING_LITERAL_LONG2, STRING_LITERAL_LONG2, unescape: true) do |prod, token, input|
139
- add_prod_datum(:string, token.value[3..-4])
138
+ input[:string] = token.value[3..-4]
140
139
  end
141
140
  terminal(:STRING_LITERAL1, STRING_LITERAL1, unescape: true) do |prod, token, input|
142
- add_prod_datum(:string, token.value[1..-2])
141
+ input[:string] = token.value[1..-2]
143
142
  end
144
143
  terminal(:STRING_LITERAL2, STRING_LITERAL2, unescape: true) do |prod, token, input|
145
- add_prod_datum(:string, token.value[1..-2])
144
+ input[:string] = token.value[1..-2]
146
145
  end
147
146
  terminal(:VAR1, VAR1) do |prod, token, input|
148
147
  add_prod_datum(:Var, variable(token.value[1..-1]))
@@ -160,19 +159,23 @@ module SPARQL::Grammar
160
159
  add_prod_datum(:AdditiveExpression, token.value)
161
160
  when :_UnaryExpression_2, :_UnaryExpression_3
162
161
  add_prod_datum(:UnaryExpression, token.value)
162
+ when :PathMod
163
+ add_prod_datum(:PathMod, token.value)
163
164
  else
164
165
  raise "Unexpected production #{prod} for #{token}"
165
166
  end
167
+ when '?' then add_prod_datum(:PathMod, token.value)
168
+ when '^' then input[:reverse] = token.value
166
169
  when '*', '/' then add_prod_datum(:MultiplicativeExpression, token.value)
167
170
  when '=', '!=', '<',
168
171
  '>', '<=', '>=' then add_prod_datum(:RelationalExpression, token.value)
169
172
  when '&&' then add_prod_datum(:ConditionalAndExpression, token.value)
170
173
  when '||' then add_prod_datum(:ConditionalOrExpression, token.value)
171
174
  when '!' then add_prod_datum(:UnaryExpression, token.value)
172
- when 'a' then add_prod_datum(:Verb, (a = RDF.type.dup; a.lexical = 'a'; a))
173
- when /true|false/ then add_prod_datum(:literal, RDF::Literal::Boolean.new(token.value.downcase))
174
- when /ASC|DESC/ then add_prod_datum(:OrderDirection, token.value.downcase.to_sym)
175
- when /DISTINCT|REDUCED/ then add_prod_datum(:DISTINCT_REDUCED, token.value.downcase.to_sym)
175
+ when 'a' then input[:Verb] = (a = RDF.type.dup; a.lexical = 'a'; a)
176
+ when /true|false/ then input[:literal] = RDF::Literal::Boolean.new(token.value.downcase)
177
+ when /ASC|DESC/ then input[:OrderDirection] = token.value.downcase.to_sym
178
+ when /DISTINCT|REDUCED/ then input[:DISTINCT_REDUCED] = token.value.downcase.to_sym
176
179
  when %r{
177
180
  ABS|ALL|AVG|BNODE|BOUND|CEIL|COALESCE|CONCAT
178
181
  |CONTAINS|COUNT|DATATYPE|DAY|DEFAULT|ENCODE_FOR_URI|EXISTS
@@ -220,7 +223,7 @@ module SPARQL::Grammar
220
223
 
221
224
  # [5] BaseDecl ::= 'BASE' IRI_REF
222
225
  production(:BaseDecl) do |input, data, callback|
223
- iri = data[:iri].last
226
+ iri = data[:iri]
224
227
  debug("BaseDecl") {"Defined base as #{iri}"}
225
228
  self.base_uri = iri(iri)
226
229
  add_prod_datum(:BaseDecl, iri) unless resolve_iris?
@@ -229,14 +232,14 @@ module SPARQL::Grammar
229
232
  # [6] PrefixDecl ::= 'PREFIX' PNAME_NS IRI_REF
230
233
  production(:PrefixDecl) do |input, data, callback|
231
234
  if data[:iri]
232
- pfx = data[:prefix].last
233
- self.prefix(pfx, data[:iri].last)
234
- prefix_op = SPARQL::Algebra::Operator::Prefix.new([["#{pfx}:".to_sym, data[:iri].last]], [])
235
+ pfx = data[:prefix]
236
+ self.prefix(pfx, data[:iri])
237
+ prefix_op = SPARQL::Algebra::Operator::Prefix.new([["#{pfx}:".to_sym, data[:iri]]], [])
235
238
  add_prod_datum(:PrefixDecl, prefix_op)
236
239
  end
237
240
  end
238
241
 
239
- # [7] SelectQuery ::= SelectClause DatasetClause* WhereClause SolutionModifier ValuesClause
242
+ # [7] SelectQuery ::= SelectClause DatasetClause* WhereClause SolutionModifier
240
243
  production(:SelectQuery) do |input, data, callback|
241
244
  query = merge_modifiers(data)
242
245
  add_prod_datum :query, query
@@ -263,7 +266,6 @@ module SPARQL::Grammar
263
266
  # 'WHERE' '{' TriplesTemplate? '}'
264
267
  # SolutionModifier
265
268
  # )
266
- # ValuesClause
267
269
  production(:ConstructQuery) do |input, data, callback|
268
270
  data[:query] ||= [SPARQL::Algebra::Operator::BGP.new(*data[:pattern])]
269
271
  query = merge_modifiers(data)
@@ -272,14 +274,14 @@ module SPARQL::Grammar
272
274
  end
273
275
 
274
276
  # [11] DescribeQuery ::= 'DESCRIBE' ( VarOrIri+ | '*' )
275
- # DatasetClause* WhereClause? SolutionModifier ValuesClause
277
+ # DatasetClause* WhereClause? SolutionModifier
276
278
  production(:DescribeQuery) do |input, data, callback|
277
279
  query = merge_modifiers(data)
278
- to_describe = data[:VarOrIri] || []
280
+ to_describe = Array(data[:VarOrIri])
279
281
  add_prod_datum :query, SPARQL::Algebra::Expression[:describe, to_describe, query]
280
282
  end
281
283
 
282
- # [12] AskQuery ::= 'ASK' DatasetClause* WhereClause ValuesClause
284
+ # [12] AskQuery ::= 'ASK' DatasetClause* WhereClause
283
285
  production(:AskQuery) do |input, data, callback|
284
286
  query = merge_modifiers(data)
285
287
  add_prod_datum :query, SPARQL::Algebra::Expression[:ask, query]
@@ -292,7 +294,7 @@ module SPARQL::Grammar
292
294
 
293
295
  # [15] NamedGraphClause ::= 'NAMED' SourceSelector
294
296
  production(:NamedGraphClause) do |input, data, callback|
295
- add_prod_data :dataset, data[:iri].unshift(:named)
297
+ add_prod_data :dataset, [:named, data[:iri]]
296
298
  end
297
299
 
298
300
  # [18] SolutionModifier ::= GroupClause? HavingClause? OrderClause? LimitOffsetClauses?
@@ -336,7 +338,7 @@ module SPARQL::Grammar
336
338
  # | ( Constraint | Var )
337
339
  production(:OrderCondition) do |input, data, callback|
338
340
  if data[:OrderDirection]
339
- add_prod_datum(:OrderCondition, SPARQL::Algebra::Expression.for(data[:OrderDirection] + data[:Expression]))
341
+ add_prod_datum(:OrderCondition, SPARQL::Algebra::Expression(data[:OrderDirection], *data[:Expression]))
340
342
  else
341
343
  add_prod_datum(:OrderCondition, data[:Constraint] || data[:Var])
342
344
  end
@@ -367,7 +369,7 @@ module SPARQL::Grammar
367
369
  debug("ValuesClause") {"vars: #{data[:Var].inspect}, row: #{data[:row].inspect}"}
368
370
  if data[:row]
369
371
  add_prod_datum :ValuesClause, SPARQL::Algebra::Expression.for(:table,
370
- data[:Var].to_a.unshift(:vars),
372
+ Array(data[:Var]).unshift(:vars),
371
373
  *data[:row]
372
374
  )
373
375
  else
@@ -413,9 +415,13 @@ module SPARQL::Grammar
413
415
  production(:Load) do |input, data, callback|
414
416
  args = []
415
417
  args << :silent if data[:silent]
416
- args += Array(data[:iri])
418
+ args << data[:iri]
419
+ args << data[:into] if data[:into]
417
420
  input[:update_op] = SPARQL::Algebra::Expression(:load, *args)
418
421
  end
422
+ production(:_Load_2) do |input, data, callback|
423
+ input[:into] = data[:iri]
424
+ end
419
425
 
420
426
  # [32] Clear ::= "CLEAR" "SILENT"? GraphRefAll
421
427
  production(:Clear) do |input, data, callback|
@@ -496,7 +502,7 @@ module SPARQL::Grammar
496
502
  query = data[:query].first if data[:query]
497
503
  query = SPARQL::Algebra::Expression.for(:using, data[:using], query) if data[:using]
498
504
  operands = [query, data[:delete], data[:insert]].compact
499
- operands = [SPARQL::Algebra::Expression.for(:with, data[:iri].first, *operands)] if data[:iri]
505
+ operands = [SPARQL::Algebra::Expression.for(:with, data[:iri], *operands)] if data[:iri]
500
506
  input[:update_op] = SPARQL::Algebra::Expression(:modify, *operands)
501
507
  end
502
508
 
@@ -518,10 +524,10 @@ module SPARQL::Grammar
518
524
 
519
525
  # [44] UsingClause ::= "USING" ( iri | "NAMED" iri)
520
526
  production(:UsingClause) do |input, data, callback|
521
- add_prod_data(:using, data[:iri].first)
527
+ add_prod_data(:using, data[:iri])
522
528
  end
523
529
  production(:_UsingClause_2) do |input, data, callback|
524
- add_prod_data(:iri, [:named, data[:iri].first])
530
+ input[:iri] = [:named, data[:iri]]
525
531
  end
526
532
 
527
533
  # [45] GraphOrDefault ::= "DEFAULT" | "GRAPH"? iri
@@ -529,18 +535,14 @@ module SPARQL::Grammar
529
535
  if data[:default]
530
536
  add_prod_datum(:GraphOrDefault, :default)
531
537
  else
532
- add_prod_data(:GraphOrDefault, data[:iri].first)
538
+ add_prod_data(:GraphOrDefault, data[:iri])
533
539
  end
534
540
  end
535
541
 
536
542
  # [46] GraphRef ::= "GRAPH" iri
537
543
  production(:GraphRef) do |input, data, callback|
538
- add_prod_data(:iri, data[:iri].first)
544
+ input[:iri] = data[:iri]
539
545
  end
540
- # [47] GraphRefAll ::= GraphRef | "DEFAULT" | "NAMED" | "ALL"
541
- #production(:GraphRefAll) do |input, data, callback|
542
- # add_prod_datum(:GraphRefAll, data)
543
- #end
544
546
 
545
547
  # [49] QuadData ::= "{" Quads "}"
546
548
  # QuadData is like QuadPattern, except without BNodes
@@ -584,15 +586,19 @@ module SPARQL::Grammar
584
586
  # [55] TriplesBlock ::= TriplesSameSubjectPath
585
587
  # ( '.' TriplesBlock? )?
586
588
  production(:TriplesBlock) do |input, data, callback|
587
- query = SPARQL::Algebra::Operator::BGP.new
588
- data[:pattern].to_a.each {|p| query << p}
589
-
590
- # Append triples from ('.' TriplesBlock? )?
591
- data[:query].to_a.each {|q| query += q}
592
- if (lhs = (input.delete(:query) || []).first) && !lhs.empty?
593
- query = SPARQL::Algebra::Expression.for(:join, lhs, query)
589
+ if data[:pattern]
590
+ query = SPARQL::Algebra::Operator::BGP.new
591
+ Array(data[:pattern]).each {|p| query << p}
592
+
593
+ # Append triples from ('.' TriplesBlock? )?
594
+ Array(data[:query]).each {|q| query += q}
595
+ if (lhs = (input.delete(:query) || []).first) && !lhs.empty?
596
+ query = SPARQL::Algebra::Expression.for(:join, lhs, query)
597
+ end
598
+ add_prod_datum(:query, query)
599
+ else
600
+ add_prod_datum(:query, data[:path])
594
601
  end
595
- add_prod_datum(:query, query)
596
602
  end
597
603
 
598
604
  # [56] GraphPatternNotTriples ::= GroupOrUnionGraphPattern
@@ -684,10 +690,10 @@ module SPARQL::Grammar
684
690
  vars = data[:Var]
685
691
  add_prod_datum :Var, vars
686
692
 
687
- if data[:NIL].to_a.length > 1
693
+ if data[:nilrow]
688
694
  add_prod_data :row, [:row]
689
695
  else
690
- data[:DataBlockValue].to_a.each do |ds|
696
+ Array(data[:rowdata]).each do |ds|
691
697
  r = [:row]
692
698
  ds.each_with_index do |d, i|
693
699
  r << [vars[i], d] if d
@@ -697,9 +703,13 @@ module SPARQL::Grammar
697
703
  end
698
704
  end
699
705
 
700
- # _InlineDataFull_8 ::= '(' DataBlockValue* ')'
701
- production(:_InlineDataFull_8) do |input, data, callback|
702
- add_prod_data :DataBlockValue, data[:DataBlockValue].map {|v| v unless v == :undef}
706
+ # _InlineDataFull_6 ::= '(' '(' DataBlockValue* ')' | NIL ')'
707
+ production(:_InlineDataFull_6) do |input, data, callback|
708
+ if data[:DataBlockValue]
709
+ add_prod_data :rowdata, data[:DataBlockValue].map {|v| v unless v == :undef}
710
+ else
711
+ input[:nilrow] = true
712
+ end
703
713
  end
704
714
 
705
715
  # [65] DataBlockValue ::= iri | RDFLiteral | NumericLiteral | BooleanLiteral | 'UNDEF'
@@ -716,7 +726,7 @@ module SPARQL::Grammar
716
726
  # [67] GroupOrUnionGraphPattern ::= GroupGraphPattern
717
727
  # ( 'UNION' GroupGraphPattern )*
718
728
  production(:GroupOrUnionGraphPattern) do |input, data, callback|
719
- res = data[:query].to_a.first
729
+ res = Array(data[:query]).first
720
730
  if data[:union]
721
731
  while !data[:union].empty?
722
732
  # Join union patterns together as Union operators
@@ -731,7 +741,7 @@ module SPARQL::Grammar
731
741
 
732
742
  # ( 'UNION' GroupGraphPattern )*
733
743
  production(:_GroupOrUnionGraphPattern_1) do |input, data, callback|
734
- input[:union] = data[:union].to_a.unshift(data[:query].first)
744
+ input[:union] = Array(data[:union]).unshift(data[:query].first)
735
745
  end
736
746
 
737
747
  # [68] Filter ::= 'FILTER' Constraint
@@ -744,7 +754,7 @@ module SPARQL::Grammar
744
754
  production(:Constraint) do |input, data, callback|
745
755
  if data[:Expression]
746
756
  # Resolve expression to the point it is either an atom or an s-exp
747
- add_prod_data(:Constraint, data[:Expression].to_a.first)
757
+ add_prod_data(:Constraint, Array(data[:Expression]).first)
748
758
  elsif data[:BuiltInCall]
749
759
  add_prod_datum(:Constraint, data[:BuiltInCall])
750
760
  elsif data[:Function]
@@ -754,7 +764,7 @@ module SPARQL::Grammar
754
764
 
755
765
  # [70] FunctionCall ::= iri ArgList
756
766
  production(:FunctionCall) do |input, data, callback|
757
- add_prod_data(:Function, data[:iri] + data[:ArgList])
767
+ add_prod_data(:Function, Array(data[:iri]) + data[:ArgList])
758
768
  end
759
769
 
760
770
  # [71] ArgList ::= NIL
@@ -798,46 +808,76 @@ module SPARQL::Grammar
798
808
  add_prod_datum(:pattern, data[:pattern])
799
809
  end
800
810
 
811
+ # [78] Verb ::= VarOrIri | 'a'
812
+ production(:Verb) do |input, data, callback|
813
+ input[:Verb] = data.values.first
814
+ end
815
+
801
816
  # [79] ObjectList ::= Object ( ',' Object )*
802
817
  start_production(:ObjectList) do |input, data, callback|
803
818
  # Called after Verb. The prod_data stack should have Subject and Verb elements
804
819
  data[:Subject] = prod_data[:Subject]
805
820
  error(nil, "Expected Subject", production: :ObjectList) if !prod_data[:Subject] && validate?
806
- error(nil, "Expected Verb", production: :ObjectList) if !prod_data[:Verb] && validate?
821
+ error(nil, "Expected Verb", production: :ObjectList) if !(prod_data[:Verb] || prod_data[:VerbPath]) && validate?
807
822
  data[:Subject] = prod_data[:Subject]
808
- data[:Verb] = prod_data[:Verb].to_a.last
823
+ if prod_data[:Verb]
824
+ data[:Verb] = prod_data[:Verb]
825
+ else
826
+ data[:VerbPath] = prod_data[:VerbPath]
827
+ end
809
828
  end
810
829
  production(:ObjectList) do |input, data, callback|
811
830
  add_prod_datum(:pattern, data[:pattern])
831
+ add_prod_datum(:path, data[:path])
812
832
  end
813
833
 
814
834
  # [80] Object ::= GraphNode
815
835
  production(:Object) do |input, data, callback|
816
836
  object = data[:VarOrTerm] || data[:TriplesNode] || data[:GraphNode]
817
837
  if object
818
- add_pattern(:Object, subject: prod_data[:Subject], predicate: prod_data[:Verb], object: object)
819
- add_prod_datum(:pattern, data[:pattern])
838
+ if prod_data[:Verb]
839
+ add_pattern(:Object, subject: prod_data[:Subject], predicate: prod_data[:Verb], object: object)
840
+ add_prod_datum(:pattern, data[:pattern])
841
+ else
842
+ add_prod_datum(:path,
843
+ SPARQL::Algebra::Expression(:path,
844
+ prod_data[:Subject].first,
845
+ prod_data[:VerbPath],
846
+ object.first))
847
+ end
820
848
  end
821
849
  end
822
850
 
823
- # [78] Verb ::= VarOrIri | 'a'
824
- production(:Verb) do |input, data, callback|
825
- data.values.each {|v| add_prod_datum(:Verb, v)}
851
+ # [81] TriplesSameSubjectPath ::= VarOrTerm PropertyListPathNotEmpty | TriplesNode PropertyListPath
852
+ production(:TriplesSameSubjectPath) do |input, data, callback|
853
+ if data[:pattern]
854
+ add_prod_datum(:pattern, data[:pattern])
855
+ else
856
+ add_prod_datum(:path, data[:path])
857
+ end
826
858
  end
827
859
 
828
- # [83] PropertyListNotEmptyPath ::= ( VerbPath | VerbSimple ) ObjectList ( ';' ( ( VerbPath | VerbSimple ) ObjectList )? )*
829
- start_production(:PropertyListNotEmptyPath) do |input, data, callback|
830
- subject = input[:VarOrTerm]
831
- error(nil, "Expected VarOrTerm", production: ::PropertyListNotEmptyPath) if validate? && !subject
860
+ # [83] PropertyListPathNotEmpty ::= ( VerbPath | VerbSimple ) ObjectList ( ';' ( ( VerbPath | VerbSimple ) ObjectList )? )*
861
+ start_production(:PropertyListPathNotEmpty) do |input, data, callback|
862
+ subject = input[:VarOrTerm] || input[:TriplesNode] || input[:GraphNode]
863
+ error(nil, "Expected VarOrTerm, got nothing", production: :PropertyListPathNotEmpty) if validate? && !subject
832
864
  data[:Subject] = subject
833
865
  end
834
- production(:PropertyListNotEmptyPath) do |input, data, callback|
835
- add_prod_datum(:pattern, data[:pattern])
866
+ production(:PropertyListPathNotEmpty) do |input, data, callback|
867
+ if data[:pattern]
868
+ add_prod_datum(:pattern, data[:pattern])
869
+ else
870
+ add_prod_datum(:path, data[:path])
871
+ end
836
872
  end
837
873
 
838
874
  # [84] VerbPath ::= Path
839
875
  production(:VerbPath) do |input, data, callback|
840
- data.values.each {|v| add_prod_datum(:Verb, v)}
876
+ if data[:Path]
877
+ input[:VerbPath] = data[:Path]
878
+ else
879
+ input[:Verb] = data[:iri]
880
+ end
841
881
  end
842
882
 
843
883
  # [85] VerbSimple ::= Var
@@ -845,6 +885,134 @@ module SPARQL::Grammar
845
885
  data.values.each {|v| add_prod_datum(:Verb, v)}
846
886
  end
847
887
 
888
+ # [86] ObjectListPath ::= ObjectPath ("," ObjectPath)*
889
+ start_production(:ObjectListPath) do |input, data, callback|
890
+ # Called after Verb. The prod_data stack should have Subject and Verb elements
891
+ data[:Subject] = prod_data[:Subject]
892
+ error(nil, "Expected Subject", production: :ObjectListPath) if !prod_data[:Subject] && validate?
893
+ error(nil, "Expected Verb", production: :ObjectListPath) if !(prod_data[:Verb] || prod_data[:VerbPath]) && validate?
894
+ if prod_data[:Verb]
895
+ data[:Verb] = Array(prod_data[:Verb]).last
896
+ else
897
+ data[:VerbPath] = prod_data[:VerbPath]
898
+ end
899
+ end
900
+ production(:ObjectListPath) do |input, data, callback|
901
+ add_prod_datum(:pattern, data[:pattern])
902
+ add_prod_datum(:path, data[:path])
903
+ end
904
+
905
+ # [87] ObjectPath ::= GraphNodePath
906
+ production(:ObjectPath) do |input, data, callback|
907
+ object = data[:VarOrTerm] || data[:TriplesNode] || data[:GraphNode]
908
+ if object
909
+ if prod_data[:Verb]
910
+ if data[:pattern] && data[:path]
911
+ # Generate a sequence (for collection of paths)
912
+ data[:pattern].unshift(RDF::Query::Pattern.new(prod_data[:Subject].first, prod_data[:Verb], object.first))
913
+ bgp = SPARQL::Algebra::Expression[:bgp, data[:pattern]]
914
+ add_prod_datum(:path, SPARQL::Algebra::Expression[:sequence, bgp, *data[:path]])
915
+ else
916
+ add_pattern(:Object, subject: prod_data[:Subject], predicate: prod_data[:Verb], object: object)
917
+ add_prod_datum(:pattern, data[:pattern])
918
+ end
919
+ else
920
+ add_prod_datum(:path,
921
+ SPARQL::Algebra::Expression(:path,
922
+ Array(prod_data[:Subject]).first,
923
+ prod_data[:VerbPath],
924
+ object.first))
925
+ end
926
+ end
927
+ end
928
+ # [88] Path ::= PathAlternative
929
+ # output is a :Path or :iri
930
+ production(:Path) do |input, data, callback|
931
+ if data[:Path].is_a?(RDF::URI)
932
+ input[:iri] = data[:Path]
933
+ else
934
+ input[:Path] = data[:Path]
935
+ end
936
+ end
937
+
938
+ # [89] PathAlternative ::= PathSequence ( '|' PathSequence )*
939
+ production(:PathAlternative) do |input, data, callback|
940
+ lhs = Array(data[:PathSequence]).shift
941
+ while data[:PathSequence] && !data[:PathSequence].empty?
942
+ rhs = data[:PathSequence].shift
943
+ lhs = SPARQL::Algebra::Expression[:alt, lhs, rhs]
944
+ end
945
+ input[:Path] = lhs
946
+ end
947
+
948
+ # ( '|' PathSequence )*
949
+ production(:_PathAlternative_1) do |input, data, callback|
950
+ input[:PathSequence] += data[:PathSequence]
951
+ end
952
+
953
+ # [90] PathSequence ::= PathEltOrInverse ( '/' PathEltOrInverse )*
954
+ production(:PathSequence) do |input, data, callback|
955
+ lhs = data[:PathEltOrInverse].shift
956
+ while data[:PathEltOrInverse] && !data[:PathEltOrInverse].empty?
957
+ rhs = data[:PathEltOrInverse].shift
958
+ lhs = SPARQL::Algebra::Expression[:seq, lhs, rhs]
959
+ end
960
+ input[:PathSequence] = [lhs]
961
+ end
962
+
963
+ # ( '/' PathEltOrInverse )*
964
+ production(:_PathSequence_1) do |input, data, callback|
965
+ input[:PathEltOrInverse] += data[:PathEltOrInverse]
966
+ end
967
+
968
+ # [91] PathElt ::= PathPrimary PathMod?
969
+ production(:PathElt) do |input, data, callback|
970
+ path_mod = data.delete(:PathMod) if data.has_key?(:PathMod)
971
+ path_mod ||= data.delete(:MultiplicativeExpression) if data.has_key?(:MultiplicativeExpression)
972
+ path_mod = path_mod.first if path_mod
973
+
974
+ res = data[:PathPrimary]
975
+ res = SPARQL::Algebra::Expression("path#{path_mod}", res) if path_mod
976
+ input[:Path] = res
977
+ end
978
+
979
+ # [92] PathEltOrInverse ::= PathElt | '^' PathElt
980
+ production(:PathEltOrInverse) do |input, data, callback|
981
+ res = if data[:reverse]
982
+ SPARQL::Algebra::Expression(:reverse, data[:Path])
983
+ else
984
+ data[:Path]
985
+ end
986
+ input[:PathEltOrInverse] = [res]
987
+ end
988
+
989
+ # [94] PathPrimary ::= iri | 'a' | '!' PathNegatedPropertySet | '(' Path ')'
990
+ production(:PathPrimary) do |input, data, callback|
991
+ input[:PathPrimary] = case
992
+ when data[:Verb] then data[:Verb]
993
+ when data[:iri] then data[:iri]
994
+ when data[:PathNegatedPropertySet] then data[:PathNegatedPropertySet]
995
+ when data[:Path] then data[:Path]
996
+ end
997
+ end
998
+
999
+ # [95] PathNegatedPropertySet ::= PathOneInPropertySet | '(' ( PathOneInPropertySet ( '|' PathOneInPropertySet )* )? ')'
1000
+ production(:PathNegatedPropertySet) do |input, data, callback|
1001
+ input[:Path] = SPARQL::Algebra::Expression(:notoneof, *Array(data[:Path]))
1002
+ end
1003
+
1004
+ # ( '|' PathOneInPropertySet )* )?
1005
+ production(:_PathNegatedPropertySet_4) do |input, data, callback|
1006
+ add_prod_datum(:Path, data[:Path])
1007
+ end
1008
+
1009
+ # [96] PathOneInPropertySet ::= iri | 'a' | '^' ( iri | 'a' )
1010
+ production(:PathOneInPropertySet) do |input, data, callback|
1011
+ term = (Array(data[:iri]) || data[:Verb]).first
1012
+ term = SPARQL::Algebra::Expression(:reverse, term) if data[:reverse]
1013
+ input[:Path] = [term]
1014
+ end
1015
+
848
1016
  # [98] TriplesNode ::= Collection | BlankNodePropertyList
849
1017
  start_production(:TriplesNode) do |input, data, callback|
850
1018
  # Called after Verb. The prod_data stack should have Subject and Verb elements
@@ -855,6 +1023,17 @@ module SPARQL::Grammar
855
1023
  add_prod_datum(:TriplesNode, data[:TriplesNode])
856
1024
  end
857
1025
 
1026
+ # [100] TriplesNodePath ::= CollectionPath | BlankNodePropertyListPath
1027
+ start_production(:TriplesNodePath) do |input, data, callback|
1028
+ # Called after Verb. The prod_data stack should have Subject and Verb elements
1029
+ data[:TriplesNode] = bnode
1030
+ end
1031
+ production(:TriplesNodePath) do |input, data, callback|
1032
+ add_prod_datum(:pattern, data[:pattern])
1033
+ add_prod_datum(:path, data[:path])
1034
+ add_prod_datum(:TriplesNode, data[:TriplesNode])
1035
+ end
1036
+
858
1037
  # [102] Collection ::= '(' GraphNode+ ')'
859
1038
  start_production(:Collection) do |input, data, callback|
860
1039
  # Tells the TriplesNode production to collect and not generate statements
@@ -864,6 +1043,16 @@ module SPARQL::Grammar
864
1043
  expand_collection(data)
865
1044
  end
866
1045
 
1046
+ # [103] CollectionPath ::= "(" GraphNodePath+ ")"
1047
+ start_production(:CollectionPath) do |input, data, callback|
1048
+ # Tells the TriplesNode production to collect and not generate statements
1049
+ data[:Collection] = prod_data[:TriplesNode]
1050
+ end
1051
+ production(:CollectionPath) do |input, data, callback|
1052
+ expand_collection(data)
1053
+ add_prod_datum(:path, data[:path])
1054
+ end
1055
+
867
1056
  # [104] GraphNode ::= VarOrTerm | TriplesNode
868
1057
  production(:GraphNode) do |input, data, callback|
869
1058
  term = data[:VarOrTerm] || data[:TriplesNode]
@@ -871,6 +1060,14 @@ module SPARQL::Grammar
871
1060
  add_prod_datum(:GraphNode, term)
872
1061
  end
873
1062
 
1063
+ # [105] GraphNodePath ::= VarOrTerm | TriplesNodePath
1064
+ production(:GraphNodePath) do |input, data, callback|
1065
+ term = data[:VarOrTerm] || data[:TriplesNode]
1066
+ add_prod_datum(:pattern, data[:pattern])
1067
+ add_prod_datum(:path, data[:path])
1068
+ add_prod_datum(:GraphNode, term)
1069
+ end
1070
+
874
1071
  # [106] VarOrTerm ::= Var | GraphTerm
875
1072
  production(:VarOrTerm) do |input, data, callback|
876
1073
  data.values.each {|v| add_prod_datum(:VarOrTerm, v)}
@@ -986,7 +1183,7 @@ module SPARQL::Grammar
986
1183
 
987
1184
  # | ( NumericLiteralPositive | NumericLiteralNegative )
988
1185
  production(:_AdditiveExpression_7) do |input, data, callback|
989
- lit = data[:literal].first
1186
+ lit = data[:literal]
990
1187
  val = lit.to_s
991
1188
  op, val = val[0,1], val[1..-1]
992
1189
  add_prod_datum(:AdditiveExpression, op)
@@ -1106,19 +1303,18 @@ module SPARQL::Grammar
1106
1303
  # | ExistsFunc
1107
1304
  # | NotExistsFunc
1108
1305
  production(:BuiltInCall) do |input, data, callback|
1109
- if builtin = data.keys.detect {|k| BUILTINS.include?(k)}
1110
- add_prod_datum(:BuiltInCall,
1111
- SPARQL::Algebra::Expression.for(
1112
- (data[:ExpressionList] || data[:Expression] || []).
1113
- unshift(builtin)))
1306
+ input[:BuiltInCall] = if builtin = data.keys.detect {|k| BUILTINS.include?(k)}
1307
+ SPARQL::Algebra::Expression.for(
1308
+ (data[:ExpressionList] || data[:Expression] || []).
1309
+ unshift(builtin))
1114
1310
  elsif builtin_rule = data.keys.detect {|k| BUILTIN_RULES.include?(k)}
1115
- add_prod_datum(:BuiltInCall, SPARQL::Algebra::Expression.for(data[builtin_rule].unshift(builtin_rule)))
1311
+ SPARQL::Algebra::Expression.for(data[builtin_rule].unshift(builtin_rule))
1116
1312
  elsif aggregate_rule = data.keys.detect {|k| AGGREGATE_RULES.include?(k)}
1117
- add_prod_datum(:BuiltInCall, data[aggregate_rule].first)
1313
+ data[aggregate_rule].first
1118
1314
  elsif data[:bound]
1119
- add_prod_datum(:BuiltInCall, SPARQL::Algebra::Expression.for(data[:Var].unshift(:bound)))
1315
+ SPARQL::Algebra::Expression.for(data[:Var].unshift(:bound))
1120
1316
  elsif data[:BuiltInCall]
1121
- add_prod_datum(:BuiltInCall, SPARQL::Algebra::Expression.for(data[:BuiltInCall] + data[:Expression]))
1317
+ SPARQL::Algebra::Expression.for(data[:BuiltInCall] + data[:Expression])
1122
1318
  end
1123
1319
  end
1124
1320
 
@@ -1164,7 +1360,7 @@ module SPARQL::Grammar
1164
1360
  production(:Aggregate) do |input, data, callback|
1165
1361
  if aggregate_rule = data.keys.detect {|k| AGGREGATE_RULES.include?(k)}
1166
1362
  parts = [aggregate_rule]
1167
- parts << [:separator, RDF::Literal(data[:string].first)] if data[:separator] && data[:string]
1363
+ parts << [:separator, RDF::Literal(data[:string])] if data[:separator] && data[:string]
1168
1364
  parts << :distinct if data[:DISTINCT_REDUCED]
1169
1365
  parts << data[:Expression].first if data[:Expression]
1170
1366
  add_prod_data(aggregate_rule, SPARQL::Algebra::Expression.for(parts))
@@ -1175,9 +1371,9 @@ module SPARQL::Grammar
1175
1371
  production(:iriOrFunction) do |input, data, callback|
1176
1372
  if data.has_key?(:ArgList)
1177
1373
  # Function is (func arg1 arg2 ...)
1178
- add_prod_data(:Function, data[:iri] + data[:ArgList])
1374
+ add_prod_data(:Function, Array(data[:iri]) + data[:ArgList])
1179
1375
  else
1180
- add_prod_datum(:iri, data[:iri])
1376
+ input[:iri] = data[:iri]
1181
1377
  end
1182
1378
  end
1183
1379
 
@@ -1185,10 +1381,10 @@ module SPARQL::Grammar
1185
1381
  production(:RDFLiteral) do |input, data, callback|
1186
1382
  if data[:string]
1187
1383
  lit = data.dup
1188
- str = lit.delete(:string).last
1189
- lit[:datatype] = lit.delete(:iri).last if lit[:iri]
1384
+ str = lit.delete(:string)
1385
+ lit[:datatype] = lit.delete(:iri) if lit[:iri]
1190
1386
  lit[:language] = lit.delete(:language).last.downcase if lit[:language]
1191
- add_prod_datum(:literal, RDF::Literal.new(str, lit)) if str
1387
+ input[:literal] = RDF::Literal.new(str, lit) if str
1192
1388
  end
1193
1389
  end
1194
1390
 
@@ -1197,7 +1393,7 @@ module SPARQL::Grammar
1197
1393
  # | DOUBLE_POSITIVE
1198
1394
  production(:NumericLiteralPositive) do |input, data, callback|
1199
1395
  num = data.values.flatten.last
1200
- add_prod_datum(:literal, num)
1396
+ input[:literal] = num
1201
1397
 
1202
1398
  # Keep track of this for parent UnaryExpression production
1203
1399
  add_prod_datum(:UnaryExpression, data[:UnaryExpression])
@@ -1208,17 +1404,12 @@ module SPARQL::Grammar
1208
1404
  # | DOUBLE_NEGATIVE
1209
1405
  production(:NumericLiteralNegative) do |input, data, callback|
1210
1406
  num = data.values.flatten.last
1211
- add_prod_datum(:literal, num)
1407
+ input[:literal] = num
1212
1408
 
1213
1409
  # Keep track of this for parent UnaryExpression production
1214
1410
  add_prod_datum(:UnaryExpression, data[:UnaryExpression])
1215
1411
  end
1216
1412
 
1217
- # [137] PrefixedName ::= PNAME_LN | PNAME_NS
1218
- production(:PrefixedName) do |input, data, callback|
1219
- add_prod_datum(:iri, data[:PrefixedName])
1220
- end
1221
-
1222
1413
  ##
1223
1414
  # Initializes a new parser instance.
1224
1415
  #
@@ -1318,10 +1509,10 @@ module SPARQL::Grammar
1318
1509
  level, lineno, depth, *args = data
1319
1510
  message = args.to_sse
1320
1511
  d_str = depth > 100 ? ' ' * 100 + '+' : ' ' * depth
1321
- str = "[#{lineno}](#{level})#{d_str}#{message}"
1512
+ str = "[#{lineno}](#{level})#{d_str}#{message}".chop
1322
1513
  case @options[:debug]
1323
1514
  when Array
1324
- @options[:debug] << str
1515
+ @options[:debug] << str unless level > 2
1325
1516
  when TrueClass
1326
1517
  $stderr.puts str
1327
1518
  when Integer
@@ -1337,13 +1528,17 @@ module SPARQL::Grammar
1337
1528
  when prod_data.empty?
1338
1529
  nil
1339
1530
  when prod_data[:query]
1340
- prod_data[:query].to_a.length == 1 ? prod_data[:query].first : prod_data[:query]
1531
+ Array(prod_data[:query]).length == 1 ? prod_data[:query].first : prod_data[:query]
1341
1532
  when prod_data[:update]
1342
1533
  prod_data[:update]
1343
1534
  else
1344
1535
  key = prod_data.keys.first
1345
1536
  [key] + Array(prod_data[key]) # Creates [:key, [:triple], ...]
1346
1537
  end
1538
+
1539
+ # Validate resulting expression
1540
+ @result.validate! if @result && validate?
1541
+ @result
1347
1542
  end
1348
1543
 
1349
1544
  private
@@ -1539,7 +1734,7 @@ module SPARQL::Grammar
1539
1734
 
1540
1735
  # Create list items for each element in data[:GraphNode]
1541
1736
  first = data[:Collection]
1542
- list = data[:GraphNode].to_a.flatten.compact
1737
+ list = Array(data[:GraphNode]).flatten.compact
1543
1738
  last = list.pop
1544
1739
 
1545
1740
  list.each do |r|
@@ -1560,7 +1755,6 @@ module SPARQL::Grammar
1560
1755
  # @param [String] production Production generating pattern
1561
1756
  # @param [Hash{Symbol => Object}] options
1562
1757
  def add_pattern(production, options)
1563
- progress(production, "add_pattern: #{options.inspect}")
1564
1758
  progress(production, "[:pattern, #{options[:subject]}, #{options[:predicate]}, #{options[:object]}]")
1565
1759
  triple = {}
1566
1760
  options.each_pair do |r, v|
@@ -1681,7 +1875,7 @@ module SPARQL::Grammar
1681
1875
 
1682
1876
  query = SPARQL::Algebra::Expression[:project, vars, query] unless vars.empty?
1683
1877
 
1684
- query = SPARQL::Algebra::Expression[data[:DISTINCT_REDUCED].first, query] if data[:DISTINCT_REDUCED]
1878
+ query = SPARQL::Algebra::Expression[data[:DISTINCT_REDUCED], query] if data[:DISTINCT_REDUCED]
1685
1879
 
1686
1880
  query = SPARQL::Algebra::Expression[:slice, data[:slice][0], data[:slice][1], query] if data[:slice]
1687
1881