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.
- checksums.yaml +4 -4
- data/README.md +4 -6
- data/VERSION +1 -1
- data/lib/sparql/algebra/expression.rb +28 -2
- data/lib/sparql/algebra/extensions.rb +73 -0
- data/lib/sparql/algebra/operator.rb +73 -9
- data/lib/sparql/algebra/operator/alt.rb +58 -0
- data/lib/sparql/algebra/operator/extend.rb +15 -3
- data/lib/sparql/algebra/operator/filter.rb +18 -1
- data/lib/sparql/algebra/operator/group.rb +22 -1
- data/lib/sparql/algebra/operator/join.rb +16 -5
- data/lib/sparql/algebra/operator/left_join.rb +12 -1
- data/lib/sparql/algebra/operator/notin.rb +1 -1
- data/lib/sparql/algebra/operator/notoneof.rb +52 -0
- data/lib/sparql/algebra/operator/path.rb +49 -0
- data/lib/sparql/algebra/operator/path_opt.rb +112 -0
- data/lib/sparql/algebra/operator/path_plus.rb +99 -0
- data/lib/sparql/algebra/operator/path_star.rb +42 -0
- data/lib/sparql/algebra/operator/reverse.rb +54 -0
- data/lib/sparql/algebra/operator/seq.rb +73 -0
- data/lib/sparql/algebra/operator/sequence.rb +63 -0
- data/lib/sparql/algebra/operator/union.rb +12 -1
- data/lib/sparql/algebra/query.rb +1 -0
- data/lib/sparql/grammar/meta.rb +4593 -4582
- data/lib/sparql/grammar/parser11.rb +301 -107
- metadata +13 -4
@@ -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
|
-
|
58
|
+
input[:BlankNode] = bnode
|
59
59
|
end
|
60
60
|
terminal(:NIL, NIL) do |prod, token, input|
|
61
|
-
|
61
|
+
input[:NIL] = RDF['nil']
|
62
62
|
end
|
63
63
|
terminal(:BLANK_NODE_LABEL, BLANK_NODE_LABEL) do |prod, token, input|
|
64
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
84
|
+
input[:literal] = literal(value, datatype: RDF::XSD.decimal)
|
85
85
|
end
|
86
86
|
terminal(:INTEGER_POSITIVE, INTEGER_POSITIVE) do |prod, token, input|
|
87
|
-
|
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
|
-
|
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
|
-
|
100
|
+
input[:literal] = literal(value, datatype: RDF::XSD.decimal)
|
101
101
|
end
|
102
102
|
terminal(:INTEGER_NEGATIVE, INTEGER_NEGATIVE) do |prod, token, input|
|
103
|
-
|
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
|
-
|
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
|
-
|
116
|
+
input[:literal] = literal(value, datatype: RDF::XSD.decimal)
|
117
117
|
end
|
118
118
|
terminal(:INTEGER, INTEGER) do |prod, token, input|
|
119
|
-
|
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
|
-
|
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
|
-
|
132
|
-
|
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
|
-
|
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
|
-
|
138
|
+
input[:string] = token.value[3..-4]
|
140
139
|
end
|
141
140
|
terminal(:STRING_LITERAL1, STRING_LITERAL1, unescape: true) do |prod, token, input|
|
142
|
-
|
141
|
+
input[:string] = token.value[1..-2]
|
143
142
|
end
|
144
143
|
terminal(:STRING_LITERAL2, STRING_LITERAL2, unescape: true) do |prod, token, input|
|
145
|
-
|
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
|
173
|
-
when /true|false/ then
|
174
|
-
when /ASC|DESC/ then
|
175
|
-
when /DISTINCT|REDUCED/ then
|
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]
|
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]
|
233
|
-
self.prefix(pfx, data[:iri]
|
234
|
-
prefix_op = SPARQL::Algebra::Operator::Prefix.new([["#{pfx}:".to_sym, data[:iri]
|
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
|
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
|
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
|
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]
|
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
|
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].
|
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
|
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]
|
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]
|
527
|
+
add_prod_data(:using, data[:iri])
|
522
528
|
end
|
523
529
|
production(:_UsingClause_2) do |input, data, callback|
|
524
|
-
|
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]
|
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
|
-
|
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
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
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[:
|
693
|
+
if data[:nilrow]
|
688
694
|
add_prod_data :row, [:row]
|
689
695
|
else
|
690
|
-
data[:
|
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
|
-
#
|
701
|
-
production(:
|
702
|
-
|
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].
|
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].
|
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].
|
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
|
-
|
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
|
-
|
819
|
-
|
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
|
-
# [
|
824
|
-
production(:
|
825
|
-
data
|
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]
|
829
|
-
start_production(:
|
830
|
-
subject = input[:VarOrTerm]
|
831
|
-
error(nil, "Expected VarOrTerm", production:
|
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(:
|
835
|
-
|
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
|
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]
|
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
|
-
|
1111
|
-
|
1112
|
-
|
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
|
-
|
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
|
-
|
1313
|
+
data[aggregate_rule].first
|
1118
1314
|
elsif data[:bound]
|
1119
|
-
|
1315
|
+
SPARQL::Algebra::Expression.for(data[:Var].unshift(:bound))
|
1120
1316
|
elsif data[:BuiltInCall]
|
1121
|
-
|
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]
|
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
|
-
|
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)
|
1189
|
-
lit[:datatype] = lit.delete(: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
|
-
|
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
|
-
|
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
|
-
|
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].
|
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].
|
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]
|
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
|
|