sparql 1.1.6 → 1.1.7

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