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