sparql 3.3.1 → 3.3.2
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 +13 -15
- data/VERSION +1 -1
- data/bin/sparql +33 -24
- data/lib/sparql/algebra/aggregate.rb +1 -1
- data/lib/sparql/algebra/expression.rb +2 -2
- data/lib/sparql/algebra/extensions.rb +29 -2
- data/lib/sparql/algebra/operator/bgp.rb +7 -3
- data/lib/sparql/algebra/operator/group_concat.rb +5 -1
- data/lib/sparql/algebra/operator/join.rb +11 -5
- data/lib/sparql/algebra/operator/left_join.rb +13 -12
- data/lib/sparql/algebra/operator/minus.rb +1 -1
- data/lib/sparql/algebra/operator/path.rb +38 -0
- data/lib/sparql/algebra/operator/regex.rb +41 -3
- data/lib/sparql/algebra/operator/table.rb +1 -1
- data/lib/sparql/algebra/operator/union.rb +1 -1
- data/lib/sparql/algebra/operator.rb +8 -0
- data/lib/sparql/algebra.rb +5 -1
- data/lib/sparql/grammar/meta.rb +568 -51294
- data/lib/sparql/grammar/meta11.rb +51297 -0
- data/lib/sparql/grammar/parser.rb +3115 -0
- data/lib/sparql/grammar/parser11.rb +3 -3
- data/lib/sparql/grammar/{terminals11.rb → terminals.rb} +11 -11
- data/lib/sparql/grammar.rb +33 -26
- data/lib/sparql/server.rb +15 -6
- data/lib/sparql.rb +6 -1
- metadata +105 -53
@@ -0,0 +1,3115 @@
|
|
1
|
+
require 'ebnf'
|
2
|
+
require 'ebnf/peg/parser'
|
3
|
+
require 'sparql/grammar/meta'
|
4
|
+
|
5
|
+
module SPARQL::Grammar
|
6
|
+
##
|
7
|
+
# A parser for the SPARQL 1.1 grammar.
|
8
|
+
#
|
9
|
+
# @see https://www.w3.org/TR/sparql11-query/#grammar
|
10
|
+
# @see https://en.wikipedia.org/wiki/LR_parser
|
11
|
+
class Parser
|
12
|
+
include SPARQL::Grammar::Meta
|
13
|
+
include SPARQL::Grammar::Terminals
|
14
|
+
include EBNF::PEG::Parser
|
15
|
+
|
16
|
+
##
|
17
|
+
# Any additional options for the parser.
|
18
|
+
#
|
19
|
+
# @return [Hash]
|
20
|
+
attr_reader :options
|
21
|
+
|
22
|
+
##
|
23
|
+
# The current input string being processed.
|
24
|
+
#
|
25
|
+
# @return [String]
|
26
|
+
attr_accessor :input
|
27
|
+
|
28
|
+
##
|
29
|
+
# The internal representation of the result using hierarchy of RDF objects and SPARQL::Algebra::Operator
|
30
|
+
# objects.
|
31
|
+
# @return [Array]
|
32
|
+
attr_accessor :result
|
33
|
+
|
34
|
+
# Terminals passed to lexer. Order matters!
|
35
|
+
terminal(:ANON, ANON) do |value, prod|
|
36
|
+
bnode
|
37
|
+
end
|
38
|
+
terminal(:NIL, NIL) do |value, prod|
|
39
|
+
RDF['nil']
|
40
|
+
end
|
41
|
+
terminal(:BLANK_NODE_LABEL, BLANK_NODE_LABEL) do |value, prod|
|
42
|
+
bnode(value[2..-1])
|
43
|
+
end
|
44
|
+
terminal(:IRIREF, IRIREF) do |value, prod|
|
45
|
+
begin
|
46
|
+
iri(value[1..-2])
|
47
|
+
rescue ArgumentError => e
|
48
|
+
raise Error, e.message
|
49
|
+
end
|
50
|
+
end
|
51
|
+
terminal(:DOUBLE_POSITIVE, DOUBLE_POSITIVE) do |value, prod|
|
52
|
+
# Note that a Turtle Double may begin with a '.[eE]', so tack on a leading
|
53
|
+
# zero if necessary
|
54
|
+
value = value.sub(/\.([eE])/, '.0\1')
|
55
|
+
literal(value, datatype: RDF::XSD.double)
|
56
|
+
end
|
57
|
+
terminal(:DECIMAL_POSITIVE, DECIMAL_POSITIVE) do |value, prod|
|
58
|
+
# Note that a Turtle Decimal may begin with a '.', so tack on a leading
|
59
|
+
# zero if necessary
|
60
|
+
value = "0#{value}" if value[0,1] == "."
|
61
|
+
literal(value, datatype: RDF::XSD.decimal)
|
62
|
+
end
|
63
|
+
terminal(:INTEGER_POSITIVE, INTEGER_POSITIVE) do |value, prod|
|
64
|
+
literal(value, datatype: RDF::XSD.integer)
|
65
|
+
end
|
66
|
+
terminal(:DOUBLE_NEGATIVE, DOUBLE_NEGATIVE) do |value, prod|
|
67
|
+
# Note that a Turtle Double may begin with a '.[eE]', so tack on a leading
|
68
|
+
# zero if necessary
|
69
|
+
value = value.sub(/\.([eE])/, '.0\1')
|
70
|
+
literal(value, datatype: RDF::XSD.double)
|
71
|
+
end
|
72
|
+
terminal(:DECIMAL_NEGATIVE, DECIMAL_NEGATIVE) do |value, prod|
|
73
|
+
# Note that a Turtle Decimal may begin with a '.', so tack on a leading
|
74
|
+
# zero if necessary
|
75
|
+
value = "0#{value}" if value[0,1] == "."
|
76
|
+
literal(value, datatype: RDF::XSD.decimal)
|
77
|
+
end
|
78
|
+
terminal(:INTEGER_NEGATIVE, INTEGER_NEGATIVE) do |value, prod|
|
79
|
+
literal(value, datatype: RDF::XSD.integer)
|
80
|
+
end
|
81
|
+
terminal(:DOUBLE, DOUBLE) do |value, prod|
|
82
|
+
# Note that a Turtle Double may begin with a '.[eE]', so tack on a leading
|
83
|
+
# zero if necessary
|
84
|
+
value = value.sub(/\.([eE])/, '.0\1')
|
85
|
+
literal(value, datatype: RDF::XSD.double)
|
86
|
+
end
|
87
|
+
terminal(:DECIMAL, DECIMAL) do |value, prod|
|
88
|
+
# Note that a Turtle Decimal may begin with a '.', so tack on a leading
|
89
|
+
# zero if necessary
|
90
|
+
value = value
|
91
|
+
#value = "0#{value}" if value[0,1] == "."
|
92
|
+
literal(value, datatype: RDF::XSD.decimal)
|
93
|
+
end
|
94
|
+
terminal(:INTEGER, INTEGER) do |value, prod|
|
95
|
+
literal(value, datatype: RDF::XSD.integer)
|
96
|
+
end
|
97
|
+
terminal(:LANG_DIR, LANG_DIR) do |value, prod|
|
98
|
+
value[1..-1]
|
99
|
+
end
|
100
|
+
terminal(:PNAME_LN, PNAME_LN, unescape: true) do |value, prod|
|
101
|
+
prefix, suffix = value.split(":", 2)
|
102
|
+
ns(prefix, suffix)
|
103
|
+
end
|
104
|
+
terminal(:PNAME_NS, PNAME_NS) do |value, prod|
|
105
|
+
value[0..-2].to_sym
|
106
|
+
end
|
107
|
+
terminal(:STRING_LITERAL_LONG1, STRING_LITERAL_LONG1, unescape: true) do |value, prod|
|
108
|
+
value[3..-4]
|
109
|
+
end
|
110
|
+
terminal(:STRING_LITERAL_LONG2, STRING_LITERAL_LONG2, unescape: true) do |value, prod|
|
111
|
+
value[3..-4]
|
112
|
+
end
|
113
|
+
terminal(:STRING_LITERAL1, STRING_LITERAL1, unescape: true) do |value, prod|
|
114
|
+
value[1..-2]
|
115
|
+
end
|
116
|
+
terminal(:STRING_LITERAL2, STRING_LITERAL2, unescape: true) do |value, prod|
|
117
|
+
value[1..-2]
|
118
|
+
end
|
119
|
+
terminal(:VAR1, VAR1) do |value, prod|
|
120
|
+
variable(value[1..-1])
|
121
|
+
end
|
122
|
+
terminal(:VAR2, VAR2) do |value, prod|
|
123
|
+
variable(value[1..-1])
|
124
|
+
end
|
125
|
+
|
126
|
+
# Productions
|
127
|
+
|
128
|
+
# Query ::= Prologue ( SelectQuery | ConstructQuery | DescribeQuery | AskQuery )
|
129
|
+
#
|
130
|
+
# Inputs from value include :Prologe and :_Query_1
|
131
|
+
# Result is query
|
132
|
+
start_production(:Query, as_hash: true)
|
133
|
+
production(:Query) do |value|
|
134
|
+
query = value[:_Query_1]
|
135
|
+
prologue = value[:Prologue] || {PrefixDecl: []}
|
136
|
+
|
137
|
+
# Add prefix
|
138
|
+
unless prologue[:PrefixDecl].empty?
|
139
|
+
pfx = prologue[:PrefixDecl].shift
|
140
|
+
prologue[:PrefixDecl].each {|p| pfx.merge!(p)}
|
141
|
+
pfx.operands[1] = query
|
142
|
+
query = pfx
|
143
|
+
end
|
144
|
+
|
145
|
+
# Add base
|
146
|
+
query = SPARQL::Algebra::Expression[:base, prologue[:BaseDecl], query] if prologue[:BaseDecl]
|
147
|
+
|
148
|
+
query
|
149
|
+
end
|
150
|
+
|
151
|
+
# UpdateUnit ::= Update
|
152
|
+
#
|
153
|
+
# Result is update
|
154
|
+
start_production(:UpdateUnit, as_hash: true)
|
155
|
+
production(:UpdateUnit) do |value|
|
156
|
+
value[:Update]
|
157
|
+
end
|
158
|
+
|
159
|
+
# Prologue ::= ( BaseDecl | PrefixDecl )*
|
160
|
+
#
|
161
|
+
# Inputs from value include :BaseDecl and :PrefixDecl
|
162
|
+
# Result is hash including BaseDecl and PrefixDecl
|
163
|
+
production(:Prologue) do |value|
|
164
|
+
unless resolve_iris?
|
165
|
+
# Only output if we're not resolving URIs internally
|
166
|
+
{
|
167
|
+
BaseDecl: value.map {|v| v[:BaseDecl]}.compact.last,
|
168
|
+
PrefixDecl: value.map {|v| v[:PrefixDecl]}.compact
|
169
|
+
}.compact
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# BaseDecl ::= 'BASE' IRIREF
|
174
|
+
#
|
175
|
+
# Inputs from value includes :IRIREF
|
176
|
+
# Result is hash including BaseDecl, unless we are resolving IRIs
|
177
|
+
start_production(:BaseDecl, as_hash: true, insensitive_srings: :upper)
|
178
|
+
production(:BaseDecl) do |value|
|
179
|
+
iri = value[:IRIREF]
|
180
|
+
debug("BaseDecl") {"Defined base as #{iri}"}
|
181
|
+
self.base_uri = iri(iri)
|
182
|
+
resolve_iris? || {BaseDecl: iri}
|
183
|
+
end
|
184
|
+
|
185
|
+
# PrefixDecl ::= 'PREFIX' PNAME_NS IRIREF
|
186
|
+
#
|
187
|
+
# Inputs from value include :PNAME_NS and :IRIREF
|
188
|
+
# Result is hash including PrefixDecl
|
189
|
+
start_production(:PrefixDecl, as_hash: true, insensitive_srings: :upper)
|
190
|
+
production(:PrefixDecl) do |value|
|
191
|
+
pfx = value[:PNAME_NS]
|
192
|
+
self.prefix(pfx, value[:IRIREF])
|
193
|
+
prefix_op = SPARQL::Algebra::Operator::Prefix.new([["#{pfx}:".to_sym, value[:IRIREF]]], [])
|
194
|
+
{PrefixDecl: prefix_op}
|
195
|
+
end
|
196
|
+
|
197
|
+
# SelectQuery ::= SelectClause DatasetClause* WhereClause SolutionModifier ValuesClause
|
198
|
+
#
|
199
|
+
# Inputs are dataset, query, values, solution modifiers, vars, and extensions.
|
200
|
+
# Result is a query
|
201
|
+
start_production(:SelectQuery, as_hash: true)
|
202
|
+
production(:SelectQuery) do |value|
|
203
|
+
modifiers = {
|
204
|
+
dataset: value[:_SelectQuery_1],
|
205
|
+
query: value[:WhereClause][:query],
|
206
|
+
values: value[:ValuesClause],
|
207
|
+
}.merge(value[:SolutionModifier]).merge(value[:SelectClause])
|
208
|
+
merge_modifiers(modifiers)
|
209
|
+
end
|
210
|
+
|
211
|
+
# SubSelect ::= SelectClause WhereClause SolutionModifier
|
212
|
+
#
|
213
|
+
# Inputs are query, solution modifiers, vars, and extensions.
|
214
|
+
# Result is a hash including query.
|
215
|
+
start_production(:SubSelect, as_hash: true)
|
216
|
+
production(:SubSelect) do |value|
|
217
|
+
modifiers = value[:WhereClause].merge(value[:SolutionModifier]).merge(value[:SelectClause])
|
218
|
+
query = merge_modifiers(modifiers)
|
219
|
+
{query: query}
|
220
|
+
end
|
221
|
+
|
222
|
+
# SelectClause ::= 'SELECT' ( 'DISTINCT' | 'REDUCED' )? ( ( Var | ( '(' Expression 'AS' Var ')' ) )+ | '*' )
|
223
|
+
#
|
224
|
+
# (rule SelectClause (seq 'SELECT' _SelectClause_1 _SelectClause_2))
|
225
|
+
# (rule _SelectClause_1 (opt _SelectClause_3))
|
226
|
+
# (rule _SelectClause_3 (alt 'DISTINCT' 'REDUCED'))
|
227
|
+
# (rule _SelectClause_2 (alt _SelectClause_4 '*'))
|
228
|
+
# (rule _SelectClause_4 (plus _SelectClause_5))
|
229
|
+
# (rule _SelectClause_5 (alt Var _SelectClause_6))
|
230
|
+
# (rule _SelectClause_6 (seq '(' Expression 'AS' Var ')'))
|
231
|
+
#
|
232
|
+
# Inputs from value includes :_SelectClause_2 (a list of :variables and extensions).
|
233
|
+
# Result is a hash including distinct/reduced, vars and extensions.
|
234
|
+
start_production(:SelectClause, as_hash: true)
|
235
|
+
production(:SelectClause) do |value|
|
236
|
+
res = {
|
237
|
+
DISTINCT_REDUCED: value[:_SelectClause_1]
|
238
|
+
}
|
239
|
+
|
240
|
+
sc2 = Array(value[:_SelectClause_2])
|
241
|
+
sc2.each do |expr|
|
242
|
+
if expr == '*'
|
243
|
+
res[:Var] = %w(*)
|
244
|
+
elsif expr.is_a?(RDF::Query::Variable)
|
245
|
+
(res[:Var] ||= []) << expr
|
246
|
+
elsif expr.is_a?(Hash) && expr[:extend]
|
247
|
+
(res[:extend] ||= []) << expr[:extend]
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
res
|
252
|
+
end
|
253
|
+
|
254
|
+
# (rule _SelectClause_6 (seq '(' Expression 'AS' Var ')'))
|
255
|
+
start_production(:_SelectClause_6, as_hash: true)
|
256
|
+
production(:_SelectClause_6) do |value|
|
257
|
+
{extend: [value[:Var], value[:Expression]]}
|
258
|
+
end
|
259
|
+
|
260
|
+
# ConstructQuery ::= 'CONSTRUCT'
|
261
|
+
# ( ConstructTemplate
|
262
|
+
# DatasetClause*
|
263
|
+
# WhereClause
|
264
|
+
# SolutionModifier | DatasetClause*
|
265
|
+
# 'WHERE' '{' TriplesTemplate? '}'
|
266
|
+
# SolutionModifier
|
267
|
+
# )
|
268
|
+
# ValuesClause
|
269
|
+
#
|
270
|
+
# (rule ConstructQuery (seq 'CONSTRUCT' _ConstructQuery_1 ValuesClause))
|
271
|
+
# (rule _ConstructQuery_1 (alt _ConstructQuery_2 _ConstructQuery_3))
|
272
|
+
# (rule _ConstructQuery_2
|
273
|
+
# (seq ConstructTemplate _ConstructQuery_4 WhereClause SolutionModifier))
|
274
|
+
# (rule _ConstructQuery_4 (star DatasetClause))
|
275
|
+
# (rule _ConstructQuery_3
|
276
|
+
# (seq _ConstructQuery_5 'WHERE' '{' _ConstructQuery_6 '}' SolutionModifier))
|
277
|
+
# (rule _ConstructQuery_5 (star DatasetClause))
|
278
|
+
# (rule _ConstructQuery_6 (opt TriplesTemplate))
|
279
|
+
#
|
280
|
+
# Inputs from value includes :_ConstructQuery_1 (query modifiers) and :ValuesClause.
|
281
|
+
# Result is a query
|
282
|
+
start_production(:ConstructQuery, as_hash: true)
|
283
|
+
production(:ConstructQuery) do |value|
|
284
|
+
modifiers = value[:_ConstructQuery_1].merge(values: value[:ValuesClause])
|
285
|
+
template = modifiers.delete(:template) || []
|
286
|
+
query = merge_modifiers(modifiers)
|
287
|
+
SPARQL::Algebra::Expression[:construct, template, query]
|
288
|
+
end
|
289
|
+
|
290
|
+
# (rule _ConstructQuery_2
|
291
|
+
# (seq ConstructTemplate _ConstructQuery_4 WhereClause SolutionModifier))
|
292
|
+
start_production(:_ConstructQuery_2, as_hash: true)
|
293
|
+
production(:_ConstructQuery_2) do |value|
|
294
|
+
{
|
295
|
+
template: value[:ConstructTemplate],
|
296
|
+
dataset: value[:_ConstructQuery_4],
|
297
|
+
query: value[:WhereClause][:query]
|
298
|
+
}.merge(value[:SolutionModifier])
|
299
|
+
end
|
300
|
+
|
301
|
+
# (rule _ConstructQuery_3
|
302
|
+
# (seq _ConstructQuery_5 'WHERE' '{' _ConstructQuery_6 '}'
|
303
|
+
start_production(:_ConstructQuery_3, as_hash: true)
|
304
|
+
production(:_ConstructQuery_3) do |value|
|
305
|
+
{
|
306
|
+
template: value[:_ConstructQuery_6],
|
307
|
+
dataset: value[:_ConstructQuery_5],
|
308
|
+
query: SPARQL::Algebra::Operator::BGP.new(*value[:_ConstructQuery_6])
|
309
|
+
}.merge(value[:SolutionModifier])
|
310
|
+
end
|
311
|
+
|
312
|
+
# DescribeQuery ::= 'DESCRIBE' ( VarOrIri+ | '*' )
|
313
|
+
# DatasetClause* WhereClause? SolutionModifier ValuesClause
|
314
|
+
#
|
315
|
+
# Inputs from value includes dataset, query, values, and other merge modifiers.
|
316
|
+
# Result is a query
|
317
|
+
start_production(:DescribeQuery, as_hash: true)
|
318
|
+
production(:DescribeQuery) do |value|
|
319
|
+
modifiers = {
|
320
|
+
dataset: value[:_DescribeQuery_2],
|
321
|
+
query: value&.dig(:_DescribeQuery_3, :query),
|
322
|
+
values: value[:ValuesClause]
|
323
|
+
}.merge(value[:SolutionModifier])
|
324
|
+
query = merge_modifiers(modifiers)
|
325
|
+
to_describe = Array(value[:_DescribeQuery_1]).reject {|v| v == '*'}
|
326
|
+
SPARQL::Algebra::Expression[:describe, to_describe, query]
|
327
|
+
end
|
328
|
+
|
329
|
+
# AskQuery ::= 'ASK' DatasetClause* WhereClause ValuesClause
|
330
|
+
#
|
331
|
+
# Inputs from value includes dataset, query, values, and other merge modifiers.
|
332
|
+
# Result is a query
|
333
|
+
start_production(:AskQuery, as_hash: true)
|
334
|
+
production(:AskQuery) do |value|
|
335
|
+
modifiers = {
|
336
|
+
dataset: value[:_AskQuery_1],
|
337
|
+
query: value&.dig(:WhereClause, :query),
|
338
|
+
values: value[:ValuesClause]
|
339
|
+
}.merge(value[:SolutionModifier])
|
340
|
+
SPARQL::Algebra::Operator::Ask.new(merge_modifiers(modifiers))
|
341
|
+
end
|
342
|
+
|
343
|
+
# DatasetClause ::= 'FROM' ( DefaultGraphClause | NamedGraphClause )
|
344
|
+
start_production(:DatasetClause, as_hash: true, insenstive_strings: true)
|
345
|
+
production(:DatasetClause) do |value|
|
346
|
+
value[:_DatasetClause_1]
|
347
|
+
end
|
348
|
+
|
349
|
+
# DefaultGraphClause ::= SourceSelector
|
350
|
+
#
|
351
|
+
# Output is the source selector
|
352
|
+
production(:DefaultGraphClause) do |value|
|
353
|
+
value.first[:SourceSelector]
|
354
|
+
end
|
355
|
+
|
356
|
+
# NamedGraphClause ::= 'NAMED' SourceSelector
|
357
|
+
#
|
358
|
+
# Output is the named source selector.
|
359
|
+
start_production(:NamedGraphClause, as_hash: true)
|
360
|
+
production(:NamedGraphClause) do |value|
|
361
|
+
[:named, value[:SourceSelector]]
|
362
|
+
end
|
363
|
+
|
364
|
+
# SourceSelector ::= iri
|
365
|
+
production(:SourceSelector) do |value|
|
366
|
+
value.first[:iri]
|
367
|
+
end
|
368
|
+
|
369
|
+
# WhereClause ::= 'WHERE'? GroupGraphPattern
|
370
|
+
start_production(:WhereClause, as_hash: true)
|
371
|
+
production(:WhereClause) do |value|
|
372
|
+
{query: value&.dig(:GroupGraphPattern, :query)}
|
373
|
+
end
|
374
|
+
|
375
|
+
# SolutionModifier ::= GroupClause? HavingClause? OrderClause? LimitOffsetClauses?
|
376
|
+
#
|
377
|
+
# Result is a query modifier including group, having, order, and slice.
|
378
|
+
start_production(:SolutionModifier, as_hash: true)
|
379
|
+
production(:SolutionModifier) do |value|
|
380
|
+
{
|
381
|
+
group: value[:_SolutionModifier_1],
|
382
|
+
having: value[:_SolutionModifier_2],
|
383
|
+
order: value[:_SolutionModifier_3],
|
384
|
+
slice: value[:_SolutionModifier_4],
|
385
|
+
}
|
386
|
+
end
|
387
|
+
|
388
|
+
# GroupClause ::= 'GROUP' 'BY' GroupCondition+
|
389
|
+
#
|
390
|
+
# Returns one or more group conditions
|
391
|
+
start_production(:GroupClause, as_hash: true)
|
392
|
+
production(:GroupClause) do |value|
|
393
|
+
value[:_GroupClause_1]
|
394
|
+
end
|
395
|
+
|
396
|
+
# GroupCondition ::= BuiltInCall | FunctionCall
|
397
|
+
# | '(' Expression ( 'AS' Var )? ')' | Var
|
398
|
+
#
|
399
|
+
# (rule GroupCondition (alt BuiltInCall FunctionCall _GroupCondition_1 Var))
|
400
|
+
# (rule _GroupCondition_1 (seq '(' Expression _GroupCondition_2 ')'))
|
401
|
+
# (rule _GroupCondition_2 (opt _GroupCondition_3))
|
402
|
+
# (rule _GroupCondition_3 (seq 'AS' Var))
|
403
|
+
#
|
404
|
+
# Result is an expression
|
405
|
+
start_production(:GroupCondition, as_hash: true)
|
406
|
+
production(:GroupCondition) do |value|
|
407
|
+
value
|
408
|
+
end
|
409
|
+
|
410
|
+
# _GroupCondition_1 ::= '(' Expression ( 'AS' Var )? ')'
|
411
|
+
#
|
412
|
+
# (rule _GroupCondition_1 (seq '(' Expression _GroupCondition_2 ')'))
|
413
|
+
# (rule _GroupCondition_2 (opt _GroupCondition_3))
|
414
|
+
# (rule _GroupCondition_3 (seq 'AS' Var))
|
415
|
+
#
|
416
|
+
# Returns the expression, or an array of the var and expression.
|
417
|
+
start_production(:_GroupCondition_1, as_hash: true)
|
418
|
+
production(:_GroupCondition_1) do |value|
|
419
|
+
if value[:_GroupCondition_2]
|
420
|
+
[value[:_GroupCondition_2], value[:Expression]]
|
421
|
+
else
|
422
|
+
value[:Expression]
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
production(:_GroupCondition_3) {|value| value.last[:Var]}
|
427
|
+
|
428
|
+
# HavingClause ::= 'HAVING' HavingCondition+
|
429
|
+
#
|
430
|
+
# (rule HavingClause (seq 'HAVING' _HavingClause_1))
|
431
|
+
# (rule _HavingClause_1 (plus HavingCondition))
|
432
|
+
start_production(:HavingClause, as_hash: true)
|
433
|
+
production(:HavingClause) do |value|
|
434
|
+
value[:_HavingClause_1]
|
435
|
+
end
|
436
|
+
|
437
|
+
# HavingCondition ::= Constraint
|
438
|
+
start_production(:HavingCondition, as_hash: true)
|
439
|
+
production(:HavingCondition) do |value|
|
440
|
+
value[:Constraint]
|
441
|
+
end
|
442
|
+
|
443
|
+
# OrderClause ::= 'ORDER' 'BY' OrderCondition+
|
444
|
+
start_production(:OrderClause, as_hash: true)
|
445
|
+
production(:OrderClause) do |value|
|
446
|
+
value[:_OrderClause_1]
|
447
|
+
end
|
448
|
+
|
449
|
+
# OrderCondition ::= ( ( 'ASC' | 'DESC' ) BrackettedExpression ) | ( Constraint | Var )
|
450
|
+
#
|
451
|
+
# (rule OrderCondition (alt _OrderCondition_1 _OrderCondition_2))
|
452
|
+
# (rule _OrderCondition_1 (seq _OrderCondition_3 BrackettedExpression))
|
453
|
+
# (rule _OrderCondition_3 (alt 'ASC' 'DESC'))
|
454
|
+
# (rule _OrderCondition_2 (alt Constraint Var))
|
455
|
+
start_production(:OrderCondition, as_hash: true)
|
456
|
+
production(:OrderCondition) do |value|
|
457
|
+
if value.is_a?(Hash) && value[:_OrderCondition_3]
|
458
|
+
SPARQL::Algebra::Expression(value[:_OrderCondition_3].downcase, value[:BrackettedExpression])
|
459
|
+
else
|
460
|
+
value
|
461
|
+
end
|
462
|
+
end
|
463
|
+
start_production(:_OrderCondition_1, as_hash: true)
|
464
|
+
|
465
|
+
# LimitOffsetClauses ::= LimitClause OffsetClause? | OffsetClause LimitClause?
|
466
|
+
#
|
467
|
+
# (rule _LimitOffsetClauses_1 (seq LimitClause _LimitOffsetClauses_3))
|
468
|
+
# (rule _LimitOffsetClauses_3 (opt OffsetClause))
|
469
|
+
# (rule _LimitOffsetClauses_2 (seq OffsetClause _LimitOffsetClauses_4))
|
470
|
+
# (rule _LimitOffsetClauses_4 (opt LimitClause))
|
471
|
+
production(:LimitOffsetClauses) do |value|
|
472
|
+
if value[:LimitClause]
|
473
|
+
if value[:_LimitOffsetClauses_3]
|
474
|
+
[value[:_LimitOffsetClauses_3], value[:LimitClause]]
|
475
|
+
else
|
476
|
+
[:_, value[:LimitClause]]
|
477
|
+
end
|
478
|
+
else
|
479
|
+
if value[:_LimitOffsetClauses_4]
|
480
|
+
[value[:OffsetClause], value[:_LimitOffsetClauses_4]]
|
481
|
+
else
|
482
|
+
[value[:OffsetClause], :_]
|
483
|
+
end
|
484
|
+
end
|
485
|
+
end
|
486
|
+
start_production(:_LimitOffsetClauses_1, as_hash: true)
|
487
|
+
start_production(:_LimitOffsetClauses_2, as_hash: true)
|
488
|
+
|
489
|
+
# LimitClause ::= 'LIMIT' INTEGER
|
490
|
+
start_production(:LimitClause, as_hash: true)
|
491
|
+
production(:LimitClause) do |value|
|
492
|
+
value[:INTEGER]
|
493
|
+
end
|
494
|
+
|
495
|
+
# OffsetClause ::= 'OFFSET' INTEGER
|
496
|
+
start_production(:OffsetClause, as_hash: true)
|
497
|
+
production(:OffsetClause) do |value|
|
498
|
+
value[:INTEGER]
|
499
|
+
end
|
500
|
+
|
501
|
+
# ValuesClause ::= ( 'VALUES' DataBlock )?
|
502
|
+
#
|
503
|
+
# Result is a table operator
|
504
|
+
start_production(:ValuesClause, as_hash: true)
|
505
|
+
production(:ValuesClause) do |value|
|
506
|
+
debug("ValuesClause") {value.inspect}
|
507
|
+
if value
|
508
|
+
args = [Array(value[:DataBlock][:Var]).unshift(:vars)] + value[:DataBlock][:row]
|
509
|
+
table = SPARQL::Algebra::Expression.for(:table, *args)
|
510
|
+
table
|
511
|
+
end
|
512
|
+
end
|
513
|
+
|
514
|
+
# Update ::= Prologue (Update1 (";" Update)? )?
|
515
|
+
#
|
516
|
+
# (rule Update (seq Prologue _Update_1))
|
517
|
+
# (rule _Update_1 (opt _Update_2))
|
518
|
+
# (rule _Update_2 (seq Update1 _Update_3))
|
519
|
+
# (rule _Update_3 (opt _Update_4))
|
520
|
+
# (rule _Update_4 (seq ';' Update))
|
521
|
+
#
|
522
|
+
# Output is algebra Expression
|
523
|
+
start_production(:Update, as_hash: true)
|
524
|
+
production(:Update) do |value|
|
525
|
+
prologue = value[:Prologue] || {PrefixDecl: []}
|
526
|
+
update = value[:_Update_1] || SPARQL::Algebra::Expression(:update)
|
527
|
+
|
528
|
+
# Add prefix
|
529
|
+
unless prologue[:PrefixDecl].empty?
|
530
|
+
pfx = prologue[:PrefixDecl].shift
|
531
|
+
prologue[:PrefixDecl].each {|p| pfx.merge!(p)}
|
532
|
+
pfx.operands[1] = update
|
533
|
+
update = pfx
|
534
|
+
end
|
535
|
+
|
536
|
+
# Add base
|
537
|
+
update = SPARQL::Algebra::Expression[:base, prologue[:BaseDecl], update] if prologue[:BaseDecl]
|
538
|
+
update
|
539
|
+
end
|
540
|
+
|
541
|
+
# (rule _Update_2 (seq Update1 _Update_3))
|
542
|
+
#
|
543
|
+
# Merges update operators
|
544
|
+
#
|
545
|
+
# Returns an update operator
|
546
|
+
start_production(:_Update_2, as_hash: true)
|
547
|
+
production(:_Update_2) do |value|
|
548
|
+
if value[:_Update_3]
|
549
|
+
SPARQL::Algebra::Expression(:update, *(value[:Update1].operands + value[:_Update_3].operands))
|
550
|
+
else
|
551
|
+
value[:Update1]
|
552
|
+
end
|
553
|
+
end
|
554
|
+
|
555
|
+
# (rule _Update_4 (seq ';' Update))
|
556
|
+
production(:_Update_4) do |value|
|
557
|
+
value.last[:Update]
|
558
|
+
end
|
559
|
+
|
560
|
+
# Update1 ::= Load | Clear | Drop | Add | Move | Copy
|
561
|
+
# | Create | InsertData | DeleteData | DeleteWhere | Modify
|
562
|
+
#
|
563
|
+
# Output is SSE `(update ...)`
|
564
|
+
production(:Update1) do |value|
|
565
|
+
SPARQL::Algebra::Expression.for(:update, value)
|
566
|
+
end
|
567
|
+
|
568
|
+
# Load ::= "LOAD" "SILENT"? iri ("INTO" GraphRef)?
|
569
|
+
#
|
570
|
+
# (rule Load (seq 'LOAD' _Load_1 iri _Load_2))
|
571
|
+
# (rule _Load_1 (opt 'SILENT'))
|
572
|
+
# (rule _Load_2 (opt _Load_3))
|
573
|
+
# (rule _Load_3 (seq 'INTO' GraphRef))
|
574
|
+
start_production(:Load, as_hash: true)
|
575
|
+
production(:Load) do |value|
|
576
|
+
args = []
|
577
|
+
args << :silent if value[:_Load_1]
|
578
|
+
args << value[:iri]
|
579
|
+
args << value[:_Load_2].last[:GraphRef] if value[:_Load_2]
|
580
|
+
SPARQL::Algebra::Expression(:load, *args)
|
581
|
+
end
|
582
|
+
|
583
|
+
# Clear ::= "CLEAR" "SILENT"? GraphRefAll
|
584
|
+
start_production(:Clear, as_hash: true)
|
585
|
+
production(:Clear) do |value|
|
586
|
+
args = []
|
587
|
+
args << :silent if value[:_Clear_1]
|
588
|
+
args << (value[:GraphRefAll].is_a?(String) ? value[:GraphRefAll].downcase.to_sym : value[:GraphRefAll])
|
589
|
+
SPARQL::Algebra::Expression(:clear, *args)
|
590
|
+
end
|
591
|
+
|
592
|
+
# Drop ::= "DROP" "SILENT"? GraphRefAll
|
593
|
+
start_production(:Drop, as_hash: true)
|
594
|
+
production(:Drop) do |value|
|
595
|
+
args = []
|
596
|
+
args << :silent if value[:_Drop_1]
|
597
|
+
args << (value[:GraphRefAll].is_a?(String) ? value[:GraphRefAll].downcase.to_sym : value[:GraphRefAll])
|
598
|
+
SPARQL::Algebra::Expression(:drop, *args)
|
599
|
+
end
|
600
|
+
|
601
|
+
# Create ::= "CREATE" "SILENT"? GraphRef
|
602
|
+
start_production(:Create, as_hash: true)
|
603
|
+
production(:Create) do |value|
|
604
|
+
args = []
|
605
|
+
args << :silent if value[:_Create_1]
|
606
|
+
args << (value[:GraphRef].is_a?(String) ? value[:GraphRef].downcase.to_sym : value[:GraphRef])
|
607
|
+
SPARQL::Algebra::Expression(:create, *args)
|
608
|
+
end
|
609
|
+
|
610
|
+
# Add ::= "ADD" "SILENT"? GraphOrDefault "TO" GraphOrDefault
|
611
|
+
#
|
612
|
+
# Input is `GraphOrDefault` and optionally `:silent`.
|
613
|
+
# Output is an `Operator::Add` object.
|
614
|
+
production(:Add) do |value|
|
615
|
+
args = []
|
616
|
+
args << :silent if value[1][:_Add_1]
|
617
|
+
args << value[2][:GraphOrDefault]
|
618
|
+
args << value[4][:GraphOrDefault]
|
619
|
+
SPARQL::Algebra::Expression(:add, *args)
|
620
|
+
end
|
621
|
+
|
622
|
+
# Move ::= "MOVE" "SILENT"? GraphOrDefault "TO" GraphOrDefault
|
623
|
+
production(:Move) do |value|
|
624
|
+
args = []
|
625
|
+
args << :silent if value[1][:_Move_1]
|
626
|
+
args << value[2][:GraphOrDefault]
|
627
|
+
args << value[4][:GraphOrDefault]
|
628
|
+
SPARQL::Algebra::Expression(:move, *args)
|
629
|
+
end
|
630
|
+
|
631
|
+
# Copy ::= "COPY" "SILENT"? GraphOrDefault "TO" GraphOrDefault
|
632
|
+
production(:Copy) do |value|
|
633
|
+
args = []
|
634
|
+
args << :silent if value[1][:_Copy_1]
|
635
|
+
args << value[2][:GraphOrDefault]
|
636
|
+
args << value[4][:GraphOrDefault]
|
637
|
+
SPARQL::Algebra::Expression(:copy, *args)
|
638
|
+
end
|
639
|
+
|
640
|
+
# InsertData ::= "INSERT DATA" QuadData
|
641
|
+
#
|
642
|
+
# Freeze existing bnodes, so that if an attempt is made to re-use such a node, and error is raised
|
643
|
+
#
|
644
|
+
# Returns (insertData ...)
|
645
|
+
start_production(:InsertData, as_hash: true)
|
646
|
+
production(:InsertData) do |value|
|
647
|
+
SPARQL::Algebra::Expression(:insertData, value[:QuadData])
|
648
|
+
end
|
649
|
+
|
650
|
+
# DeleteData ::= "DELETE DATA" QuadData
|
651
|
+
# Generate BNodes instead of non-distinguished variables. BNodes are not legal, but this will generate them rather than non-distinguished variables so they can be detected.
|
652
|
+
start_production(:DeleteData, as_hash: true)
|
653
|
+
production(:DeleteData) do |value|
|
654
|
+
raise Error, "DeleteData contains BNode operands: #{value[:QuadData].to_sse}" if Array(value[:QuadData]).any?(&:node?)
|
655
|
+
SPARQL::Algebra::Expression(:deleteData, value[:QuadData])
|
656
|
+
end
|
657
|
+
|
658
|
+
# DeleteWhere ::= "DELETE WHERE" QuadPattern
|
659
|
+
# Generate BNodes instead of non-distinguished variables. BNodes are not legal, but this will generate them rather than non-distinguished variables so they can be detected.
|
660
|
+
start_production(:DeleteWhere, as_hash: true)
|
661
|
+
production(:DeleteWhere) do |value|
|
662
|
+
raise Error, "DeleteWhere contains BNode operands: #{value[:QuadPattern].to_sse}" if Array(value[:QuadPattern]).any?(&:node?)
|
663
|
+
SPARQL::Algebra::Expression(:deleteWhere, Array(value[:QuadPattern]))
|
664
|
+
end
|
665
|
+
|
666
|
+
#
|
667
|
+
# Modify::= ( 'WITH' iri )? ( DeleteClause InsertClause? | InsertClause ) UsingClause* 'WHERE' GroupGraphPattern
|
668
|
+
#
|
669
|
+
# (rule Modify (seq _Modify_1 _Modify_2 _Modify_3 'WHERE' GroupGraphPattern))
|
670
|
+
# (rule _Modify_1 (opt _Modify_4))
|
671
|
+
# (rule _Modify_4 (seq 'WITH' iri))
|
672
|
+
# (rule _Modify_2 (alt _Modify_5 InsertClause))
|
673
|
+
# (rule _Modify_5 (seq DeleteClause _Modify_6))
|
674
|
+
# (rule _Modify_6 (opt InsertClause))
|
675
|
+
# (rule _Modify_3 (star UsingClause))
|
676
|
+
#
|
677
|
+
# Returns modify operand
|
678
|
+
start_production(:Modify, as_hash: true)
|
679
|
+
production(:Modify) do |value|
|
680
|
+
query = value&.dig(:GroupGraphPattern, :query)
|
681
|
+
query = SPARQL::Algebra::Expression.for(:using, value[:_Modify_3], query) unless value[:_Modify_3].empty?
|
682
|
+
operands = [query, *Array(value[:_Modify_2])].compact
|
683
|
+
operands = [SPARQL::Algebra::Expression.for(:with, value[:_Modify_1], *operands)] if value[:_Modify_1]
|
684
|
+
SPARQL::Algebra::Expression(:modify, *operands)
|
685
|
+
end
|
686
|
+
|
687
|
+
# (rule _Modify_2 (alt _Modify_5 InsertClause))
|
688
|
+
#
|
689
|
+
# Clear cached bnodes here to be able to detect illegal attempt to re-define
|
690
|
+
#
|
691
|
+
# XXX Doe we really need to clear the cache?
|
692
|
+
start_production(:_Modify_2) {self.clear_bnode_cache}
|
693
|
+
|
694
|
+
# (rule _Modify_4 (seq 'WITH' iri))
|
695
|
+
production(:_Modify_4) do |value|
|
696
|
+
value.last[:iri]
|
697
|
+
end
|
698
|
+
|
699
|
+
# (rule _Modify_5 (seq DeleteClause _Modify_6))
|
700
|
+
start_production(:_Modify_5, as_hash: true)
|
701
|
+
production(:_Modify_5) do |value|
|
702
|
+
[value[:DeleteClause], value[:_Modify_6]]
|
703
|
+
end
|
704
|
+
|
705
|
+
# DeleteClause ::= "DELETE" QuadPattern
|
706
|
+
#
|
707
|
+
# Generate BNodes instead of non-distinguished variables. BNodes are not legal, but this will generate them rather than non-distinguished variables so they can be detected.
|
708
|
+
start_production(:DeleteClause, as_hash: true)
|
709
|
+
production(:DeleteClause) do |value|
|
710
|
+
raise Error, "DeleteClause contains BNode operands: #{Array(value[:QuadPattern]).to_sse}" if Array(value[:QuadPattern]).any?(&:node?)
|
711
|
+
SPARQL::Algebra::Expression(:delete, Array(value[:QuadPattern]))
|
712
|
+
end
|
713
|
+
|
714
|
+
# InsertClause ::= "INSERT" QuadPattern
|
715
|
+
#
|
716
|
+
# Generate BNodes instead of non-distinguished variables.
|
717
|
+
start_production(:InsertClause, as_hash: true)
|
718
|
+
production(:InsertClause) do |value|
|
719
|
+
SPARQL::Algebra::Expression(:insert, Array(value[:QuadPattern]))
|
720
|
+
end
|
721
|
+
|
722
|
+
# UsingClause ::= "USING" ( iri | "NAMED" iri)
|
723
|
+
#
|
724
|
+
# (rule UsingClause (seq 'USING' _UsingClause_1))
|
725
|
+
# (rule _UsingClause_1 (alt iri _UsingClause_2))
|
726
|
+
# (rule _UsingClause_2 (seq 'NAMED' iri))
|
727
|
+
#
|
728
|
+
start_production(:UsingClause, as_hash: true)
|
729
|
+
production(:UsingClause) do |value|
|
730
|
+
value[:_UsingClause_1]
|
731
|
+
end
|
732
|
+
|
733
|
+
# (rule _UsingClause_2 (seq 'NAMED' iri))
|
734
|
+
start_production(:_UsingClause_2, as_hash: true)
|
735
|
+
production(:_UsingClause_2) do |value|
|
736
|
+
[:named, value[:iri]]
|
737
|
+
end
|
738
|
+
|
739
|
+
# GraphOrDefault ::= "DEFAULT" | "GRAPH"? iri
|
740
|
+
#
|
741
|
+
# (rule GraphOrDefault (alt 'DEFAULT' _GraphOrDefault_1))
|
742
|
+
# (rule _GraphOrDefault_1 (seq _GraphOrDefault_2 iri))
|
743
|
+
# (rule _GraphOrDefault_2 (opt 'GRAPH'))
|
744
|
+
production(:GraphOrDefault) do |value|
|
745
|
+
value.is_a?(String) ? value.downcase.to_sym : value
|
746
|
+
end
|
747
|
+
start_production(:_GraphOrDefault_1, as_hash: true)
|
748
|
+
production(:_GraphOrDefault_1) {|value| value[:iri]}
|
749
|
+
|
750
|
+
# GraphRef ::= "GRAPH" iri
|
751
|
+
production(:GraphRef) do |value|
|
752
|
+
value.last[:iri]
|
753
|
+
end
|
754
|
+
|
755
|
+
# QuadPattern::= '{' Quads '}'
|
756
|
+
# Returns array of patterns
|
757
|
+
start_production(:QuadPattern, as_hash: true) {self.gen_bnodes}
|
758
|
+
production(:QuadPattern) do |value|
|
759
|
+
self.gen_bnodes(false)
|
760
|
+
value[:Quads]
|
761
|
+
end
|
762
|
+
|
763
|
+
# QuadData ::= "{" Quads "}"
|
764
|
+
#
|
765
|
+
# QuadData is like QuadPattern, except without BNodes
|
766
|
+
# Generate BNodes instead of non-distinguished variables
|
767
|
+
#
|
768
|
+
# Returns array of patterns
|
769
|
+
start_production(:QuadData, as_hash: true) do |data|
|
770
|
+
# Freeze bnodes if called from INSERT DATA
|
771
|
+
self.freeze_bnodes if data[:_rept_data].first.key?(:"INSERT DATA")
|
772
|
+
self.gen_bnodes
|
773
|
+
end
|
774
|
+
production(:QuadData) do |value|
|
775
|
+
# Transform using statements instead of patterns, and verify there are no variables
|
776
|
+
raise Error, "QuadData contains variable operands: #{Array(value[:Quads]).to_sse}" if Array(value[:Quads]).any?(&:variable?)
|
777
|
+
self.gen_bnodes(false)
|
778
|
+
value[:Quads]
|
779
|
+
end
|
780
|
+
|
781
|
+
# Quads ::= TriplesTemplate? ( QuadsNotTriples '.'? TriplesTemplate? )*
|
782
|
+
#
|
783
|
+
# (rule Quads (seq _Quads_1 _Quads_2))
|
784
|
+
# (rule _Quads_1 (opt TriplesTemplate))
|
785
|
+
# (rule _Quads_2 (star _Quads_3))
|
786
|
+
# (rule _Quads_3 (seq QuadsNotTriples _Quads_4 _Quads_5))
|
787
|
+
# (rule _Quads_4 (opt '.'))
|
788
|
+
# (rule _Quads_5 (opt TriplesTemplate))
|
789
|
+
#
|
790
|
+
# Returns an array of patterns
|
791
|
+
start_production(:Quads, as_hash: true)
|
792
|
+
production(:Quads) do |value|
|
793
|
+
Array(value[:_Quads_1]) + value[:_Quads_2].flatten
|
794
|
+
end
|
795
|
+
|
796
|
+
# (rule _Quads_3 (seq QuadsNotTriples _Quads_4 _Quads_5))
|
797
|
+
start_production(:_Quads_3, as_hash: true)
|
798
|
+
production(:_Quads_3) do |value|
|
799
|
+
[value[:QuadsNotTriples]] + Array(value[:_Quads_5])
|
800
|
+
end
|
801
|
+
|
802
|
+
# QuadsNotTriples ::= "GRAPH" VarOrIri "{" TriplesTemplate? "}"
|
803
|
+
#
|
804
|
+
# (rule QuadsNotTriples (seq 'GRAPH' VarOrIri '{' _QuadsNotTriples_1 '}'))
|
805
|
+
# (rule _QuadsNotTriples_1 (opt TriplesTemplate))
|
806
|
+
#
|
807
|
+
# Result is Graph operator
|
808
|
+
start_production(:QuadsNotTriples, as_hash: true)
|
809
|
+
production(:QuadsNotTriples) do |value|
|
810
|
+
SPARQL::Algebra::Expression.for(:graph, value[:VarOrIri], Array(value[:_QuadsNotTriples_1]))
|
811
|
+
end
|
812
|
+
|
813
|
+
# TriplesTemplate ::= TriplesSameSubject ("." TriplesTemplate? )?
|
814
|
+
#
|
815
|
+
# (rule TriplesTemplate (seq TriplesSameSubject _TriplesTemplate_1))
|
816
|
+
# (rule _TriplesTemplate_1 (opt _TriplesTemplate_2))
|
817
|
+
# (rule _TriplesTemplate_2 (seq '.' _TriplesTemplate_3))
|
818
|
+
# (rule _TriplesTemplate_3 (opt TriplesTemplate))
|
819
|
+
#
|
820
|
+
# Returnes patterns
|
821
|
+
start_production(:TriplesTemplate, as_hash: true)
|
822
|
+
production(:TriplesTemplate) do |value|
|
823
|
+
value[:TriplesSameSubject] + Array(value[:_TriplesTemplate_1])
|
824
|
+
end
|
825
|
+
|
826
|
+
# (rule _TriplesTemplate_2 (seq '.' _TriplesTemplate_3))
|
827
|
+
production(:_TriplesTemplate_2) do |value|
|
828
|
+
value.last[:_TriplesTemplate_3]
|
829
|
+
end
|
830
|
+
|
831
|
+
# GroupGraphPattern ::= '{' ( SubSelect | GroupGraphPatternSub ) '}'
|
832
|
+
start_production(:GroupGraphPattern, as_hash: true)
|
833
|
+
production(:GroupGraphPattern) do |value|
|
834
|
+
{query: value&.dig(:_GroupGraphPattern_1, :query)}
|
835
|
+
end
|
836
|
+
|
837
|
+
# GroupGraphPatternSub ::= TriplesBlock? (GraphPatternNotTriples "."? TriplesBlock? )*
|
838
|
+
#
|
839
|
+
# (rule GroupGraphPatternSub (seq _GroupGraphPatternSub_1 _GroupGraphPatternSub_2))
|
840
|
+
# (rule _GroupGraphPatternSub_1 (opt TriplesBlock))
|
841
|
+
# (rule _GroupGraphPatternSub_2 (star _GroupGraphPatternSub_3))
|
842
|
+
# (rule _GroupGraphPatternSub_3
|
843
|
+
# (seq GraphPatternNotTriples _GroupGraphPatternSub_4 _GroupGraphPatternSub_5))
|
844
|
+
# (rule _GroupGraphPatternSub_4 (opt '.'))
|
845
|
+
# (rule _GroupGraphPatternSub_5 (opt TriplesBlock))
|
846
|
+
start_production(:GroupGraphPatternSub, as_hash: true)
|
847
|
+
production(:GroupGraphPatternSub) do |value|
|
848
|
+
query = value[:_GroupGraphPatternSub_1] || SPARQL::Algebra::Operator::BGP.new
|
849
|
+
extensions = []
|
850
|
+
filters = []
|
851
|
+
|
852
|
+
value[:_GroupGraphPatternSub_2].each do |ggps2|
|
853
|
+
filters << ggps2[:filter] if ggps2[:filter]
|
854
|
+
|
855
|
+
bgp = ggps2[:query]
|
856
|
+
query = if bgp && query.mergable?(bgp) && false # XXX No agressive merging
|
857
|
+
query.merge(bgp)
|
858
|
+
elsif query.empty? && bgp
|
859
|
+
bgp
|
860
|
+
elsif !bgp || bgp.empty?
|
861
|
+
query
|
862
|
+
else
|
863
|
+
SPARQL::Algebra::Operator::Join.new(query, bgp)
|
864
|
+
end
|
865
|
+
|
866
|
+
# Extensions
|
867
|
+
if ggps2[:extend]
|
868
|
+
# Extensions will be an array of pairs of variable and expression
|
869
|
+
error(nil,
|
870
|
+
"Internal error on extensions form",
|
871
|
+
production: :GroupGraphPatternSub,
|
872
|
+
fatal: true) unless
|
873
|
+
ggps2[:extend].is_a?(Array) && ggps2[:extend].all? {|e| e.is_a?(Array)}
|
874
|
+
|
875
|
+
# The variable assigned in a BIND clause must not be already in-use within the immediately preceding TriplesBlock within a GroupGraphPattern.
|
876
|
+
# None of the variables on the lhs of data[:extend] may be used in lhs
|
877
|
+
ggps2[:extend].each do |(v, _)|
|
878
|
+
error(nil, "BIND Variable #{v} used in pattern", production: :GraphPatternNotTriples) if query.vars.map(&:to_sym).include?(v.to_sym)
|
879
|
+
end
|
880
|
+
query = if query.is_a?(SPARQL::Algebra::Operator::Extend)
|
881
|
+
# Coalesce extensions
|
882
|
+
lhs = query.dup
|
883
|
+
lhs.operands.first.concat(ggps2[:extend])
|
884
|
+
lhs
|
885
|
+
else
|
886
|
+
SPARQL::Algebra::Expression[:extend, ggps2[:extend], query] unless ggps2[:extend].empty?
|
887
|
+
end
|
888
|
+
end
|
889
|
+
|
890
|
+
# _GroupGraphPatternSub_3 can return patterns from TriplesBlock?
|
891
|
+
if bgp = ggps2[:extra]
|
892
|
+
query = if query.mergable?(bgp) && false # XXX No agressive merging
|
893
|
+
query.merge(bgp)
|
894
|
+
elsif query.empty?
|
895
|
+
bgp
|
896
|
+
elsif bgp.empty?
|
897
|
+
query
|
898
|
+
elsif bgp.is_a?(SPARQL::Algebra::Operator::Path)
|
899
|
+
SPARQL::Algebra::Operator::Sequence.new(query, bgp)
|
900
|
+
else
|
901
|
+
SPARQL::Algebra::Operator::Join.new(query, bgp)
|
902
|
+
end
|
903
|
+
end
|
904
|
+
|
905
|
+
query = if ggps2[:leftjoin]
|
906
|
+
SPARQL::Algebra::Expression.for(:leftjoin, query, *ggps2[:leftjoin])
|
907
|
+
elsif ggps2[:minus]
|
908
|
+
SPARQL::Algebra::Expression.for(:minus, query, ggps2[:minus])
|
909
|
+
else
|
910
|
+
query
|
911
|
+
end
|
912
|
+
end
|
913
|
+
|
914
|
+
# Filters
|
915
|
+
unless filters.empty?
|
916
|
+
expr = filters.length > 1 ? SPARQL::Algebra::Operator::Exprlist.new(*filters) : filters.first
|
917
|
+
query = SPARQL::Algebra::Operator::Filter.new(expr, query)
|
918
|
+
end
|
919
|
+
|
920
|
+
{query: query}
|
921
|
+
end
|
922
|
+
|
923
|
+
# (rule _GroupGraphPatternSub_3
|
924
|
+
# (seq GraphPatternNotTriples _GroupGraphPatternSub_4 _GroupGraphPatternSub_5))
|
925
|
+
start_production(:_GroupGraphPatternSub_3, as_hash: true)
|
926
|
+
production(:_GroupGraphPatternSub_3) do |value|
|
927
|
+
{
|
928
|
+
extend: value&.dig(:GraphPatternNotTriples, :extend),
|
929
|
+
extra: value[:_GroupGraphPatternSub_5],
|
930
|
+
filter: value&.dig(:GraphPatternNotTriples, :filter),
|
931
|
+
leftjoin: value&.dig(:GraphPatternNotTriples, :leftjoin),
|
932
|
+
minus: value&.dig(:GraphPatternNotTriples, :minus),
|
933
|
+
query: value&.dig(:GraphPatternNotTriples, :query),
|
934
|
+
}
|
935
|
+
end
|
936
|
+
|
937
|
+
# TriplesBlock ::= TriplesSameSubjectPath
|
938
|
+
# ( '.' TriplesBlock? )?
|
939
|
+
#
|
940
|
+
# (rule TriplesBlock (seq TriplesSameSubjectPath _TriplesBlock_1))
|
941
|
+
# (rule _TriplesBlock_1 (opt _TriplesBlock_2))
|
942
|
+
# (rule _TriplesBlock_2 (seq '.' _TriplesBlock_3))
|
943
|
+
# (rule _TriplesBlock_3 (opt TriplesBlock))
|
944
|
+
start_production(:TriplesBlock, as_hash: true)
|
945
|
+
production(:TriplesBlock) do |value|
|
946
|
+
tb1 = value[:_TriplesBlock_1]
|
947
|
+
sequence = Array(value[:TriplesSameSubjectPath])
|
948
|
+
|
949
|
+
# Append triples from ('.' TriplesBlock? )?
|
950
|
+
if tb1.is_a?(SPARQL::Algebra::Operator::Sequence)
|
951
|
+
tb1.operands.each do |op|
|
952
|
+
sequence += op.respond_to?(:patterns) ? op.patterns : [op]
|
953
|
+
end
|
954
|
+
elsif tb1.respond_to?(:patterns)
|
955
|
+
sequence += tb1.patterns
|
956
|
+
elsif tb1
|
957
|
+
sequence << tb1
|
958
|
+
end
|
959
|
+
|
960
|
+
# Merge runs of patterns into BGPs
|
961
|
+
patterns = []
|
962
|
+
new_seq = []
|
963
|
+
sequence.each do |element|
|
964
|
+
case element
|
965
|
+
when RDF::Query::Pattern
|
966
|
+
patterns << element
|
967
|
+
when RDF::Queryable
|
968
|
+
patterns += element.patterns
|
969
|
+
else
|
970
|
+
new_seq << SPARQL::Algebra::Operator::BGP.new(*patterns) unless patterns.empty?
|
971
|
+
patterns = []
|
972
|
+
new_seq << element
|
973
|
+
end
|
974
|
+
end
|
975
|
+
new_seq << SPARQL::Algebra::Operator::BGP.new(*patterns) unless patterns.empty?
|
976
|
+
|
977
|
+
# Optionally create a sequence, if there are enough gathered.
|
978
|
+
# FIXME: Join?
|
979
|
+
if new_seq.length > 1
|
980
|
+
if new_seq.any? {|e| e.is_a?(SPARQL::Algebra::Operator::Path)}
|
981
|
+
SPARQL::Algebra::Expression.for(:sequence, *new_seq)
|
982
|
+
else
|
983
|
+
SPARQL::Algebra::Expression.for(:join, *new_seq)
|
984
|
+
end
|
985
|
+
else
|
986
|
+
new_seq.first
|
987
|
+
end
|
988
|
+
end
|
989
|
+
|
990
|
+
# (rule _TriplesBlock_2 (seq '.' _TriplesBlock_3))
|
991
|
+
start_production(:_TriplesBlock_2, as_hash: true)
|
992
|
+
production(:_TriplesBlock_2) do |value|
|
993
|
+
value[:_TriplesBlock_3]
|
994
|
+
end
|
995
|
+
|
996
|
+
# ReifiedTripleBlock ::= ReifiedTriple PropertyList
|
997
|
+
start_production(:ReifiedTripleBlock, as_hash: true)
|
998
|
+
production(:ReifiedTripleBlock) do |value|
|
999
|
+
{ReifiedTripleBlock: value[:ReifiedTriple][:pattern] + Array(value[:PropertyList])}
|
1000
|
+
end
|
1001
|
+
|
1002
|
+
# ReifiedTripleBlockPath ::= ReifiedTriple PropertyListPath
|
1003
|
+
#
|
1004
|
+
# Returns `{ReifiedTripleBlockPath: patterns}`
|
1005
|
+
start_production(:ReifiedTripleBlockPath, as_hash: true)
|
1006
|
+
production(:ReifiedTripleBlockPath) do |value|
|
1007
|
+
{ReifiedTripleBlockPath: value[:ReifiedTriple][:pattern] + Array(value[:PropertyListPath])}
|
1008
|
+
end
|
1009
|
+
|
1010
|
+
# OptionalGraphPattern ::= 'OPTIONAL' GroupGraphPattern
|
1011
|
+
#
|
1012
|
+
# FIXME: This should not extract a filter if there is more than one level of curly braces.
|
1013
|
+
start_production(:OptionalGraphPattern, as_hash: true)
|
1014
|
+
production(:OptionalGraphPattern) do |value|
|
1015
|
+
query = value&.dig(:GroupGraphPattern, :query) || SPARQL::Algebra::Operator::BGP.new
|
1016
|
+
if query.is_a?(SPARQL::Algebra::Operator::Filter)
|
1017
|
+
# Change to expression on left-join with query element
|
1018
|
+
expr, query = query.operands
|
1019
|
+
{leftjoin: [query, expr]}
|
1020
|
+
elsif !query.empty?
|
1021
|
+
{leftjoin: [query]}
|
1022
|
+
end
|
1023
|
+
end
|
1024
|
+
|
1025
|
+
# GraphGraphPattern ::= 'GRAPH' VarOrIri GroupGraphPattern
|
1026
|
+
start_production(:GraphGraphPattern, as_hash: true)
|
1027
|
+
production(:GraphGraphPattern) do |value|
|
1028
|
+
name = value[:VarOrIri]
|
1029
|
+
bgp = value&.dig(:GroupGraphPattern, :query) || SPARQL::Algebra::Operator::BGP.new
|
1030
|
+
{
|
1031
|
+
query: (name ? SPARQL::Algebra::Expression.for(:graph, name, bgp) : bgp)
|
1032
|
+
}
|
1033
|
+
end
|
1034
|
+
|
1035
|
+
# ServiceGraphPattern ::= 'SERVICE' 'SILENT'? VarOrIri GroupGraphPattern
|
1036
|
+
start_production(:ServiceGraphPattern, as_hash: true)
|
1037
|
+
production(:ServiceGraphPattern) do |value|
|
1038
|
+
query = value&.dig(:GroupGraphPattern, :query) || SPARQL::Algebra::Operator::BGP.new
|
1039
|
+
args = []
|
1040
|
+
args << :silent if value[:_ServiceGraphPattern_1]
|
1041
|
+
args << value[:VarOrIri]
|
1042
|
+
args << query
|
1043
|
+
service = SPARQL::Algebra::Expression.for(:service, *args)
|
1044
|
+
{query: service}
|
1045
|
+
end
|
1046
|
+
|
1047
|
+
# Bind ::= 'BIND' '(' Expression 'AS' Var ')'
|
1048
|
+
start_production(:Bind, as_hash: true)
|
1049
|
+
production(:Bind) do |value|
|
1050
|
+
{extend: [[value[:Var], value[:Expression]]]}
|
1051
|
+
end
|
1052
|
+
|
1053
|
+
# InlineData ::= 'VALUES' DataBlock
|
1054
|
+
start_production(:InlineData, as_hash: true)
|
1055
|
+
production(:InlineData) do |value|
|
1056
|
+
debug("InlineData") {value[:DataBlock].inspect}
|
1057
|
+
args = [Array(value[:DataBlock][:Var]).unshift(:vars)] + value[:DataBlock][:row]
|
1058
|
+
table = SPARQL::Algebra::Expression.for(:table, *args)
|
1059
|
+
{query: table}
|
1060
|
+
end
|
1061
|
+
|
1062
|
+
# InlineDataOneVar ::= Var '{' DataBlockValue* '}'
|
1063
|
+
start_production(:InlineDataOneVar, as_hash: true)
|
1064
|
+
production(:InlineDataOneVar) do |value|
|
1065
|
+
{
|
1066
|
+
Var: value[:Var],
|
1067
|
+
row: value[:_InlineDataOneVar_1].map {|dbv| [:row, [value[:Var], dbv]]}
|
1068
|
+
}
|
1069
|
+
end
|
1070
|
+
|
1071
|
+
# InlineDataFull ::= ( NIL | '(' Var* ')' )
|
1072
|
+
# '{' ( '(' DataBlockValue* ')' | NIL )* '}'
|
1073
|
+
#
|
1074
|
+
# (rule InlineDataFull (seq _InlineDataFull_1 '{' _InlineDataFull_2 '}'))
|
1075
|
+
# (rule _InlineDataFull_1 (alt NIL _InlineDataFull_3))
|
1076
|
+
# (rule _InlineDataFull_3 (seq '(' _InlineDataFull_4 ')'))
|
1077
|
+
# (rule _InlineDataFull_4 (star Var))
|
1078
|
+
# (rule _InlineDataFull_2 (star _InlineDataFull_5))
|
1079
|
+
# (rule _InlineDataFull_5 (alt _InlineDataFull_6 NIL))
|
1080
|
+
# (rule _InlineDataFull_6 (seq '(' _InlineDataFull_7 ')'))
|
1081
|
+
# (rule _InlineDataFull_7 (star DataBlockValue))
|
1082
|
+
#
|
1083
|
+
start_production(:InlineDataFull, as_hash: true)
|
1084
|
+
production(:InlineDataFull) do |value|
|
1085
|
+
vars = value[:_InlineDataFull_1]
|
1086
|
+
vars = [] if vars == RDF.nil
|
1087
|
+
|
1088
|
+
rows = value[:_InlineDataFull_2].map do |ds|
|
1089
|
+
# XXX what if ds == RDF.nil
|
1090
|
+
if ds.length < vars.length
|
1091
|
+
raise Error, "Too few values in a VALUE clause compared to the number of variables"
|
1092
|
+
elsif ds.length > vars.length
|
1093
|
+
raise Error, "Too many values in a VALUE clause compared to the number of variables"
|
1094
|
+
end
|
1095
|
+
r = [:row]
|
1096
|
+
ds.each_with_index do |d, i|
|
1097
|
+
r << [vars[i], d] if d
|
1098
|
+
end
|
1099
|
+
r unless r.empty?
|
1100
|
+
end.compact
|
1101
|
+
|
1102
|
+
{
|
1103
|
+
Var: vars,
|
1104
|
+
row: rows
|
1105
|
+
}
|
1106
|
+
end
|
1107
|
+
|
1108
|
+
# (rule _InlineDataFull_3 (seq '(' _InlineDataFull_4 ')'))
|
1109
|
+
start_production(:_InlineDataFull_3, as_hash: true)
|
1110
|
+
production(:_InlineDataFull_3) do |value|
|
1111
|
+
value[:_InlineDataFull_4]
|
1112
|
+
end
|
1113
|
+
|
1114
|
+
# (rule _InlineDataFull_6 (seq '(' _InlineDataFull_7 ')'))
|
1115
|
+
start_production(:_InlineDataFull_6, as_hash: true)
|
1116
|
+
production(:_InlineDataFull_6) do |value|
|
1117
|
+
value[:_InlineDataFull_7]
|
1118
|
+
end
|
1119
|
+
|
1120
|
+
# Reifier ::= '~' VarOrReifierId?
|
1121
|
+
#
|
1122
|
+
# Beginning the reifier production, the curReifier is taken from the reifier term constructor. Then yield the the RDF triple curReifier rdf:reifies curTripleTerm.
|
1123
|
+
#
|
1124
|
+
# Returns emitted pattern
|
1125
|
+
start_production(:Reifier, as_hash: true)
|
1126
|
+
production(:Reifier) do |value|
|
1127
|
+
rid = prod_data[:curReifier] = value[:_Reifier_1] || bnode
|
1128
|
+
RDF::Query::Pattern.new(rid, RDF.reifies, prod_data[:TripleTerm]) if prod_data[:TripleTerm]
|
1129
|
+
end
|
1130
|
+
|
1131
|
+
# MinusGraphPattern ::= 'MINUS' GroupGraphPattern
|
1132
|
+
start_production(:MinusGraphPattern, as_hash: true)
|
1133
|
+
production(:MinusGraphPattern) do |value|
|
1134
|
+
query = value&.dig(:GroupGraphPattern, :query) || SPARQL::Algebra::Operator::BGP.new
|
1135
|
+
{minus: query}
|
1136
|
+
end
|
1137
|
+
|
1138
|
+
# GroupOrUnionGraphPattern ::= GroupGraphPattern
|
1139
|
+
# ( 'UNION' GroupGraphPattern )*
|
1140
|
+
start_production(:GroupOrUnionGraphPattern, as_hash: true)
|
1141
|
+
production(:GroupOrUnionGraphPattern) do |value|
|
1142
|
+
lhs = value&.dig(:GroupGraphPattern, :query)
|
1143
|
+
query = value[:_GroupOrUnionGraphPattern_1].reduce(lhs) do |memo, q|
|
1144
|
+
SPARQL::Algebra::Expression.for(:union, memo, q)
|
1145
|
+
end
|
1146
|
+
|
1147
|
+
{query: query}
|
1148
|
+
end
|
1149
|
+
|
1150
|
+
# (rule _GroupOrUnionGraphPattern_2 (seq 'UNION' GroupGraphPattern))
|
1151
|
+
start_production(:_GroupOrUnionGraphPattern_2, as_hash: true)
|
1152
|
+
production(:_GroupOrUnionGraphPattern_2) do |value|
|
1153
|
+
value&.dig(:GroupGraphPattern, :query)
|
1154
|
+
end
|
1155
|
+
|
1156
|
+
# Filter ::= 'FILTER' Constraint
|
1157
|
+
start_production(:Filter, as_hash: true)
|
1158
|
+
production(:Filter) do |value|
|
1159
|
+
{filter: value[:Constraint]}
|
1160
|
+
end
|
1161
|
+
|
1162
|
+
# FunctionCall ::= iri ArgList
|
1163
|
+
start_production(:FunctionCall, as_hash: true)
|
1164
|
+
production(:FunctionCall) do |value|
|
1165
|
+
SPARQL::Algebra::Operator::FunctionCall.new(value[:iri], *value[:ArgList])
|
1166
|
+
end
|
1167
|
+
|
1168
|
+
# ArgList ::= NIL | '(' 'DISTINCT'? Expression ( ',' Expression )* ')'
|
1169
|
+
#
|
1170
|
+
# (rule ArgList (alt NIL _ArgList_1))
|
1171
|
+
# (rule _ArgList_1 (seq '(' _ArgList_2 Expression _ArgList_3 ')'))
|
1172
|
+
# (rule _ArgList_2 (opt 'DISTINCT'))
|
1173
|
+
# (rule _ArgList_3 (star _ArgList_4))
|
1174
|
+
# (rule _ArgList_4 (seq ',' Expression))
|
1175
|
+
#
|
1176
|
+
# XXX handle DISTINCT?
|
1177
|
+
production(:ArgList) do |value|
|
1178
|
+
Array(value)
|
1179
|
+
end
|
1180
|
+
|
1181
|
+
start_production(:_ArgList_1, as_hash: true)
|
1182
|
+
production(:_ArgList_1) do |value|
|
1183
|
+
value[:_ArgList_3].unshift(value[:Expression])
|
1184
|
+
end
|
1185
|
+
|
1186
|
+
start_production(:_ArgList_4, as_hash: true)
|
1187
|
+
production(:_ArgList_4) do |value|
|
1188
|
+
value[:Expression]
|
1189
|
+
end
|
1190
|
+
|
1191
|
+
# ExpressionList ::= NIL | '(' Expression ( ',' Expression )* ')'
|
1192
|
+
#
|
1193
|
+
# (rule ExpressionList (alt NIL _ExpressionList_1))
|
1194
|
+
production(:ExpressionList) do |value|
|
1195
|
+
value.is_a?(RDF::Term) ? [] : value.flatten
|
1196
|
+
end
|
1197
|
+
|
1198
|
+
# (rule _ExpressionList_1 (seq '(' Expression _ExpressionList_2 ')'))
|
1199
|
+
production(:_ExpressionList_1) do |value|
|
1200
|
+
[value[1][:Expression], value[2][:_ExpressionList_2]].compact
|
1201
|
+
end
|
1202
|
+
|
1203
|
+
# (rule _ExpressionList_2 (star _ExpressionList_3))
|
1204
|
+
# (rule _ExpressionList_3 (seq ',' Expression))
|
1205
|
+
production(:_ExpressionList_2) do |value|
|
1206
|
+
value.map {|el3| el3.last[:Expression]}
|
1207
|
+
end
|
1208
|
+
|
1209
|
+
# ConstructTemplate ::= '{' ConstructTriples? '}'
|
1210
|
+
start_production(:ConstructTemplate, as_hash: true)
|
1211
|
+
production(:ConstructTemplate) do |value|
|
1212
|
+
# Generate BNodes instead of non-distinguished variables
|
1213
|
+
self.gen_bnodes(false)
|
1214
|
+
value[:_ConstructTemplate_1]
|
1215
|
+
end
|
1216
|
+
|
1217
|
+
# ConstructTriples ::= TriplesSameSubject ( '.' ConstructTriples? )?
|
1218
|
+
# Returns patterns
|
1219
|
+
start_production(:ConstructTriples, as_hash: true) do
|
1220
|
+
# Generate BNodes instead of non-distinguished variables
|
1221
|
+
self.gen_bnodes
|
1222
|
+
end
|
1223
|
+
production(:ConstructTriples) do |value|
|
1224
|
+
# Generate BNodes instead of non-distinguished variables
|
1225
|
+
value[:TriplesSameSubject] + Array(value[:_ConstructTriples_1])
|
1226
|
+
end
|
1227
|
+
|
1228
|
+
# (rule _ConstructTriples_2 (seq '.' _ConstructTriples_3))
|
1229
|
+
start_production(:_ConstructTriples_2, as_hash: true)
|
1230
|
+
production(:_ConstructTriples_2) do |value|
|
1231
|
+
value[:_ConstructTriples_3]
|
1232
|
+
end
|
1233
|
+
|
1234
|
+
# TriplesSameSubject ::= VarOrTerm PropertyListNotEmpty
|
1235
|
+
# | TriplesNode PropertyList | ReifiedTripleBlock
|
1236
|
+
#
|
1237
|
+
# (rule TriplesSameSubject
|
1238
|
+
# (alt _TriplesSameSubject_1 _TriplesSameSubject_2 ReifiedTripleBlock))
|
1239
|
+
# (rule _TriplesSameSubject_1 (seq VarOrTerm PropertyListNotEmpty))
|
1240
|
+
# (rule _TriplesSameSubject_2 (seq TriplesNode PropertyList))
|
1241
|
+
#
|
1242
|
+
# Returns patterns
|
1243
|
+
production(:TriplesSameSubject) do |value|
|
1244
|
+
pattern = if value[:VarOrTerm]
|
1245
|
+
value[:PropertyListNotEmpty]
|
1246
|
+
elsif value[:TriplesNode]
|
1247
|
+
value[:TriplesNode][:pattern] + Array(value[:PropertyList])
|
1248
|
+
elsif value[:ReifiedTripleBlock]
|
1249
|
+
value[:ReifiedTripleBlock]
|
1250
|
+
else
|
1251
|
+
[]
|
1252
|
+
end
|
1253
|
+
pattern
|
1254
|
+
end
|
1255
|
+
|
1256
|
+
# (rule _TriplesSameSubject_1 (seq VarOrTerm PropertyListNotEmpty))
|
1257
|
+
start_production(:_TriplesSameSubject_1, as_hash: true)
|
1258
|
+
|
1259
|
+
# (rule _TriplesSameSubject_2 (seq TriplesNode PropertyList))
|
1260
|
+
start_production(:_TriplesSameSubject_2, as_hash: true)
|
1261
|
+
|
1262
|
+
# PropertyList ::= PropertyListNotEmpty?
|
1263
|
+
|
1264
|
+
# PropertyListNotEmpty ::= Verb ObjectList
|
1265
|
+
# ( ';' ( Verb ObjectList )? )*
|
1266
|
+
#
|
1267
|
+
# (rule PropertyListNotEmpty (seq Verb ObjectList _PropertyListNotEmpty_1))
|
1268
|
+
# (rule _PropertyListNotEmpty_1 (star _PropertyListNotEmpty_2))
|
1269
|
+
# (rule _PropertyListNotEmpty_2 (seq ';' _PropertyListNotEmpty_3))
|
1270
|
+
# (rule _PropertyListNotEmpty_3 (opt _PropertyListNotEmpty_4))
|
1271
|
+
# (rule _PropertyListNotEmpty_4 (seq Verb ObjectList))
|
1272
|
+
#
|
1273
|
+
# Returns patterns
|
1274
|
+
start_production(:PropertyListNotEmpty, as_hash: true) do |data|
|
1275
|
+
# If we're in an AnnotationPathBlock, use reification information
|
1276
|
+
if anno_data = prod_data[:AnnotationData]
|
1277
|
+
# Allocate a reifier ID, if necessary and use as subject
|
1278
|
+
prod_data[:Subject] = anno_data[:curReifier] ||= bnode
|
1279
|
+
end
|
1280
|
+
|
1281
|
+
# If options has a `:_rept_data` entry, use it to get the subject
|
1282
|
+
subject = prod_data[:Subject] || prod_data[:TriplesNode] || data[:_rept_data].last[:VarOrTerm]
|
1283
|
+
error(nil, "Expected VarOrTerm or TriplesNode or GraphNode", production: :PropertyListNotEmpty) if !subject
|
1284
|
+
data[:Subject] = subject
|
1285
|
+
end
|
1286
|
+
production(:PropertyListNotEmpty) do |value|
|
1287
|
+
patterns = Array(value[:ObjectList][:pattern])
|
1288
|
+
value[:_PropertyListNotEmpty_1].each do |plne|
|
1289
|
+
patterns += plne[:pattern]
|
1290
|
+
end
|
1291
|
+
patterns
|
1292
|
+
end
|
1293
|
+
|
1294
|
+
# (rule _PropertyListNotEmpty_2 (seq ';' _PropertyListNotEmpty_3))
|
1295
|
+
start_production(:_PropertyListNotEmpty_2, as_hash: true) do |data|
|
1296
|
+
data[:Subject] = prod_data[:Subject]
|
1297
|
+
end
|
1298
|
+
production(:_PropertyListNotEmpty_2) do |value|
|
1299
|
+
value[:_PropertyListNotEmpty_3]
|
1300
|
+
end
|
1301
|
+
|
1302
|
+
# (rule _PropertyListNotEmpty_4 (seq Verb ObjectList))
|
1303
|
+
start_production(:_PropertyListNotEmpty_4, as_hash: true) do |data|
|
1304
|
+
data[:Subject] = prod_data[:Subject]
|
1305
|
+
end
|
1306
|
+
production(:_PropertyListNotEmpty_4) do |value|
|
1307
|
+
value[:ObjectList]
|
1308
|
+
end
|
1309
|
+
|
1310
|
+
# Verb ::= VarOrIri | 'a'
|
1311
|
+
#
|
1312
|
+
# Output to input is `:Verb`.
|
1313
|
+
start_production(:Verb, as_hash: true, insensitive_strings: false)
|
1314
|
+
production(:Verb) do |value|
|
1315
|
+
value == 'a' ? RDF.type.dup.tap {|a| a.lexical = 'a'} : value
|
1316
|
+
end
|
1317
|
+
|
1318
|
+
# ObjectList ::= Object ( ',' Object )*
|
1319
|
+
#
|
1320
|
+
# (rule ObjectList (seq Object _ObjectList_1))
|
1321
|
+
# (rule _ObjectList_1 (star _ObjectList_2))
|
1322
|
+
# (rule _ObjectList_2 (seq ',' Object))
|
1323
|
+
#
|
1324
|
+
# Returns objects and patterns
|
1325
|
+
start_production(:ObjectList, as_hash: true) do |data|
|
1326
|
+
# Called after Verb. The prod_data stack should have Subject and Verb elements
|
1327
|
+
data[:Subject] = prod_data[:Subject]
|
1328
|
+
data[:Verb] = data[:_rept_data].last[:Verb]
|
1329
|
+
error(nil, "Expected Subject", production: :ObjectList) if !data[:Subject]
|
1330
|
+
error(nil, "Expected Verb", production: :ObjectList) if !(data[:Verb])
|
1331
|
+
end
|
1332
|
+
production(:ObjectList) do |value|
|
1333
|
+
objects = Array(value[:Object][:object])
|
1334
|
+
patterns = Array(value[:Object][:pattern])
|
1335
|
+
|
1336
|
+
value[:_ObjectList_1].each do |ob|
|
1337
|
+
objects << ob[:object]
|
1338
|
+
patterns += Array(ob[:pattern])
|
1339
|
+
end
|
1340
|
+
|
1341
|
+
{
|
1342
|
+
object: objects,
|
1343
|
+
pattern: patterns
|
1344
|
+
}
|
1345
|
+
end
|
1346
|
+
|
1347
|
+
# (rule _ObjectList_2 (seq ',' Object))
|
1348
|
+
start_production(:_ObjectList_2, as_hash: true) do |data|
|
1349
|
+
data[:Subject] = prod_data[:Subject]
|
1350
|
+
data[:Verb] = prod_data[:Verb]
|
1351
|
+
end
|
1352
|
+
production(:_ObjectList_2) do |value|
|
1353
|
+
value[:Object]
|
1354
|
+
end
|
1355
|
+
|
1356
|
+
# Object ::= GraphNode Annotation
|
1357
|
+
#
|
1358
|
+
# Sets `:Subject` and `:Verb` in data from input.
|
1359
|
+
start_production(:Object, as_hash: true) do |data|
|
1360
|
+
data[:Subject] = prod_data[:Subject]
|
1361
|
+
data[:Verb] = prod_data[:Verb]
|
1362
|
+
end
|
1363
|
+
production(:Object) do |value, data|
|
1364
|
+
subject = data[:Subject]
|
1365
|
+
verb = data[:Verb]
|
1366
|
+
object = value[:GraphNode][:object]
|
1367
|
+
patterns = [RDF::Query::Pattern.new(subject, verb, object)]
|
1368
|
+
{
|
1369
|
+
object: object,
|
1370
|
+
pattern: patterns + value[:GraphNode][:pattern] + value[:Annotation]
|
1371
|
+
}
|
1372
|
+
end
|
1373
|
+
|
1374
|
+
|
1375
|
+
# TriplesSameSubjectPath ::= VarOrTerm PropertyListPathNotEmpty
|
1376
|
+
# | TriplesNodePath PropertyListPath
|
1377
|
+
# | ReifiedTripleBlockPath
|
1378
|
+
#
|
1379
|
+
# (rule TriplesSameSubjectPath
|
1380
|
+
# (alt _TriplesSameSubjectPath_1 _TriplesSameSubjectPath_2 ReifiedTripleBlockPath))
|
1381
|
+
#
|
1382
|
+
# Returns patterns
|
1383
|
+
production(:TriplesSameSubjectPath) do |value|
|
1384
|
+
pattern = if value[:VarOrTerm]
|
1385
|
+
value[:PropertyListPathNotEmpty]
|
1386
|
+
elsif value[:TriplesNodePath]
|
1387
|
+
value[:TriplesNodePath][:pattern] + Array(value[:PropertyListPath])
|
1388
|
+
elsif value[:ReifiedTripleBlockPath]
|
1389
|
+
value[:ReifiedTripleBlockPath]
|
1390
|
+
else
|
1391
|
+
[]
|
1392
|
+
end
|
1393
|
+
pattern
|
1394
|
+
end
|
1395
|
+
|
1396
|
+
# (rule _TriplesSameSubjectPath_1 (seq VarOrTerm PropertyListPathNotEmpty))
|
1397
|
+
start_production(:_TriplesSameSubjectPath_1, as_hash: true)
|
1398
|
+
|
1399
|
+
# (rule _TriplesSameSubjectPath_2 (seq TriplesNodePath PropertyListPath))
|
1400
|
+
start_production(:_TriplesSameSubjectPath_2, as_hash: true)
|
1401
|
+
|
1402
|
+
# PropertyListPathNotEmpty ::= ( VerbPath | VerbSimple ) ObjectListPath
|
1403
|
+
# ( ';' ( ( VerbPath | VerbSimple )
|
1404
|
+
# ObjectListPath )? )*
|
1405
|
+
#
|
1406
|
+
# (rule PropertyListPathNotEmpty
|
1407
|
+
# (seq _PropertyListPathNotEmpty_1 ObjectListPath _PropertyListPathNotEmpty_2))
|
1408
|
+
#
|
1409
|
+
# Sets `:Subject` in data from either `:VarOrTerm`,
|
1410
|
+
# `:TriplesNode`, or `:GraphNode` in input with error checking.
|
1411
|
+
#
|
1412
|
+
# Returns patterns
|
1413
|
+
start_production(:PropertyListPathNotEmpty, as_hash: true) do |data|
|
1414
|
+
# If we're in an AnnotationPathBlock, use reification information
|
1415
|
+
if anno_data = prod_data[:AnnotationData]
|
1416
|
+
# Allocate a reifier ID, if necessary and use as subject
|
1417
|
+
prod_data[:Subject] = anno_data[:curReifier] ||= bnode
|
1418
|
+
end
|
1419
|
+
|
1420
|
+
# If options has a `:_rept_data` entry, use it to get the subject
|
1421
|
+
subject = prod_data[:Subject] ||
|
1422
|
+
prod_data[:TriplesNode] ||
|
1423
|
+
data[:_rept_data].last[:VarOrTerm]
|
1424
|
+
error(nil, "Expected Subject, got nothing", production: :PropertyListPathNotEmpty) if !subject
|
1425
|
+
data[:Subject] = subject
|
1426
|
+
end
|
1427
|
+
production(:PropertyListPathNotEmpty) do |value|
|
1428
|
+
patterns = Array(value[:ObjectListPath][:pattern])
|
1429
|
+
value[:_PropertyListPathNotEmpty_2].each do |plpne|
|
1430
|
+
patterns += plpne[:pattern]
|
1431
|
+
end
|
1432
|
+
patterns
|
1433
|
+
end
|
1434
|
+
|
1435
|
+
# (rule _PropertyListPathNotEmpty_1 (alt VerbPath VerbSimple))
|
1436
|
+
|
1437
|
+
# (rule _PropertyListPathNotEmpty_2 (star _PropertyListPathNotEmpty_3))
|
1438
|
+
start_production(:_PropertyListPathNotEmpty_2) do |data|
|
1439
|
+
data[:Subject] = prod_data[:Subject]
|
1440
|
+
end
|
1441
|
+
production(:_PropertyListPathNotEmpty_2) do |value|
|
1442
|
+
value.flatten
|
1443
|
+
end
|
1444
|
+
|
1445
|
+
# (rule _PropertyListPathNotEmpty_3 (seq ';' _PropertyListPathNotEmpty_4))
|
1446
|
+
start_production(:_PropertyListPathNotEmpty_3, as_hash: true) do |data|
|
1447
|
+
data[:Subject] = prod_data[:Subject]
|
1448
|
+
end
|
1449
|
+
production(:_PropertyListPathNotEmpty_3) do |value|
|
1450
|
+
value[:_PropertyListPathNotEmpty_4]
|
1451
|
+
end
|
1452
|
+
|
1453
|
+
# (rule _PropertyListPathNotEmpty_4 (opt _PropertyListPathNotEmpty_5))
|
1454
|
+
start_production(:_PropertyListPathNotEmpty_4) do |data|
|
1455
|
+
data[:Subject] = prod_data[:Subject]
|
1456
|
+
end
|
1457
|
+
|
1458
|
+
# (rule _PropertyListPathNotEmpty_5 (seq _PropertyListPathNotEmpty_6 ObjectListPath))
|
1459
|
+
start_production(:_PropertyListPathNotEmpty_5, as_hash: true) do |data|
|
1460
|
+
data[:Subject] = prod_data[:Subject]
|
1461
|
+
end
|
1462
|
+
production(:_PropertyListPathNotEmpty_5) do |value|
|
1463
|
+
value[:ObjectListPath]
|
1464
|
+
end
|
1465
|
+
|
1466
|
+
# VerbPath ::= Path
|
1467
|
+
start_production(:VerbPath, as_hash: true)
|
1468
|
+
production(:VerbPath) do |value|
|
1469
|
+
value[:Path]
|
1470
|
+
end
|
1471
|
+
|
1472
|
+
# VerbSimple ::= Var
|
1473
|
+
production(:VerbSimple) do |value|
|
1474
|
+
value.first[:Var]
|
1475
|
+
end
|
1476
|
+
|
1477
|
+
# ObjectListPath ::= ObjectPath ("," ObjectPath)*
|
1478
|
+
#
|
1479
|
+
# Addes `:Subject` from input to data with error checking.
|
1480
|
+
# Also adds either `:Verb` or `:VerbPath`
|
1481
|
+
#
|
1482
|
+
# Returns objects and patterns
|
1483
|
+
start_production(:ObjectListPath, as_hash: true) do |data|
|
1484
|
+
# Called after Verb. The prod_data stack should have Subject and Verb elements
|
1485
|
+
data[:Subject] = prod_data[:Subject]
|
1486
|
+
data[:Verb] = data[:_rept_data].last[:_PropertyListPathNotEmpty_1] ||
|
1487
|
+
data[:_rept_data].last[:_PropertyListPathNotEmpty_6]
|
1488
|
+
error(nil, "Expected Subject", production: :ObjectListPath) if !data[:Subject]
|
1489
|
+
error(nil, "Expected Verb", production: :ObjectListPath) if !(data[:Verb])
|
1490
|
+
end
|
1491
|
+
production(:ObjectListPath) do |value|
|
1492
|
+
objects = Array(value[:ObjectPath][:object])
|
1493
|
+
patterns = Array(value[:ObjectPath][:pattern])
|
1494
|
+
value[:_ObjectListPath_1].each do |olp|
|
1495
|
+
objects << olp[:object]
|
1496
|
+
patterns += olp[:pattern]
|
1497
|
+
end
|
1498
|
+
{
|
1499
|
+
object: objects,
|
1500
|
+
pattern: patterns
|
1501
|
+
}
|
1502
|
+
end
|
1503
|
+
|
1504
|
+
# (rule _ObjectListPath_1 (star _ObjectListPath_2))
|
1505
|
+
start_production(:_ObjectListPath_1, as_hash: true) do |data|
|
1506
|
+
data[:Subject] = prod_data[:Subject]
|
1507
|
+
data[:Verb] = prod_data[:Verb]
|
1508
|
+
end
|
1509
|
+
|
1510
|
+
# (rule _ObjectListPath_2 (seq ',' ObjectPath))
|
1511
|
+
start_production(:_ObjectListPath_2, as_hash: true) do |data|
|
1512
|
+
data[:Subject] = prod_data[:Subject]
|
1513
|
+
data[:Verb] = prod_data[:Verb]
|
1514
|
+
end
|
1515
|
+
production(:_ObjectListPath_2) do |value|
|
1516
|
+
value[:ObjectPath]
|
1517
|
+
end
|
1518
|
+
|
1519
|
+
# ObjectPath ::= GraphNodePath AnnotationPath
|
1520
|
+
#
|
1521
|
+
# Adds `:Subject` and `:Verb` to data from input.
|
1522
|
+
#
|
1523
|
+
# Returns patterns and object
|
1524
|
+
start_production(:ObjectPath, as_hash: true) do |data|
|
1525
|
+
data[:Subject] = prod_data[:Subject]
|
1526
|
+
data[:Verb] = prod_data[:Verb]
|
1527
|
+
end
|
1528
|
+
|
1529
|
+
production(:ObjectPath) do |value, data|
|
1530
|
+
subject = data[:Subject]
|
1531
|
+
verb = data[:Verb]
|
1532
|
+
object = value[:GraphNodePath][:object]
|
1533
|
+
patterns = if verb.is_a?(SPARQL::Algebra::Query)
|
1534
|
+
# It's a path
|
1535
|
+
[SPARQL::Algebra::Expression(:path, subject, verb, object)]
|
1536
|
+
else
|
1537
|
+
[RDF::Query::Pattern.new(subject, verb, object)]
|
1538
|
+
end
|
1539
|
+
{
|
1540
|
+
object: object,
|
1541
|
+
pattern: patterns + value[:GraphNodePath][:pattern] + value[:AnnotationPath]
|
1542
|
+
}
|
1543
|
+
end
|
1544
|
+
|
1545
|
+
# Path ::= PathAlternative
|
1546
|
+
#
|
1547
|
+
# Output an IRI or path.
|
1548
|
+
production(:Path) do |value|
|
1549
|
+
value.last[:PathAlternative]
|
1550
|
+
end
|
1551
|
+
|
1552
|
+
# PathAlternative ::= PathSequence ( '|' PathSequence )*
|
1553
|
+
#
|
1554
|
+
# Input is `:PathSequence` containing one or more path objects.
|
1555
|
+
# Output is the resulting path, containing a nested sequence of `Algebra::Alt` connecting the elements from `:PathSequence`, unless there is only one such element, in which case it is added directly.
|
1556
|
+
start_production(:PathAlternative, as_hash: true)
|
1557
|
+
production(:PathAlternative) do |value|
|
1558
|
+
lhs = value[:PathSequence]
|
1559
|
+
while value[:_PathAlternative_1] && !value[:_PathAlternative_1].empty?
|
1560
|
+
rhs = value[:_PathAlternative_1].shift
|
1561
|
+
lhs = SPARQL::Algebra::Expression[:alt, lhs, rhs]
|
1562
|
+
end
|
1563
|
+
lhs
|
1564
|
+
end
|
1565
|
+
|
1566
|
+
# (rule _PathAlternative_2 (seq '|' PathSequence))
|
1567
|
+
start_production(:_PathAlternative_2, as_hash: true)
|
1568
|
+
production(:_PathAlternative_2) do |value|
|
1569
|
+
value[:PathSequence]
|
1570
|
+
end
|
1571
|
+
|
1572
|
+
# PathSequence ::= PathEltOrInverse ( '/' PathEltOrInverse )*
|
1573
|
+
#
|
1574
|
+
# Input is `:PathSequence` containing one or more path objects.
|
1575
|
+
# Output a path containing a nested sequence of `Algebra::Seq` connecting the elements from `:PathSequence`, unless there is only one such element, in which case it is added directly.
|
1576
|
+
start_production(:PathSequence, as_hash: true)
|
1577
|
+
production(:PathSequence) do |value|
|
1578
|
+
lhs = value[:PathEltOrInverse]
|
1579
|
+
while value[:_PathSequence_1] && !value[:_PathSequence_1].empty?
|
1580
|
+
rhs = value[:_PathSequence_1].shift
|
1581
|
+
lhs = SPARQL::Algebra::Expression[:seq, lhs, rhs]
|
1582
|
+
end
|
1583
|
+
lhs
|
1584
|
+
end
|
1585
|
+
|
1586
|
+
# (rule _PathSequence_2 (seq '/' PathEltOrInverse))
|
1587
|
+
start_production(:_PathSequence_2, as_hash: true)
|
1588
|
+
production(:_PathSequence_2) do |value|
|
1589
|
+
value[:PathEltOrInverse]
|
1590
|
+
end
|
1591
|
+
|
1592
|
+
# PathElt ::= PathPrimary PathMod?
|
1593
|
+
#
|
1594
|
+
# (rule PathElt (seq PathPrimary _PathElt_1))
|
1595
|
+
# (rule _PathElt_1 (opt PathMod))
|
1596
|
+
#
|
1597
|
+
# Output is a path, a possibly modified `:PathPrimary`.
|
1598
|
+
start_production(:PathElt, as_hash: true)
|
1599
|
+
production(:PathElt) do |value|
|
1600
|
+
if path_mod = value[:_PathElt_1]
|
1601
|
+
# Add primary path to operand
|
1602
|
+
op_len = path_mod.operands.length
|
1603
|
+
path_mod.operands[op_len-1] = value[:PathPrimary]
|
1604
|
+
path_mod
|
1605
|
+
else
|
1606
|
+
value[:PathPrimary]
|
1607
|
+
end
|
1608
|
+
end
|
1609
|
+
|
1610
|
+
# PathEltOrInverse ::= PathElt | '^' PathElt
|
1611
|
+
#
|
1612
|
+
# Input is `:Path`, or a reversed path if it is an array.
|
1613
|
+
# Output is a possibly reversed path.
|
1614
|
+
production(:PathEltOrInverse) do |value|
|
1615
|
+
if value.is_a?(Array)
|
1616
|
+
SPARQL::Algebra::Expression(:reverse, value.last[:PathElt])
|
1617
|
+
else
|
1618
|
+
value
|
1619
|
+
end
|
1620
|
+
end
|
1621
|
+
|
1622
|
+
# PathMod ::= '*' | '?' | '+' | '{' INTEGER? (',' INTEGER?)? '}'
|
1623
|
+
#
|
1624
|
+
# (rule PathMod (alt '?' '*' '+' _PathMod_1))
|
1625
|
+
# (rule _PathMod_1 (seq '{' _PathMod_2 _PathMod_3 '}'))
|
1626
|
+
# (rule _PathMod_2 (opt INTEGER))
|
1627
|
+
# (rule _PathMod_3 (opt _PathMod_4))
|
1628
|
+
# (rule _PathMod_4 (seq ',' _PathMod_5))
|
1629
|
+
# (rule _PathMod_5 (opt INTEGER))
|
1630
|
+
production(:PathMod) do |value|
|
1631
|
+
if value.is_a?(SPARQL::Algebra::Expression)
|
1632
|
+
value
|
1633
|
+
elsif value
|
1634
|
+
# Last operand added in :PathElt
|
1635
|
+
SPARQL::Algebra::Expression("path#{value}", RDF.nil)
|
1636
|
+
end
|
1637
|
+
end
|
1638
|
+
|
1639
|
+
start_production(:_PathMod_1, as_hash: true)
|
1640
|
+
production(:_PathMod_1) do |value|
|
1641
|
+
raise Error, "expect property range to have integral elements" if
|
1642
|
+
value[:_PathMod_2].nil? && value[:_PathMod_3] == :*
|
1643
|
+
min = value[:_PathMod_2] || 0
|
1644
|
+
max = value[:_PathMod_3] || min
|
1645
|
+
|
1646
|
+
# Last operand added in :PathElt
|
1647
|
+
SPARQL::Algebra::Expression(:pathRange, min, max, RDF.nil)
|
1648
|
+
end
|
1649
|
+
|
1650
|
+
# (rule _PathMod_4 (seq ',' _PathMod_5))
|
1651
|
+
start_production(:_PathMod_4, as_hash: true)
|
1652
|
+
production(:_PathMod_4) do |value|
|
1653
|
+
value[:_PathMod_5] || :*
|
1654
|
+
end
|
1655
|
+
|
1656
|
+
# PathPrimary ::= iri | 'a' | '!' PathNegatedPropertySet | '(' Path ')'
|
1657
|
+
#
|
1658
|
+
# (rule PathPrimary (alt iri 'a' _PathPrimary_1 _PathPrimary_2))
|
1659
|
+
# (rule _PathPrimary_1 (seq '!' PathNegatedPropertySet))
|
1660
|
+
# (rule _PathPrimary_2 (seq '(' Path ')'))
|
1661
|
+
start_production(:PathPrimary, insensitive_strings: false)
|
1662
|
+
production(:PathPrimary) do |value|
|
1663
|
+
if value == 'a'
|
1664
|
+
RDF.type.dup.tap {|a| a.lexical = 'a'}
|
1665
|
+
else
|
1666
|
+
value
|
1667
|
+
end
|
1668
|
+
end
|
1669
|
+
|
1670
|
+
# (rule _PathPrimary_1 (seq '!' PathNegatedPropertySet))
|
1671
|
+
production(:_PathPrimary_1) {|value| value.last[:PathNegatedPropertySet]}
|
1672
|
+
|
1673
|
+
# (rule _PathPrimary_2 (seq '(' Path ')'))
|
1674
|
+
production(:_PathPrimary_2) {|value| value[1][:Path]}
|
1675
|
+
|
1676
|
+
# PathNegatedPropertySet ::= PathOneInPropertySet |
|
1677
|
+
# '('
|
1678
|
+
# ( PathOneInPropertySet
|
1679
|
+
# ( '|' PathOneInPropertySet )*
|
1680
|
+
# )?
|
1681
|
+
# ')'
|
1682
|
+
#
|
1683
|
+
# (rule PathNegatedPropertySet (alt PathOneInPropertySet _PathNegatedPropertySet_1))
|
1684
|
+
# (rule _PathNegatedPropertySet_1 (seq '(' _PathNegatedPropertySet_2 ')'))
|
1685
|
+
# (rule _PathNegatedPropertySet_2 (opt _PathNegatedPropertySet_3))
|
1686
|
+
# (rule _PathNegatedPropertySet_3
|
1687
|
+
# (seq PathOneInPropertySet _PathNegatedPropertySet_4))
|
1688
|
+
# (rule _PathNegatedPropertySet_4 (star _PathNegatedPropertySet_5))
|
1689
|
+
# (rule _PathNegatedPropertySet_5 (seq '|' PathOneInPropertySet))
|
1690
|
+
#
|
1691
|
+
production(:PathNegatedPropertySet) do |value|
|
1692
|
+
SPARQL::Algebra::Expression(:notoneof, *Array(value))
|
1693
|
+
end
|
1694
|
+
|
1695
|
+
# (rule _PathNegatedPropertySet_1 (seq '(' _PathNegatedPropertySet_2 ')'))
|
1696
|
+
production(:_PathNegatedPropertySet_1) do |value|
|
1697
|
+
value[1][:_PathNegatedPropertySet_2]
|
1698
|
+
end
|
1699
|
+
|
1700
|
+
# (rule _PathNegatedPropertySet_3
|
1701
|
+
# (seq PathOneInPropertySet _PathNegatedPropertySet_4))
|
1702
|
+
start_production(:_PathNegatedPropertySet_3, as_hash: true)
|
1703
|
+
production(:_PathNegatedPropertySet_3) do |value|
|
1704
|
+
value[:_PathNegatedPropertySet_4].unshift(value[:PathOneInPropertySet])
|
1705
|
+
end
|
1706
|
+
|
1707
|
+
# (rule _PathNegatedPropertySet_5 (seq '|' PathOneInPropertySet))
|
1708
|
+
production(:_PathNegatedPropertySet_5) do |value|
|
1709
|
+
value.last[:PathOneInPropertySet]
|
1710
|
+
end
|
1711
|
+
|
1712
|
+
# PathOneInPropertySet ::= iri | 'a' | '^' ( iri | 'a' )
|
1713
|
+
#
|
1714
|
+
# (rule PathOneInPropertySet (alt iri 'a' _PathOneInPropertySet_1))
|
1715
|
+
# (rule _PathOneInPropertySet_1 (seq '^' _PathOneInPropertySet_2))
|
1716
|
+
# (rule _PathOneInPropertySet_2 (alt iri 'a'))
|
1717
|
+
start_production(:PathOneInPropertySet, insensitive_strings: false)
|
1718
|
+
production(:PathOneInPropertySet) do |value|
|
1719
|
+
if value == 'a'
|
1720
|
+
RDF.type.dup.tap {|a| a.lexical = 'a'}
|
1721
|
+
elsif value.is_a?(RDF::URI)
|
1722
|
+
value
|
1723
|
+
else
|
1724
|
+
SPARQL::Algebra::Expression(:reverse, value.last[:_PathOneInPropertySet_2])
|
1725
|
+
end
|
1726
|
+
end
|
1727
|
+
|
1728
|
+
# BlankNodePropertyList ::= '[' PropertyListNotEmpty ']'
|
1729
|
+
start_production(:BlankNodePropertyList, as_hash: true) do |data|
|
1730
|
+
data[:Subject] = prod_data[:TriplesNode]
|
1731
|
+
end
|
1732
|
+
production(:BlankNodePropertyList) do |value, data|
|
1733
|
+
{
|
1734
|
+
object: data[:Subject],
|
1735
|
+
pattern: value[:PropertyListNotEmpty]
|
1736
|
+
}
|
1737
|
+
end
|
1738
|
+
|
1739
|
+
# TriplesNode ::= Collection | BlankNodePropertyList
|
1740
|
+
#
|
1741
|
+
# Returns object and patterns
|
1742
|
+
start_production(:TriplesNode) do |data|
|
1743
|
+
data[:TriplesNode] = bnode
|
1744
|
+
end
|
1745
|
+
production(:TriplesNode) do |value, data|
|
1746
|
+
# Record the node for downstream productions XXX
|
1747
|
+
prod_data[:TriplesNode] = data[:TriplesNode]
|
1748
|
+
|
1749
|
+
value.is_a?(Hash) ? value : {object: data[:TriplesNode], pattern: value}
|
1750
|
+
end
|
1751
|
+
|
1752
|
+
# TriplesNodePath ::= CollectionPath | BlankNodePropertyListPath
|
1753
|
+
#
|
1754
|
+
# Returns object and patterns
|
1755
|
+
start_production(:TriplesNodePath) do |data|
|
1756
|
+
# Called after Verb. The prod_data stack should have Subject and Verb elements
|
1757
|
+
data[:TriplesNode] = bnode
|
1758
|
+
end
|
1759
|
+
production(:TriplesNodePath) do |value, data|
|
1760
|
+
# Record the node for downstraem productions
|
1761
|
+
prod_data[:TriplesNode] = data[:TriplesNode]
|
1762
|
+
|
1763
|
+
value.is_a?(Hash) ? value : {object: data[:TriplesNode], pattern: value}
|
1764
|
+
end
|
1765
|
+
|
1766
|
+
# BlankNodePropertyListPath ::= '[' PropertyListPathNotEmpty ']'
|
1767
|
+
#
|
1768
|
+
# Returns object and patterns
|
1769
|
+
start_production(:BlankNodePropertyListPath, as_hash: true) do |data|
|
1770
|
+
data[:Subject] = prod_data[:TriplesNode]
|
1771
|
+
end
|
1772
|
+
production(:BlankNodePropertyListPath) do |value, data|
|
1773
|
+
{
|
1774
|
+
object: data[:Subject],
|
1775
|
+
pattern: value[:PropertyListPathNotEmpty]
|
1776
|
+
}
|
1777
|
+
end
|
1778
|
+
|
1779
|
+
# Collection ::= '(' GraphNode+ ')'
|
1780
|
+
#
|
1781
|
+
# (rule Collection (seq '(' _Collection_1 ')'))
|
1782
|
+
# (rule _Collection_1 (plus GraphNode))
|
1783
|
+
#
|
1784
|
+
# Returns patterns
|
1785
|
+
start_production(:Collection, as_hash: true) do |data|
|
1786
|
+
# Tells the TriplesNode production to collect and not generate statements
|
1787
|
+
data[:Subject] = prod_data[:TriplesNode]
|
1788
|
+
end
|
1789
|
+
production(:Collection) do |value, data|
|
1790
|
+
expand_collection(data[:Subject], value[:_Collection_1])
|
1791
|
+
end
|
1792
|
+
|
1793
|
+
# CollectionPath ::= "(" GraphNodePath+ ")"
|
1794
|
+
#
|
1795
|
+
# (rule CollectionPath (seq '(' _CollectionPath_1 ')'))
|
1796
|
+
# (rule _CollectionPath_1 (plus GraphNodePath))
|
1797
|
+
#
|
1798
|
+
# Returns patterns
|
1799
|
+
start_production(:CollectionPath, as_hash: true) do |data|
|
1800
|
+
# Tells the TriplesNode production to collect and not generate statements
|
1801
|
+
data[:Subject] = prod_data[:TriplesNode]
|
1802
|
+
end
|
1803
|
+
production(:CollectionPath) do |value, data|
|
1804
|
+
expand_collection(data[:Subject], value[:_CollectionPath_1])
|
1805
|
+
end
|
1806
|
+
|
1807
|
+
# AnnotationPath ::= ( Reifier | AnnotationBlockPath )*
|
1808
|
+
#
|
1809
|
+
# Returns patterns
|
1810
|
+
start_production(:AnnotationPath, as_hash: true) do |data|
|
1811
|
+
object = data[:_rept_data].first[:GraphNodePath][:object]
|
1812
|
+
error("AnnotationPath", "Expected Subject", production: :AnnotationPath) unless prod_data[:Subject]
|
1813
|
+
error("AnnotationPath", "Expected Verb", production: :AnnotationPath) unless prod_data[:Verb]
|
1814
|
+
error("AnnotationPath", "Expected Object", production: :AnnotationPath) unless object
|
1815
|
+
data[:curReifier] = nil
|
1816
|
+
data[:TripleTerm] = RDF::Query::Pattern.new(prod_data[:Subject], prod_data[:Verb], object, tripleTerm: true)
|
1817
|
+
end
|
1818
|
+
|
1819
|
+
production(:AnnotationPath) do |value|
|
1820
|
+
value.flatten
|
1821
|
+
end
|
1822
|
+
|
1823
|
+
# AnnotationBlockPath ::= '{|' PropertyListPathNotEmpty '|}'
|
1824
|
+
#
|
1825
|
+
# Beginning the annotationBlock production, if the curReifier is not set, then the curReifier is assigned a fresh RDF blank node and then yields the RDF triple curReifier rdf:reifies curTripleTerm. The curSubject is taken from the curReifier
|
1826
|
+
start_production(:AnnotationBlockPath, as_hash: true) do |data|
|
1827
|
+
# Store AnnotationPath data for reference in PropertyListPathNotEmpty
|
1828
|
+
data[:AnnotationData] = prod_data
|
1829
|
+
data[:emit_tt] = prod_data[:curReifier].nil?
|
1830
|
+
end
|
1831
|
+
|
1832
|
+
production(:AnnotationBlockPath) do |value, data|
|
1833
|
+
patterns = if data[:emit_tt]
|
1834
|
+
reifier = data[:AnnotationData][:curReifier]
|
1835
|
+
[RDF::Query::Pattern.new(reifier, RDF.reifies, prod_data[:TripleTerm])]
|
1836
|
+
else
|
1837
|
+
[]
|
1838
|
+
end
|
1839
|
+
data[:AnnotationData][:curReifier] = nil
|
1840
|
+
patterns += value[:PropertyListPathNotEmpty]
|
1841
|
+
patterns
|
1842
|
+
end
|
1843
|
+
|
1844
|
+
# Annotation ::= ( Reifier | AnnotationBlock )*
|
1845
|
+
#
|
1846
|
+
# Returns patterns
|
1847
|
+
start_production(:Annotation) do |data|
|
1848
|
+
object = data[:_rept_data].first[:GraphNode][:object]
|
1849
|
+
error("AnnotationPath", "Expected Subject", production: :AnnotationPath) unless prod_data[:Subject]
|
1850
|
+
error("AnnotationPath", "Expected Verb", production: :AnnotationPath) unless prod_data[:Verb]
|
1851
|
+
error("AnnotationPath", "Expected Object", production: :AnnotationPath) unless object
|
1852
|
+
data[:curReifier] = nil
|
1853
|
+
data[:TripleTerm] = RDF::Query::Pattern.new(prod_data[:Subject], prod_data[:Verb], object, tripleTerm: true)
|
1854
|
+
end
|
1855
|
+
|
1856
|
+
production(:Annotation) do |value|
|
1857
|
+
value.flatten
|
1858
|
+
end
|
1859
|
+
|
1860
|
+
# AnnotationBlock ::= '{|' PropertyListPathNotEmpty '|}'
|
1861
|
+
#
|
1862
|
+
# Beginning the annotationBlock production, if the curReifier is not set, then the curReifier is assigned a fresh RDF blank node and then yields the RDF triple curReifier rdf:reifies curTripleTerm. The curSubject is taken from the curReifier
|
1863
|
+
start_production(:AnnotationBlock, as_hash: true) do |data|
|
1864
|
+
# Store AnnotationPath data for reference in PropertyListPathNotEmpty
|
1865
|
+
data[:AnnotationData] = prod_data
|
1866
|
+
data[:emit_tt] = prod_data[:curReifier].nil?
|
1867
|
+
end
|
1868
|
+
|
1869
|
+
production(:AnnotationBlock) do |value, data|
|
1870
|
+
patterns = []
|
1871
|
+
if data[:emit_tt]
|
1872
|
+
reifier = data[:AnnotationData][:curReifier]
|
1873
|
+
patterns = [RDF::Query::Pattern.new(reifier, RDF.reifies, prod_data[:TripleTerm])]
|
1874
|
+
end
|
1875
|
+
data[:AnnotationData][:curReifier] = nil
|
1876
|
+
patterns += value[:PropertyListNotEmpty]
|
1877
|
+
patterns
|
1878
|
+
end
|
1879
|
+
|
1880
|
+
# GraphNode ::= VarOrTerm | TriplesNode
|
1881
|
+
#
|
1882
|
+
# Returns object and patterns
|
1883
|
+
production(:GraphNode) do |value|
|
1884
|
+
value.is_a?(Hash) ? value : {object: value, pattern: []}
|
1885
|
+
end
|
1886
|
+
|
1887
|
+
# GraphNodePath ::= VarOrTerm | TriplesNodePath | ReifiedTriple
|
1888
|
+
#
|
1889
|
+
# Returns object and patterns
|
1890
|
+
production(:GraphNodePath) do |value|
|
1891
|
+
value.is_a?(Hash) ? value : {object: value, pattern: []}
|
1892
|
+
end
|
1893
|
+
|
1894
|
+
# ReifiedTriple ::= '<<' ReifiedTripleSubject Verb ReifiedTripleObject Reifier? '>>'
|
1895
|
+
#
|
1896
|
+
# (rule ReifiedTriple
|
1897
|
+
# (seq '<<' ReifiedTripleSubject Verb ReifiedTripleObject _ReifiedTriple_1 '>>'))
|
1898
|
+
# (rule _ReifiedTriple_1 (opt Reifier))
|
1899
|
+
#
|
1900
|
+
# Returns reifier and pattern. Saves reifier in prod_data
|
1901
|
+
start_production(:ReifiedTriple, as_hash: true)
|
1902
|
+
production(:ReifiedTriple) do |value, data|
|
1903
|
+
subject = value[:ReifiedTripleSubject]
|
1904
|
+
predicate = value[:Verb]
|
1905
|
+
object = value[:ReifiedTripleObject]
|
1906
|
+
reifier = data[:curReifier] || bnode
|
1907
|
+
prod_data[:Subject] = reifier
|
1908
|
+
|
1909
|
+
{
|
1910
|
+
object: reifier,
|
1911
|
+
pattern: [RDF::Query::Pattern.new(
|
1912
|
+
reifier,
|
1913
|
+
RDF.reifies,
|
1914
|
+
RDF::Query::Pattern.new(subject, predicate, object, tripleTerm: true))]
|
1915
|
+
}
|
1916
|
+
end
|
1917
|
+
|
1918
|
+
# TripleTerm ::= ::= '<<(' TripleTermSubject Verb TripleTermObject ')>>'
|
1919
|
+
#
|
1920
|
+
# Input is subject, verb and object.
|
1921
|
+
# Output is a triple term.
|
1922
|
+
start_production(:TripleTerm, as_hash: true)
|
1923
|
+
production(:TripleTerm) do |value|
|
1924
|
+
RDF::Query::Pattern.new(value[:TripleTermSubject], value[:Verb], value[:TripleTermObject], tripleTerm: true)
|
1925
|
+
end
|
1926
|
+
|
1927
|
+
# TripleTermData ::= '<<(' TripleTermDataSubject ( iri | 'a' ) TripleTermDataObject ')>>'
|
1928
|
+
#
|
1929
|
+
# (rule TripleTermData
|
1930
|
+
# (seq '<<(' TripleTermDataSubject _TripleTermData_1 TripleTermDataObject ')>>'))
|
1931
|
+
# (rule _TripleTermData_1 (alt iri 'a'))
|
1932
|
+
start_production(:TripleTermData, as_hash: true)
|
1933
|
+
production(:TripleTermData) do |value|
|
1934
|
+
RDF::Query::Pattern.new(value[:TripleTermDataSubject], value[:_TripleTermData_1], value[:TripleTermDataObject], tripleTerm: true)
|
1935
|
+
end
|
1936
|
+
|
1937
|
+
# (rule _TripleTermData_1 (alt iri 'a'))
|
1938
|
+
production(:_TripleTermData_1) do |value|
|
1939
|
+
if value == 'a'
|
1940
|
+
RDF.type.dup.tap {|a| a.lexical = 'a'}
|
1941
|
+
else
|
1942
|
+
value
|
1943
|
+
end
|
1944
|
+
end
|
1945
|
+
|
1946
|
+
# Expression ::= ConditionalOrExpression
|
1947
|
+
production(:Expression) do |value|
|
1948
|
+
value.first[:ConditionalOrExpression]
|
1949
|
+
end
|
1950
|
+
|
1951
|
+
# ConditionalOrExpression ::= ConditionalAndExpression
|
1952
|
+
# ( '||' ConditionalAndExpression )*
|
1953
|
+
#
|
1954
|
+
# (rule ConditionalOrExpression
|
1955
|
+
# (seq ConditionalAndExpression _ConditionalOrExpression_1))
|
1956
|
+
# (rule _ConditionalOrExpression_1 (star _ConditionalOrExpression_2))
|
1957
|
+
start_production(:ConditionalOrExpression, as_hash: true)
|
1958
|
+
production(:ConditionalOrExpression) do |value|
|
1959
|
+
add_operator_expressions(value[:ConditionalAndExpression], *value[:_ConditionalOrExpression_1])
|
1960
|
+
end
|
1961
|
+
|
1962
|
+
# (rule _ConditionalOrExpression_2 (seq '||' ConditionalAndExpression))
|
1963
|
+
production(:_ConditionalOrExpression_2) do |value|
|
1964
|
+
[:or, value.last[:ConditionalAndExpression]]
|
1965
|
+
end
|
1966
|
+
|
1967
|
+
# ConditionalAndExpression ::= ValueLogical ( '&&' ValueLogical )*
|
1968
|
+
#
|
1969
|
+
# (rule ConditionalAndExpression (seq ValueLogical _ConditionalAndExpression_1))
|
1970
|
+
# (rule _ConditionalAndExpression_1 (star _ConditionalAndExpression_2))
|
1971
|
+
start_production(:ConditionalAndExpression, as_hash: true)
|
1972
|
+
production(:ConditionalAndExpression) do |value|
|
1973
|
+
add_operator_expressions(value[:ValueLogical], *value[:_ConditionalAndExpression_1])
|
1974
|
+
end
|
1975
|
+
|
1976
|
+
# (rule _ConditionalAndExpression_2 (seq '&&' ValueLogical))
|
1977
|
+
production(:_ConditionalAndExpression_2) do |value|
|
1978
|
+
[:and, value.last[:ValueLogical]]
|
1979
|
+
end
|
1980
|
+
|
1981
|
+
# ValueLogical ::= RelationalExpression
|
1982
|
+
production(:ValueLogical) do |value|
|
1983
|
+
value.first[:RelationalExpression]
|
1984
|
+
end
|
1985
|
+
|
1986
|
+
# RelationalExpression ::= NumericExpression
|
1987
|
+
# ( '=' NumericExpression
|
1988
|
+
# | '!=' NumericExpression
|
1989
|
+
# | '<' NumericExpression
|
1990
|
+
# | '>' NumericExpression
|
1991
|
+
# | '<=' NumericExpression
|
1992
|
+
# | '>=' NumericExpression
|
1993
|
+
# | 'IN' ExpressionList
|
1994
|
+
# | 'NOT' 'IN' ExpressionList
|
1995
|
+
# )?
|
1996
|
+
#
|
1997
|
+
# (rule RelationalExpression (seq NumericExpression _RelationalExpression_1))
|
1998
|
+
# (rule _RelationalExpression_1 (opt _RelationalExpression_2))
|
1999
|
+
# (rule _RelationalExpression_2
|
2000
|
+
# (alt _RelationalExpression_3 _RelationalExpression_4 _RelationalExpression_5
|
2001
|
+
# _RelationalExpression_6 _RelationalExpression_7 _RelationalExpression_8
|
2002
|
+
# _RelationalExpression_9 _RelationalExpression_10 ))
|
2003
|
+
# (rule _RelationalExpression_3 (seq '=' NumericExpression))
|
2004
|
+
# (rule _RelationalExpression_4 (seq '!=' NumericExpression))
|
2005
|
+
# (rule _RelationalExpression_5 (seq '<' NumericExpression))
|
2006
|
+
# (rule _RelationalExpression_6 (seq '>' NumericExpression))
|
2007
|
+
# (rule _RelationalExpression_7 (seq '<=' NumericExpression))
|
2008
|
+
# (rule _RelationalExpression_8 (seq '>=' NumericExpression))
|
2009
|
+
# (rule _RelationalExpression_9 (seq 'IN' ExpressionList))
|
2010
|
+
# (rule _RelationalExpression_10 (seq 'NOT' 'IN' ExpressionList))
|
2011
|
+
#
|
2012
|
+
start_production(:RelationalExpression, as_hash: true)
|
2013
|
+
production(:RelationalExpression) do |value|
|
2014
|
+
if Array(value[:_RelationalExpression_1]).empty?
|
2015
|
+
value[:NumericExpression]
|
2016
|
+
else
|
2017
|
+
comparator, rhs = value[:_RelationalExpression_1]
|
2018
|
+
SPARQL::Algebra::Expression.for(comparator, value[:NumericExpression], *Array(rhs))
|
2019
|
+
end
|
2020
|
+
end
|
2021
|
+
|
2022
|
+
# (rule _RelationalExpression_2
|
2023
|
+
# (alt _RelationalExpression_3 _RelationalExpression_4 _RelationalExpression_5
|
2024
|
+
# _RelationalExpression_6 _RelationalExpression_7 _RelationalExpression_8
|
2025
|
+
# _RelationalExpression_9 _RelationalExpression_10 ))
|
2026
|
+
production(:_RelationalExpression_2) do |value|
|
2027
|
+
if value.last.is_a?(Hash)
|
2028
|
+
comparator = value.first.values.first
|
2029
|
+
rhs = value.last.values.first
|
2030
|
+
[comparator, rhs]
|
2031
|
+
else
|
2032
|
+
value
|
2033
|
+
end
|
2034
|
+
end
|
2035
|
+
|
2036
|
+
# (rule _RelationalExpression_9 (seq 'IN' ExpressionList))
|
2037
|
+
start_production(:_RelationalExpression_9, as_hash: true, insensitve_strings: :upper)
|
2038
|
+
production(:_RelationalExpression_9) do |value|
|
2039
|
+
[:in, value[:ExpressionList]]
|
2040
|
+
end
|
2041
|
+
|
2042
|
+
# (rule _RelationalExpression_10 (seq 'NOT' 'IN' ExpressionList))
|
2043
|
+
start_production(:_RelationalExpression_10, as_hash: true, insensitve_strings: :upper)
|
2044
|
+
production(:_RelationalExpression_10) do |value|
|
2045
|
+
[:notin, value[:ExpressionList]]
|
2046
|
+
end
|
2047
|
+
|
2048
|
+
# NumericExpression::= AdditiveExpression
|
2049
|
+
production(:NumericExpression) do |value|
|
2050
|
+
value.first[:AdditiveExpression]
|
2051
|
+
end
|
2052
|
+
|
2053
|
+
# AdditiveExpression ::= MultiplicativeExpression
|
2054
|
+
# ( '+' MultiplicativeExpression
|
2055
|
+
# | '-' MultiplicativeExpression
|
2056
|
+
# | ( NumericLiteralPositive
|
2057
|
+
# | NumericLiteralNegative )
|
2058
|
+
# ( ( '*' UnaryExpression )
|
2059
|
+
# | ( '/' UnaryExpression ) )*
|
2060
|
+
# )*
|
2061
|
+
start_production(:AdditiveExpression, as_hash: true)
|
2062
|
+
production(:AdditiveExpression) do |value|
|
2063
|
+
add_operator_expressions(value[:MultiplicativeExpression], *value[:_AdditiveExpression_1])
|
2064
|
+
end
|
2065
|
+
|
2066
|
+
# (rule _AdditiveExpression_3 (seq '+' MultiplicativeExpression))
|
2067
|
+
production(:_AdditiveExpression_3) do |value|
|
2068
|
+
[:+, value.last[:MultiplicativeExpression]]
|
2069
|
+
end
|
2070
|
+
|
2071
|
+
# (rule _AdditiveExpression_4 (seq '-' MultiplicativeExpression))
|
2072
|
+
production(:_AdditiveExpression_4) do |value|
|
2073
|
+
[:-, value.last[:MultiplicativeExpression]]
|
2074
|
+
end
|
2075
|
+
|
2076
|
+
# (rule _AdditiveExpression_5 (seq _AdditiveExpression_6 _AdditiveExpression_7))
|
2077
|
+
# (rule _AdditiveExpression_6 (alt NumericLiteralPositive NumericLiteralNegative))
|
2078
|
+
# (rule _AdditiveExpression_7 (star _AdditiveExpression_8))
|
2079
|
+
# (rule _AdditiveExpression_8 (alt _AdditiveExpression_9 _AdditiveExpression_10))
|
2080
|
+
start_production(:_AdditiveExpression_5, as_hash: true)
|
2081
|
+
production(:_AdditiveExpression_5) do |value|
|
2082
|
+
op = value[:_AdditiveExpression_6] < 0 ? :- : :+
|
2083
|
+
lhs = value[:_AdditiveExpression_6].abs + 0
|
2084
|
+
[op, add_operator_expressions(lhs, *value[:_AdditiveExpression_7])]
|
2085
|
+
end
|
2086
|
+
|
2087
|
+
# (rule _AdditiveExpression_9 (seq '*' UnaryExpression))
|
2088
|
+
production(:_AdditiveExpression_9) do |value|
|
2089
|
+
[:*, value.last[:UnaryExpression]]
|
2090
|
+
end
|
2091
|
+
|
2092
|
+
# (rule _AdditiveExpression_10 (seq '/' UnaryExpression))
|
2093
|
+
production(:_AdditiveExpression_10) do |value|
|
2094
|
+
[:/, value.last[:UnaryExpression]]
|
2095
|
+
end
|
2096
|
+
|
2097
|
+
# MultiplicativeExpression ::= UnaryExpression
|
2098
|
+
# ( '*' UnaryExpression
|
2099
|
+
# | '/' UnaryExpression )*
|
2100
|
+
start_production(:MultiplicativeExpression, as_hash: true)
|
2101
|
+
production(:MultiplicativeExpression) do |value|
|
2102
|
+
add_operator_expressions(value[:UnaryExpression], *value[:_MultiplicativeExpression_1])
|
2103
|
+
end
|
2104
|
+
|
2105
|
+
# (rule _MultiplicativeExpression_3 (seq '*' UnaryExpression))
|
2106
|
+
production(:_MultiplicativeExpression_3) do |value|
|
2107
|
+
[:*, value.last[:UnaryExpression]]
|
2108
|
+
end
|
2109
|
+
|
2110
|
+
# (rule _MultiplicativeExpression_4 (seq '/' UnaryExpression))
|
2111
|
+
production(:_MultiplicativeExpression_4) do |value|
|
2112
|
+
[:/, value.last[:UnaryExpression]]
|
2113
|
+
end
|
2114
|
+
|
2115
|
+
# UnaryExpression ::= '!' PrimaryExpression
|
2116
|
+
# | '+' PrimaryExpression
|
2117
|
+
# | '-' PrimaryExpression
|
2118
|
+
# | PrimaryExpression
|
2119
|
+
#
|
2120
|
+
# (rule UnaryExpression
|
2121
|
+
# (alt _UnaryExpression_1 _UnaryExpression_2 _UnaryExpression_3 PrimaryExpression))
|
2122
|
+
# (rule _UnaryExpression_1 (seq '!' PrimaryExpression))
|
2123
|
+
# (rule _UnaryExpression_2 (seq '+' PrimaryExpression))
|
2124
|
+
# (rule _UnaryExpression_3 (seq '-' PrimaryExpression))
|
2125
|
+
|
2126
|
+
# (rule _UnaryExpression_1 (seq '!' PrimaryExpression))
|
2127
|
+
production(:_UnaryExpression_1) do |value|
|
2128
|
+
SPARQL::Algebra::Expression[:not, value.last[:PrimaryExpression]]
|
2129
|
+
end
|
2130
|
+
|
2131
|
+
# (rule _UnaryExpression_2 (seq '+' PrimaryExpression))
|
2132
|
+
production(:_UnaryExpression_2) do |value|
|
2133
|
+
value.last[:PrimaryExpression]
|
2134
|
+
end
|
2135
|
+
|
2136
|
+
# (rule _UnaryExpression_3 (seq '-' PrimaryExpression))
|
2137
|
+
production(:_UnaryExpression_3) do |value|
|
2138
|
+
expr = value.last[:PrimaryExpression]
|
2139
|
+
if expr.is_a?(RDF::Literal::Numeric)
|
2140
|
+
-expr
|
2141
|
+
else
|
2142
|
+
SPARQL::Algebra::Expression[:"-", expr]
|
2143
|
+
end
|
2144
|
+
end
|
2145
|
+
|
2146
|
+
# ExprTripleTerm ::= '<<(' ExprTripleTermSubject Verb ExprTripleTermObject ')>>'
|
2147
|
+
start_production(:ExprTripleTerm, as_hash: true)
|
2148
|
+
production(:ExprTripleTerm) do |value|
|
2149
|
+
subject = value[:ExprTripleTermSubject]
|
2150
|
+
predicate = value[:Verb]
|
2151
|
+
object = value[:ExprTripleTermObject]
|
2152
|
+
RDF::Query::Pattern.new(subject, predicate, object, tripleTerm: true)
|
2153
|
+
end
|
2154
|
+
|
2155
|
+
# BrackettedExpression ::= '(' Expression ')'
|
2156
|
+
production(:BrackettedExpression) do |value|
|
2157
|
+
value[1][:Expression]
|
2158
|
+
end
|
2159
|
+
|
2160
|
+
# (rule _BuiltInCall_1 (seq 'STR' '(' Expression ')'))
|
2161
|
+
start_production(:_BuiltInCall_1, as_hash: true)
|
2162
|
+
production(:_BuiltInCall_1) do |value|
|
2163
|
+
SPARQL::Algebra::Operator::Str.new(value[:Expression])
|
2164
|
+
end
|
2165
|
+
|
2166
|
+
# (rule _BuiltInCall_2 (seq 'LANG' '(' Expression ')'))
|
2167
|
+
start_production(:_BuiltInCall_2, as_hash: true)
|
2168
|
+
production(:_BuiltInCall_2) do |value|
|
2169
|
+
SPARQL::Algebra::Operator::Lang.new(value[:Expression])
|
2170
|
+
end
|
2171
|
+
|
2172
|
+
# (rule _BuiltInCall_3 (seq 'LANGMATCHES' '(' Expression ',' Expression ')'))
|
2173
|
+
start_production(:_BuiltInCall_3, as_hash: false)
|
2174
|
+
production(:_BuiltInCall_3) do |value|
|
2175
|
+
SPARQL::Algebra::Operator::LangMatches.new(value[2][:Expression], value[4][:Expression])
|
2176
|
+
end
|
2177
|
+
|
2178
|
+
# (rule _BuiltInCall_4 (seq 'DATATYPE' '(' Expression ')'))
|
2179
|
+
start_production(:_BuiltInCall_4, as_hash: true)
|
2180
|
+
production(:_BuiltInCall_4) do |value|
|
2181
|
+
SPARQL::Algebra::Operator::Datatype.new(value[:Expression])
|
2182
|
+
end
|
2183
|
+
|
2184
|
+
# (rule _BuiltInCall_5 (seq 'BOUND' '(' Var ')'))
|
2185
|
+
start_production(:_BuiltInCall_5, as_hash: true)
|
2186
|
+
production(:_BuiltInCall_5) do |value|
|
2187
|
+
SPARQL::Algebra::Operator::Bound.new(value[:Var])
|
2188
|
+
end
|
2189
|
+
|
2190
|
+
# (rule _BuiltInCall_6 (seq 'IRI' '(' Expression ')'))
|
2191
|
+
start_production(:_BuiltInCall_6, as_hash: true)
|
2192
|
+
production(:_BuiltInCall_6) do |value|
|
2193
|
+
SPARQL::Algebra::Operator::IRI.new(value[:Expression])
|
2194
|
+
end
|
2195
|
+
|
2196
|
+
# (rule _BuiltInCall_7 (seq 'URI' '(' Expression ')'))
|
2197
|
+
start_production(:_BuiltInCall_7, as_hash: true)
|
2198
|
+
production(:_BuiltInCall_7) do |value|
|
2199
|
+
SPARQL::Algebra::Operator::IRI.new(value[:Expression])
|
2200
|
+
end
|
2201
|
+
|
2202
|
+
# (rule _BuiltInCall_8 (seq 'BNODE' _BuiltInCall_57))
|
2203
|
+
# (rule _BuiltInCall_57 (alt _BuiltInCall_58 NIL))
|
2204
|
+
# (rule _BuiltInCall_58 (seq '(' Expression ')'))
|
2205
|
+
start_production(:_BuiltInCall_8, as_hash: true)
|
2206
|
+
production(:_BuiltInCall_8) do |value|
|
2207
|
+
if value[:_BuiltInCall_57].is_a?(RDF::Term)
|
2208
|
+
SPARQL::Algebra::Operator::BNode.new
|
2209
|
+
else
|
2210
|
+
SPARQL::Algebra::Operator::BNode.new(value[:_BuiltInCall_57][1][:Expression])
|
2211
|
+
end
|
2212
|
+
end
|
2213
|
+
|
2214
|
+
# (rule _BuiltInCall_9 (seq 'RAND' NIL))
|
2215
|
+
start_production(:_BuiltInCall_9, as_hash: true)
|
2216
|
+
production(:_BuiltInCall_9) do |value|
|
2217
|
+
SPARQL::Algebra::Operator::Rand.new
|
2218
|
+
end
|
2219
|
+
|
2220
|
+
# (rule _BuiltInCall_10 (seq 'ABS' '(' Expression ')'))
|
2221
|
+
start_production(:_BuiltInCall_10, as_hash: true)
|
2222
|
+
production(:_BuiltInCall_10) do |value|
|
2223
|
+
SPARQL::Algebra::Operator::Abs.new(value[:Expression])
|
2224
|
+
end
|
2225
|
+
|
2226
|
+
# (rule _BuiltInCall_11 (seq 'CEIL' '(' Expression ')'))
|
2227
|
+
start_production(:_BuiltInCall_11, as_hash: true)
|
2228
|
+
production(:_BuiltInCall_11) do |value|
|
2229
|
+
SPARQL::Algebra::Operator::Ceil.new(value[:Expression])
|
2230
|
+
end
|
2231
|
+
|
2232
|
+
# (rule _BuiltInCall_12 (seq 'FLOOR' '(' Expression ')'))
|
2233
|
+
start_production(:_BuiltInCall_12, as_hash: true)
|
2234
|
+
production(:_BuiltInCall_12) do |value|
|
2235
|
+
SPARQL::Algebra::Operator::Floor.new(value[:Expression])
|
2236
|
+
end
|
2237
|
+
|
2238
|
+
# (rule _BuiltInCall_13 (seq 'ROUND' '(' Expression ')'))
|
2239
|
+
start_production(:_BuiltInCall_13, as_hash: true)
|
2240
|
+
production(:_BuiltInCall_13) do |value|
|
2241
|
+
SPARQL::Algebra::Operator::Round.new(value[:Expression])
|
2242
|
+
end
|
2243
|
+
|
2244
|
+
# (rule _BuiltInCall_14 (seq 'CONCAT' ExpressionList))
|
2245
|
+
start_production(:_BuiltInCall_14, as_hash: true)
|
2246
|
+
production(:_BuiltInCall_14) do |value|
|
2247
|
+
SPARQL::Algebra::Operator::Concat.new(*value[:ExpressionList])
|
2248
|
+
end
|
2249
|
+
|
2250
|
+
# (rule _BuiltInCall_15 (seq 'STRLEN' '(' Expression ')'))
|
2251
|
+
start_production(:_BuiltInCall_15, as_hash: true)
|
2252
|
+
production(:_BuiltInCall_15) do |value|
|
2253
|
+
SPARQL::Algebra::Operator::StrLen.new(value[:Expression])
|
2254
|
+
end
|
2255
|
+
|
2256
|
+
# (rule _BuiltInCall_16 (seq 'UCASE' '(' Expression ')'))
|
2257
|
+
start_production(:_BuiltInCall_16, as_hash: true)
|
2258
|
+
production(:_BuiltInCall_16) do |value|
|
2259
|
+
SPARQL::Algebra::Operator::UCase.new(value[:Expression])
|
2260
|
+
end
|
2261
|
+
|
2262
|
+
# (rule _BuiltInCall_17 (seq 'LCASE' '(' Expression ')'))
|
2263
|
+
start_production(:_BuiltInCall_17, as_hash: true)
|
2264
|
+
production(:_BuiltInCall_17) do |value|
|
2265
|
+
SPARQL::Algebra::Operator::LCase.new(value[:Expression])
|
2266
|
+
end
|
2267
|
+
|
2268
|
+
# (rule _BuiltInCall_18 (seq 'ENCODE_FOR_URI' '(' Expression ')'))
|
2269
|
+
start_production(:_BuiltInCall_18, as_hash: true)
|
2270
|
+
production(:_BuiltInCall_18) do |value|
|
2271
|
+
SPARQL::Algebra::Operator::EncodeForURI.new(value[:Expression])
|
2272
|
+
end
|
2273
|
+
|
2274
|
+
# (rule _BuiltInCall_19 (seq 'CONTAINS' '(' Expression ',' Expression ')'))
|
2275
|
+
production(:_BuiltInCall_19) do |value|
|
2276
|
+
SPARQL::Algebra::Operator::Contains.new(value[2][:Expression], value[4][:Expression])
|
2277
|
+
end
|
2278
|
+
|
2279
|
+
# (rule _BuiltInCall_20 (seq 'STRSTARTS' '(' Expression ',' Expression ')'))
|
2280
|
+
production(:_BuiltInCall_20) do |value|
|
2281
|
+
SPARQL::Algebra::Operator::StrStarts.new(value[2][:Expression], value[4][:Expression])
|
2282
|
+
end
|
2283
|
+
|
2284
|
+
# (rule _BuiltInCall_21 (seq 'STRENDS' '(' Expression ',' Expression ')'))
|
2285
|
+
production(:_BuiltInCall_21) do |value|
|
2286
|
+
SPARQL::Algebra::Operator::StrEnds.new(value[2][:Expression], value[4][:Expression])
|
2287
|
+
end
|
2288
|
+
|
2289
|
+
# (rule _BuiltInCall_22 (seq 'STRBEFORE' '(' Expression ',' Expression ')'))
|
2290
|
+
production(:_BuiltInCall_22) do |value|
|
2291
|
+
SPARQL::Algebra::Operator::StrBefore.new(value[2][:Expression], value[4][:Expression])
|
2292
|
+
end
|
2293
|
+
|
2294
|
+
# (rule _BuiltInCall_23 (seq 'STRAFTER' '(' Expression ',' Expression ')'))
|
2295
|
+
production(:_BuiltInCall_23) do |value|
|
2296
|
+
SPARQL::Algebra::Operator::StrAfter.new(value[2][:Expression], value[4][:Expression])
|
2297
|
+
end
|
2298
|
+
|
2299
|
+
# (rule _BuiltInCall_24 (seq 'YEAR' '(' Expression ')'))
|
2300
|
+
start_production(:_BuiltInCall_24, as_hash: true)
|
2301
|
+
production(:_BuiltInCall_24) do |value|
|
2302
|
+
SPARQL::Algebra::Operator::Year.new(value[:Expression])
|
2303
|
+
end
|
2304
|
+
|
2305
|
+
# (rule _BuiltInCall_25 (seq 'MONTH' '(' Expression ')'))
|
2306
|
+
start_production(:_BuiltInCall_25, as_hash: true)
|
2307
|
+
production(:_BuiltInCall_25) do |value|
|
2308
|
+
SPARQL::Algebra::Operator::Month.new(value[:Expression])
|
2309
|
+
end
|
2310
|
+
|
2311
|
+
# (rule _BuiltInCall_26 (seq 'DAY' '(' Expression ')'))
|
2312
|
+
start_production(:_BuiltInCall_26, as_hash: true)
|
2313
|
+
production(:_BuiltInCall_26) do |value|
|
2314
|
+
SPARQL::Algebra::Operator::Day.new(value[:Expression])
|
2315
|
+
end
|
2316
|
+
|
2317
|
+
# (rule _BuiltInCall_27 (seq 'HOURS' '(' Expression ')'))
|
2318
|
+
start_production(:_BuiltInCall_27, as_hash: true)
|
2319
|
+
production(:_BuiltInCall_27) do |value|
|
2320
|
+
SPARQL::Algebra::Operator::Hours.new(value[:Expression])
|
2321
|
+
end
|
2322
|
+
|
2323
|
+
# (rule _BuiltInCall_28 (seq 'MINUTES' '(' Expression ')'))
|
2324
|
+
start_production(:_BuiltInCall_28, as_hash: true)
|
2325
|
+
production(:_BuiltInCall_28) do |value|
|
2326
|
+
SPARQL::Algebra::Operator::Minutes.new(value[:Expression])
|
2327
|
+
end
|
2328
|
+
|
2329
|
+
# (rule _BuiltInCall_29 (seq 'SECONDS' '(' Expression ')'))
|
2330
|
+
start_production(:_BuiltInCall_29, as_hash: true)
|
2331
|
+
production(:_BuiltInCall_29) do |value|
|
2332
|
+
SPARQL::Algebra::Operator::Seconds.new(value[:Expression])
|
2333
|
+
end
|
2334
|
+
|
2335
|
+
# (rule _BuiltInCall_30 (seq 'TIMEZONE' '(' Expression ')'))
|
2336
|
+
start_production(:_BuiltInCall_30, as_hash: true)
|
2337
|
+
production(:_BuiltInCall_30) do |value|
|
2338
|
+
SPARQL::Algebra::Operator::Timezone.new(value[:Expression])
|
2339
|
+
end
|
2340
|
+
|
2341
|
+
# (rule _BuiltInCall_31 (seq 'TZ' '(' Expression ')'))
|
2342
|
+
start_production(:_BuiltInCall_31, as_hash: true)
|
2343
|
+
production(:_BuiltInCall_31) do |value|
|
2344
|
+
SPARQL::Algebra::Operator::TZ.new(value[:Expression])
|
2345
|
+
end
|
2346
|
+
|
2347
|
+
# (rule _BuiltInCall_32 (seq 'NOW' NIL))
|
2348
|
+
start_production(:_BuiltInCall_32, as_hash: true)
|
2349
|
+
production(:_BuiltInCall_32) do |value|
|
2350
|
+
SPARQL::Algebra::Operator::Now.new
|
2351
|
+
end
|
2352
|
+
|
2353
|
+
# (rule _BuiltInCall_33 (seq 'UUID' NIL))
|
2354
|
+
start_production(:_BuiltInCall_33, as_hash: true)
|
2355
|
+
production(:_BuiltInCall_33) do |value|
|
2356
|
+
SPARQL::Algebra::Operator::UUID.new
|
2357
|
+
end
|
2358
|
+
|
2359
|
+
# (rule _BuiltInCall_34 (seq 'STRUUID' NIL))
|
2360
|
+
start_production(:_BuiltInCall_34, as_hash: true)
|
2361
|
+
production(:_BuiltInCall_34) do |value|
|
2362
|
+
SPARQL::Algebra::Operator::StrUUID.new
|
2363
|
+
end
|
2364
|
+
|
2365
|
+
# (rule _BuiltInCall_35 (seq 'MD5' '(' Expression ')'))
|
2366
|
+
start_production(:_BuiltInCall_35, as_hash: true)
|
2367
|
+
production(:_BuiltInCall_35) do |value|
|
2368
|
+
SPARQL::Algebra::Operator::MD5.new(value[:Expression])
|
2369
|
+
end
|
2370
|
+
|
2371
|
+
# (rule _BuiltInCall_36 (seq 'SHA1' '(' Expression ')'))
|
2372
|
+
start_production(:_BuiltInCall_36, as_hash: true)
|
2373
|
+
production(:_BuiltInCall_36) do |value|
|
2374
|
+
SPARQL::Algebra::Operator::SHA1.new(value[:Expression])
|
2375
|
+
end
|
2376
|
+
|
2377
|
+
# (rule _BuiltInCall_37 (seq 'SHA224' '(' Expression ')'))
|
2378
|
+
start_production(:_BuiltInCall_37, as_hash: true)
|
2379
|
+
production(:_BuiltInCall_37) do |value|
|
2380
|
+
SPARQL::Algebra::Operator::SHA224.new(value[:Expression])
|
2381
|
+
end
|
2382
|
+
|
2383
|
+
# (rule _BuiltInCall_38 (seq 'SHA256' '(' Expression ')'))
|
2384
|
+
start_production(:_BuiltInCall_38, as_hash: true)
|
2385
|
+
production(:_BuiltInCall_38) do |value|
|
2386
|
+
SPARQL::Algebra::Operator::SHA256.new(value[:Expression])
|
2387
|
+
end
|
2388
|
+
|
2389
|
+
# (rule _BuiltInCall_39 (seq 'SHA384' '(' Expression ')'))
|
2390
|
+
start_production(:_BuiltInCall_39, as_hash: true)
|
2391
|
+
production(:_BuiltInCall_39) do |value|
|
2392
|
+
SPARQL::Algebra::Operator::SHA384.new(value[:Expression])
|
2393
|
+
end
|
2394
|
+
|
2395
|
+
# (rule _BuiltInCall_40 (seq 'SHA512' '(' Expression ')'))
|
2396
|
+
start_production(:_BuiltInCall_40, as_hash: true)
|
2397
|
+
production(:_BuiltInCall_40) do |value|
|
2398
|
+
SPARQL::Algebra::Operator::SHA512.new(value[:Expression])
|
2399
|
+
end
|
2400
|
+
|
2401
|
+
# (rule _BuiltInCall_41 (seq 'COALESCE' ExpressionList))
|
2402
|
+
start_production(:_BuiltInCall_41, as_hash: true)
|
2403
|
+
production(:_BuiltInCall_41) do |value|
|
2404
|
+
SPARQL::Algebra::Operator::Coalesce.new(*value[:ExpressionList])
|
2405
|
+
end
|
2406
|
+
|
2407
|
+
# (rule _BuiltInCall_42 (seq 'IF' '(' Expression ',' Expression ',' Expression ')'))
|
2408
|
+
production(:_BuiltInCall_42) do |value|
|
2409
|
+
SPARQL::Algebra::Operator::If.new(value[2][:Expression], value[4][:Expression], value[6][:Expression])
|
2410
|
+
end
|
2411
|
+
|
2412
|
+
# (rule _BuiltInCall_43 (seq 'STRLANG' '(' Expression ',' Expression ')'))
|
2413
|
+
production(:_BuiltInCall_43) do |value|
|
2414
|
+
SPARQL::Algebra::Operator::StrLang.new(value[2][:Expression], value[4][:Expression])
|
2415
|
+
end
|
2416
|
+
|
2417
|
+
# (rule _BuiltInCall_44 (seq 'STRDT' '(' Expression ',' Expression ')'))
|
2418
|
+
production(:_BuiltInCall_44) do |value|
|
2419
|
+
SPARQL::Algebra::Operator::StrDT.new(value[2][:Expression], value[4][:Expression])
|
2420
|
+
end
|
2421
|
+
|
2422
|
+
# (rule _BuiltInCall_45 (seq 'sameTerm' '(' Expression ',' Expression ')'))
|
2423
|
+
production(:_BuiltInCall_45) do |value|
|
2424
|
+
SPARQL::Algebra::Operator::SameTerm.new(value[2][:Expression], value[4][:Expression])
|
2425
|
+
end
|
2426
|
+
|
2427
|
+
# (rule _BuiltInCall_46 (seq 'isIRI' '(' Expression ')'))
|
2428
|
+
start_production(:_BuiltInCall_46, as_hash: true)
|
2429
|
+
production(:_BuiltInCall_46) do |value|
|
2430
|
+
SPARQL::Algebra::Operator::IsIRI.new(value[:Expression])
|
2431
|
+
end
|
2432
|
+
|
2433
|
+
# (rule _BuiltInCall_47 (seq 'isURI' '(' Expression ')'))
|
2434
|
+
start_production(:_BuiltInCall_47, as_hash: true)
|
2435
|
+
production(:_BuiltInCall_47) do |value|
|
2436
|
+
SPARQL::Algebra::Operator::IsURI.new(value[:Expression])
|
2437
|
+
end
|
2438
|
+
|
2439
|
+
# (rule _BuiltInCall_48 (seq 'isBLANK' '(' Expression ')'))
|
2440
|
+
start_production(:_BuiltInCall_48, as_hash: true)
|
2441
|
+
production(:_BuiltInCall_48) do |value|
|
2442
|
+
SPARQL::Algebra::Operator::IsBlank.new(value[:Expression])
|
2443
|
+
end
|
2444
|
+
|
2445
|
+
# (rule _BuiltInCall_49 (seq 'isLITERAL' '(' Expression ')'))
|
2446
|
+
start_production(:_BuiltInCall_49, as_hash: true)
|
2447
|
+
production(:_BuiltInCall_49) do |value|
|
2448
|
+
SPARQL::Algebra::Operator::IsLiteral.new(value[:Expression])
|
2449
|
+
end
|
2450
|
+
|
2451
|
+
# (rule _BuiltInCall_50 (seq 'isNUMERIC' '(' Expression ')'))
|
2452
|
+
start_production(:_BuiltInCall_50, as_hash: true)
|
2453
|
+
production(:_BuiltInCall_50) do |value|
|
2454
|
+
SPARQL::Algebra::Operator::IsNumeric.new(value[:Expression])
|
2455
|
+
end
|
2456
|
+
|
2457
|
+
# (rule _BuiltInCall_51 (seq 'ADJUST' '(' Expression ',' Expression ')'))
|
2458
|
+
production(:_BuiltInCall_51) do |value|
|
2459
|
+
SPARQL::Algebra::Operator::Adjust.new(value[2][:Expression], value[4][:Expression])
|
2460
|
+
end
|
2461
|
+
|
2462
|
+
# (rule _BuiltInCall_52 (seq 'isTRIPLE' '(' Expression ')'))
|
2463
|
+
start_production(:_BuiltInCall_52, as_hash: true)
|
2464
|
+
production(:_BuiltInCall_52) do |value|
|
2465
|
+
SPARQL::Algebra::Operator::IsTriple.new(value[:Expression])
|
2466
|
+
end
|
2467
|
+
|
2468
|
+
# (rule _BuiltInCall_53
|
2469
|
+
# (seq 'TRIPLE' '(' Expression ',' Expression ',' Expression ')'))
|
2470
|
+
production(:_BuiltInCall_53) do |value|
|
2471
|
+
SPARQL::Algebra::Operator::Triple.new(value[2][:Expression], value[4][:Expression], value[6][:Expression])
|
2472
|
+
end
|
2473
|
+
|
2474
|
+
# (rule _BuiltInCall_54 (seq 'SUBJECT' '(' Expression ')'))
|
2475
|
+
start_production(:_BuiltInCall_54, as_hash: true)
|
2476
|
+
production(:_BuiltInCall_54) do |value|
|
2477
|
+
SPARQL::Algebra::Operator::Subject.new(value[:Expression])
|
2478
|
+
end
|
2479
|
+
|
2480
|
+
# (rule _BuiltInCall_55 (seq 'PREDICATE' '(' Expression ')'))
|
2481
|
+
start_production(:_BuiltInCall_55, as_hash: true)
|
2482
|
+
production(:_BuiltInCall_55) do |value|
|
2483
|
+
SPARQL::Algebra::Operator::Predicate.new(value[:Expression])
|
2484
|
+
end
|
2485
|
+
|
2486
|
+
# (rule _BuiltInCall_56 (seq 'OBJECT' '(' Expression ')'))
|
2487
|
+
start_production(:_BuiltInCall_56, as_hash: true)
|
2488
|
+
production(:_BuiltInCall_56) do |value|
|
2489
|
+
SPARQL::Algebra::Operator::Object.new(value[:Expression])
|
2490
|
+
end
|
2491
|
+
|
2492
|
+
|
2493
|
+
# RegexExpression ::= 'REGEX' '(' Expression ',' Expression
|
2494
|
+
# ( ',' Expression )? ')'
|
2495
|
+
production(:RegexExpression) do |value|
|
2496
|
+
expr_list = [value[2][:Expression], value[4][:Expression]]
|
2497
|
+
if value[5][:_RegexExpression_1]
|
2498
|
+
expr_list << value[5][:_RegexExpression_1].last[:Expression]
|
2499
|
+
end
|
2500
|
+
SPARQL::Algebra::Operator::Regex.new(*expr_list)
|
2501
|
+
end
|
2502
|
+
|
2503
|
+
# SubstringExpression ::= 'SUBSTR'
|
2504
|
+
# '(' Expression ',' Expression
|
2505
|
+
# ( ',' Expression )? ')'
|
2506
|
+
production(:SubstringExpression) do |value|
|
2507
|
+
expr_list = [value[2][:Expression], value[4][:Expression]]
|
2508
|
+
if value[5][:_SubstringExpression_1]
|
2509
|
+
expr_list << value[5][:_SubstringExpression_1].last[:Expression]
|
2510
|
+
end
|
2511
|
+
SPARQL::Algebra::Operator::SubStr.new(*expr_list)
|
2512
|
+
end
|
2513
|
+
|
2514
|
+
# StrReplaceExpression ::= 'REPLACE'
|
2515
|
+
# '(' Expression ','
|
2516
|
+
# Expression ',' Expression
|
2517
|
+
# ( ',' Expression )? ')'
|
2518
|
+
production(:StrReplaceExpression) do |value|
|
2519
|
+
expr_list = [value[2][:Expression], value[4][:Expression], value[6][:Expression]]
|
2520
|
+
if value[7][:_StrReplaceExpression_1]
|
2521
|
+
expr_list << value[7][:_StrReplaceExpression_1].last[:Expression]
|
2522
|
+
end
|
2523
|
+
SPARQL::Algebra::Operator::Replace.new(*expr_list)
|
2524
|
+
end
|
2525
|
+
|
2526
|
+
# ExistsFunc ::= 'EXISTS' GroupGraphPattern
|
2527
|
+
start_production(:ExistsFunc, as_hash: true)
|
2528
|
+
production(:ExistsFunc) do |value|
|
2529
|
+
SPARQL::Algebra::Operator::Exists.new(value&.dig(:GroupGraphPattern, :query))
|
2530
|
+
end
|
2531
|
+
|
2532
|
+
# NotExistsFunc ::= 'NOT' 'EXISTS' GroupGraphPattern
|
2533
|
+
start_production(:NotExistsFunc, as_hash: true)
|
2534
|
+
production(:NotExistsFunc) do |value|
|
2535
|
+
SPARQL::Algebra::Operator::NotExists.new(value&.dig(:GroupGraphPattern, :query))
|
2536
|
+
end
|
2537
|
+
|
2538
|
+
# Aggregate ::= 'COUNT' '(' 'DISTINCT'? ( '*' | Expression ) ')'
|
2539
|
+
# | 'SUM' '(' 'DISTINCT'? Expression ')'
|
2540
|
+
# | 'MIN' '(' 'DISTINCT'? Expression ')'
|
2541
|
+
# | 'MAX' '(' 'DISTINCT'? Expression ')'
|
2542
|
+
# | 'AVG' '(' 'DISTINCT'? Expression ')'
|
2543
|
+
# | 'SAMPLE' '(' 'DISTINCT'? Expression ')'
|
2544
|
+
# | 'GROUP_CONCAT' '(' 'DISTINCT'? Expression
|
2545
|
+
# ( ';' 'SEPARATOR' '=' String )? ')'
|
2546
|
+
production(:Aggregate) do |value|
|
2547
|
+
SPARQL::Algebra::Expression.for(*value)
|
2548
|
+
end
|
2549
|
+
|
2550
|
+
# (rule _Aggregate_1 (seq 'COUNT' '(' _Aggregate_8 _Aggregate_9 ')'))
|
2551
|
+
start_production(:_Aggregate_1, as_hash: true, insensitive_strings: :upper)
|
2552
|
+
production(:_Aggregate_1) do |value|
|
2553
|
+
expr = value[:_Aggregate_9] unless value[:_Aggregate_9] == '*'
|
2554
|
+
[:count, (value[:_Aggregate_8] ? :distinct : nil), expr].compact
|
2555
|
+
end
|
2556
|
+
|
2557
|
+
# (rule _Aggregate_2 (seq 'SUM' '(' _Aggregate_10 Expression ')'))
|
2558
|
+
start_production(:_Aggregate_2, as_hash: true, insensitive_strings: :upper)
|
2559
|
+
production(:_Aggregate_2) do |value|
|
2560
|
+
[:sum, (value[:_Aggregate_10] ? :distinct : nil), value[:Expression]].compact
|
2561
|
+
end
|
2562
|
+
|
2563
|
+
# (rule _Aggregate_3 (seq 'MIN' '(' _Aggregate_11 Expression ')'))
|
2564
|
+
start_production(:_Aggregate_3, as_hash: true, insensitive_strings: :upper)
|
2565
|
+
production(:_Aggregate_3) do |value|
|
2566
|
+
[:min, (value[:_Aggregate_11] ? :distinct : nil), value[:Expression]].compact
|
2567
|
+
end
|
2568
|
+
|
2569
|
+
# (rule _Aggregate_4 (seq 'MAX' '(' _Aggregate_12 Expression ')'))
|
2570
|
+
start_production(:_Aggregate_4, as_hash: true, insensitive_strings: :upper)
|
2571
|
+
production(:_Aggregate_4) do |value|
|
2572
|
+
[:max, (value[:_Aggregate_12] ? :distinct : nil), value[:Expression]].compact
|
2573
|
+
end
|
2574
|
+
|
2575
|
+
# (rule _Aggregate_5 (seq 'AVG' '(' _Aggregate_13 Expression ')'))
|
2576
|
+
start_production(:_Aggregate_5, as_hash: true, insensitive_strings: :upper)
|
2577
|
+
production(:_Aggregate_5) do |value|
|
2578
|
+
[:avg, (value[:_Aggregate_13] ? :distinct : nil), value[:Expression]].compact
|
2579
|
+
end
|
2580
|
+
|
2581
|
+
# (rule _Aggregate_6 (seq 'SAMPLE' '(' _Aggregate_14 Expression ')'))
|
2582
|
+
start_production(:_Aggregate_6, as_hash: true, insensitive_strings: :upper)
|
2583
|
+
production(:_Aggregate_6) do |value|
|
2584
|
+
[:sample, (value[:_Aggregate_14] ? :distinct : nil), value[:Expression]].compact
|
2585
|
+
end
|
2586
|
+
|
2587
|
+
# (rule _Aggregate_7
|
2588
|
+
# (seq 'GROUP_CONCAT' '(' _Aggregate_15 Expression _Aggregate_16 ')'))
|
2589
|
+
start_production(:_Aggregate_7, as_hash: true, insensitive_strings: :upper)
|
2590
|
+
production(:_Aggregate_7) do |value|
|
2591
|
+
separator = value&.dig(:_Aggregate_16, :String)
|
2592
|
+
[:group_concat,
|
2593
|
+
(value[:_Aggregate_15] ? :distinct : nil),
|
2594
|
+
([:separator, separator] if separator),
|
2595
|
+
value[:Expression]
|
2596
|
+
].compact
|
2597
|
+
end
|
2598
|
+
|
2599
|
+
# (rule _Aggregate_17 (seq ';' 'SEPARATOR' '=' String))
|
2600
|
+
start_production(:_Aggregate_17, as_hash: true, insensitive_strings: :upper)
|
2601
|
+
|
2602
|
+
# iriOrFunction ::= iri ArgList?
|
2603
|
+
#
|
2604
|
+
# (rule iriOrFunction (seq iri _iriOrFunction_1))
|
2605
|
+
# (rule _iriOrFunction_1 (opt ArgList))
|
2606
|
+
start_production(:iriOrFunction, as_hash: true)
|
2607
|
+
production(:iriOrFunction) do |value|
|
2608
|
+
if value[:_iriOrFunction_1]
|
2609
|
+
SPARQL::Algebra::Operator::FunctionCall.new(value[:iri], *value[:_iriOrFunction_1])
|
2610
|
+
else
|
2611
|
+
value[:iri]
|
2612
|
+
end
|
2613
|
+
end
|
2614
|
+
|
2615
|
+
# RDFLiteral ::= String ( LANG_DIR | '^^' iri )?
|
2616
|
+
start_production(:RDFLiteral, as_hash: true)
|
2617
|
+
production(:RDFLiteral) do |value|
|
2618
|
+
str = value[:String]
|
2619
|
+
dt = value[:_RDFLiteral_1] if value[:_RDFLiteral_1].is_a?(RDF::URI)
|
2620
|
+
lang = value[:_RDFLiteral_1] if value[:_RDFLiteral_1].is_a?(String)
|
2621
|
+
RDF::Literal.new(str, datatype: dt, language: lang)
|
2622
|
+
end
|
2623
|
+
|
2624
|
+
# (rule _RDFLiteral_3 (seq '^^' iri))
|
2625
|
+
production(:_RDFLiteral_3) do |value|
|
2626
|
+
value.last[:iri]
|
2627
|
+
end
|
2628
|
+
|
2629
|
+
# BooleanLiteral ::= 'true' | 'false'
|
2630
|
+
start_production(:BooleanLiteral, insensitive_strings: false)
|
2631
|
+
production(:BooleanLiteral) do |value|
|
2632
|
+
RDF::Literal::Boolean.new(value.downcase)
|
2633
|
+
end
|
2634
|
+
|
2635
|
+
# PrefixedName::= PNAME_LN | PNAME_NS
|
2636
|
+
production(:PrefixedName) do |value|
|
2637
|
+
# PNAME_NS is just the symbol, PNAME_LN is a resolved IRI
|
2638
|
+
value.is_a?(Symbol) ? self.prefix(value) : value
|
2639
|
+
end
|
2640
|
+
|
2641
|
+
##
|
2642
|
+
# Initializes a new parser instance.
|
2643
|
+
#
|
2644
|
+
# @param [String, IO, StringIO, #to_s] input
|
2645
|
+
# @param [Hash{Symbol => Object}] options
|
2646
|
+
# @option options [Boolean] :all_vars (false)
|
2647
|
+
# If `true`, emits on empty `project` operator when parsing `SELECT *`, which will emit all in-scope variables, rather than just those used in solutions.
|
2648
|
+
# In the next minor release, the default for this option will change to `true`.
|
2649
|
+
# @option options [#to_s] :anon_base ("b0")
|
2650
|
+
# Basis for generating anonymous Nodes
|
2651
|
+
# @option options [#to_s] :base_uri (nil)
|
2652
|
+
# the base URI to use when resolving relative URIs (for acessing intermediate parser productions)
|
2653
|
+
# @option options [Logger, #write, #<<] :logger
|
2654
|
+
# Record error/info/debug output
|
2655
|
+
# @option options [Hash] :prefixes (Hash.new)
|
2656
|
+
# the prefix mappings to use (for acessing intermediate parser productions)
|
2657
|
+
# @option options [Boolean] :resolve_iris (false)
|
2658
|
+
# Resolve prefix and relative IRIs, otherwise, when serializing the parsed SSE
|
2659
|
+
# as S-Expressions, use the original prefixed and relative URIs along with `base` and `prefix`
|
2660
|
+
# definitions.
|
2661
|
+
# @option options [Boolean] :validate (false)
|
2662
|
+
# whether to validate the parsed statements and values
|
2663
|
+
# @yield [parser] `self`
|
2664
|
+
# @yieldparam [SPARQL::Grammar::Parser] parser
|
2665
|
+
# @yieldreturn [void] ignored
|
2666
|
+
# @return [SPARQL::Grammar::Parser]
|
2667
|
+
def initialize(input = nil, **options, &block)
|
2668
|
+
@input = case input
|
2669
|
+
when IO, StringIO then EBNF::Unescape.unescape_codepoints(input.read)
|
2670
|
+
else EBNF::Unescape.unescape_codepoints(input.to_s)
|
2671
|
+
end
|
2672
|
+
@input.encode!(Encoding::UTF_8) if @input.respond_to?(:encode!)
|
2673
|
+
@options = {anon_base: "b0", validate: false}.merge(options)
|
2674
|
+
|
2675
|
+
debug("base IRI") {base_uri.inspect}
|
2676
|
+
debug("validate") {validate?.inspect}
|
2677
|
+
|
2678
|
+
@vars = {}
|
2679
|
+
@nd_var_gen = "0"
|
2680
|
+
|
2681
|
+
if block_given?
|
2682
|
+
case block.arity
|
2683
|
+
when 0 then instance_eval(&block)
|
2684
|
+
else block.call(self)
|
2685
|
+
end
|
2686
|
+
end
|
2687
|
+
end
|
2688
|
+
|
2689
|
+
##
|
2690
|
+
# Returns `true` if the input string is syntactically valid.
|
2691
|
+
#
|
2692
|
+
# @return [Boolean]
|
2693
|
+
def valid?
|
2694
|
+
parse
|
2695
|
+
true
|
2696
|
+
rescue Error
|
2697
|
+
false
|
2698
|
+
end
|
2699
|
+
|
2700
|
+
# @return [String]
|
2701
|
+
def to_sxp_bin
|
2702
|
+
@result
|
2703
|
+
end
|
2704
|
+
|
2705
|
+
def to_s
|
2706
|
+
@result.to_sxp
|
2707
|
+
end
|
2708
|
+
|
2709
|
+
alias_method :peg_parse, :parse
|
2710
|
+
|
2711
|
+
# Parse query
|
2712
|
+
#
|
2713
|
+
# The result is a SPARQL Algebra S-List. Productions return an array such as the following:
|
2714
|
+
#
|
2715
|
+
# (prefix ((: <http://example/>))
|
2716
|
+
# (union
|
2717
|
+
# (bgp (triple ?s ?p ?o))
|
2718
|
+
# (graph ?g
|
2719
|
+
# (bgp (triple ?s ?p ?o)))))
|
2720
|
+
#
|
2721
|
+
# @param [Symbol, #to_s] prod The starting production for the parser.
|
2722
|
+
# It may be a URI from the grammar, or a symbol representing the local_name portion of the grammar URI.
|
2723
|
+
# @return [RDF::Queryable]
|
2724
|
+
# @see https://www.w3.org/TR/sparql11-query/#sparqlAlgebra
|
2725
|
+
# @see https://axel.deri.ie/sparqltutorial/ESWC2007_SPARQL_Tutorial_unit2b.pdf
|
2726
|
+
def parse(prod = :QueryUnit)
|
2727
|
+
res = peg_parse(@input,
|
2728
|
+
start: prod.to_sym,
|
2729
|
+
rules: SPARQL::Grammar::Meta::RULES,
|
2730
|
+
whitespace: WS,
|
2731
|
+
insensitive_strings: :upper,
|
2732
|
+
**@options
|
2733
|
+
)
|
2734
|
+
|
2735
|
+
# The last thing on the @prod_data stack is the result
|
2736
|
+
@result = case
|
2737
|
+
when !res.is_a?(Hash)
|
2738
|
+
res
|
2739
|
+
when res.empty?
|
2740
|
+
nil
|
2741
|
+
when res[:query]
|
2742
|
+
res[:query]
|
2743
|
+
when res[:update]
|
2744
|
+
res[:update]
|
2745
|
+
else
|
2746
|
+
key = res.keys.first
|
2747
|
+
value = res[key]
|
2748
|
+
value = [value] unless value.is_a?(Array)
|
2749
|
+
value.unshift(key)
|
2750
|
+
end
|
2751
|
+
|
2752
|
+
# Validate resulting expression
|
2753
|
+
@result.validate! if @result && validate?
|
2754
|
+
@result
|
2755
|
+
end
|
2756
|
+
|
2757
|
+
private
|
2758
|
+
##
|
2759
|
+
# Returns the URI prefixes currently defined for this parser.
|
2760
|
+
#
|
2761
|
+
# @example
|
2762
|
+
# prefixes[:dc] #=> RDF::URI('http://purl.org/dc/terms/')
|
2763
|
+
#
|
2764
|
+
# @return [Hash{Symbol => RDF::URI}]
|
2765
|
+
# @since 0.3.0
|
2766
|
+
def prefixes
|
2767
|
+
@options[:prefixes] ||= {}
|
2768
|
+
end
|
2769
|
+
|
2770
|
+
##
|
2771
|
+
# Defines the given URI prefixes for this parser.
|
2772
|
+
#
|
2773
|
+
# @example
|
2774
|
+
# prefixes = {
|
2775
|
+
# dc: RDF::URI('http://purl.org/dc/terms/'),
|
2776
|
+
# }
|
2777
|
+
#
|
2778
|
+
# @param [Hash{Symbol => RDF::URI}] prefixes
|
2779
|
+
# @return [Hash{Symbol => RDF::URI}]
|
2780
|
+
# @since 0.3.0
|
2781
|
+
def prefixes=(prefixes)
|
2782
|
+
@options[:prefixes] = prefixes
|
2783
|
+
end
|
2784
|
+
|
2785
|
+
##
|
2786
|
+
# Defines the given named URI prefix for this parser.
|
2787
|
+
#
|
2788
|
+
# @example Defining a URI prefix
|
2789
|
+
# prefix :dc, RDF::URI('http://purl.org/dc/terms/')
|
2790
|
+
#
|
2791
|
+
# @example Returning a URI prefix
|
2792
|
+
# prefix(:dc) #=> RDF::URI('http://purl.org/dc/terms/')
|
2793
|
+
#
|
2794
|
+
# @overload prefix(name, uri)
|
2795
|
+
# @param [Symbol, #to_s] name
|
2796
|
+
# @param [RDF::URI, #to_s] uri
|
2797
|
+
#
|
2798
|
+
# @overload prefix(name)
|
2799
|
+
# @param [Symbol, #to_s] name
|
2800
|
+
#
|
2801
|
+
# @return [RDF::URI]
|
2802
|
+
def prefix(name, iri = nil)
|
2803
|
+
name = name.to_s.empty? ? nil : (name.respond_to?(:to_sym) ? name.to_sym : name.to_s.to_sym)
|
2804
|
+
iri.nil? ? prefixes[name] : prefixes[name] = iri
|
2805
|
+
end
|
2806
|
+
|
2807
|
+
##
|
2808
|
+
# Returns the Base URI defined for the parser,
|
2809
|
+
# as specified or when parsing a BASE prologue element.
|
2810
|
+
#
|
2811
|
+
# @example
|
2812
|
+
# base #=> RDF::URI('http://example.com/')
|
2813
|
+
#
|
2814
|
+
# @return [HRDF::URI]
|
2815
|
+
def base_uri
|
2816
|
+
RDF::URI(@options[:base_uri])
|
2817
|
+
end
|
2818
|
+
|
2819
|
+
##
|
2820
|
+
# Set the Base URI to use for this parser.
|
2821
|
+
#
|
2822
|
+
# @param [RDF::URI, #to_s] iri
|
2823
|
+
#
|
2824
|
+
# @example
|
2825
|
+
# base_uri = RDF::URI('http://purl.org/dc/terms/')
|
2826
|
+
#
|
2827
|
+
# @return [RDF::URI]
|
2828
|
+
def base_uri=(iri)
|
2829
|
+
@options[:base_uri] = RDF::URI(iri)
|
2830
|
+
end
|
2831
|
+
|
2832
|
+
##
|
2833
|
+
# Returns `true` if parsed statements and values should be validated.
|
2834
|
+
#
|
2835
|
+
# @return [Boolean] `true` or `false`
|
2836
|
+
# @since 0.3.0
|
2837
|
+
def resolve_iris?
|
2838
|
+
@options[:resolve_iris]
|
2839
|
+
end
|
2840
|
+
|
2841
|
+
##
|
2842
|
+
# Returns `true` when resolving IRIs, otherwise BASE and PREFIX are retained in the output algebra.
|
2843
|
+
#
|
2844
|
+
# @return [Boolean] `true` or `false`
|
2845
|
+
# @since 1.0.3
|
2846
|
+
def validate?
|
2847
|
+
@options[:validate]
|
2848
|
+
end
|
2849
|
+
|
2850
|
+
# Used for generating BNode labels
|
2851
|
+
attr_accessor :nd_var_gen
|
2852
|
+
|
2853
|
+
# Generate BNodes, not non-distinguished variables
|
2854
|
+
# @param [Boolean] value
|
2855
|
+
# @return [void]
|
2856
|
+
def gen_bnodes(value = true)
|
2857
|
+
@nd_var_gen = value ? false : "0"
|
2858
|
+
end
|
2859
|
+
|
2860
|
+
# Clear cached BNodes
|
2861
|
+
# @return [void]
|
2862
|
+
def clear_bnode_cache
|
2863
|
+
@bnode_cache = {}
|
2864
|
+
end
|
2865
|
+
|
2866
|
+
# Freeze BNodes, which allows us to detect if they're re-used
|
2867
|
+
# @return [void]
|
2868
|
+
def freeze_bnodes
|
2869
|
+
@bnode_cache ||= {}
|
2870
|
+
@bnode_cache.each_value(&:freeze)
|
2871
|
+
end
|
2872
|
+
|
2873
|
+
# Generate a BNode identifier
|
2874
|
+
def bnode(id = nil)
|
2875
|
+
if @nd_var_gen
|
2876
|
+
# Use non-distinguished variables within patterns
|
2877
|
+
variable(id, false)
|
2878
|
+
else
|
2879
|
+
unless id
|
2880
|
+
id = @options[:anon_base]
|
2881
|
+
@options[:anon_base] = @options[:anon_base].succ
|
2882
|
+
end
|
2883
|
+
@bnode_cache ||= {}
|
2884
|
+
raise Error, "Illegal attempt to reuse a BNode" if @bnode_cache[id] && @bnode_cache[id].frozen?
|
2885
|
+
@bnode_cache[id] ||= RDF::Node.new(id)
|
2886
|
+
end
|
2887
|
+
end
|
2888
|
+
|
2889
|
+
##
|
2890
|
+
# Return variable allocated to an ID.
|
2891
|
+
# If no ID is provided, a new variable
|
2892
|
+
# is allocated. Otherwise, any previous assignment will be used.
|
2893
|
+
#
|
2894
|
+
# The variable has a #distinguished? method applied depending on if this
|
2895
|
+
# is a disinguished or non-distinguished variable. Non-distinguished
|
2896
|
+
# variables are effectively the same as BNodes.
|
2897
|
+
# @return [RDF::Query::Variable]
|
2898
|
+
def variable(id, distinguished = true)
|
2899
|
+
id = nil if id.to_s.empty?
|
2900
|
+
|
2901
|
+
if id
|
2902
|
+
@vars[id] ||= begin
|
2903
|
+
RDF::Query::Variable.new(id, distinguished: distinguished)
|
2904
|
+
end
|
2905
|
+
else
|
2906
|
+
unless distinguished
|
2907
|
+
# Allocate a non-distinguished variable identifier
|
2908
|
+
id = @nd_var_gen
|
2909
|
+
@nd_var_gen = id.succ
|
2910
|
+
end
|
2911
|
+
RDF::Query::Variable.new(id, distinguished: distinguished)
|
2912
|
+
end
|
2913
|
+
end
|
2914
|
+
|
2915
|
+
# Create URIs
|
2916
|
+
def iri(value)
|
2917
|
+
# If we have a base URI, use that when constructing a new URI
|
2918
|
+
value = RDF::URI(value)
|
2919
|
+
if base_uri && value.relative?
|
2920
|
+
base_uri.join(value)
|
2921
|
+
else
|
2922
|
+
value
|
2923
|
+
end
|
2924
|
+
end
|
2925
|
+
|
2926
|
+
def ns(prefix, suffix)
|
2927
|
+
base = prefix(prefix).to_s
|
2928
|
+
suffix = suffix.to_s.gsub(PN_LOCAL_ESC) {|esc| esc[1]} if
|
2929
|
+
suffix.to_s.match?(PN_LOCAL_ESC)
|
2930
|
+
suffix = suffix.to_s.sub(/^\#/, "") if base.index("#")
|
2931
|
+
debug {"ns(#{prefix.inspect}): base: '#{base}', suffix: '#{suffix}'"}
|
2932
|
+
iri(base + suffix.to_s)
|
2933
|
+
end
|
2934
|
+
|
2935
|
+
# Create a literal
|
2936
|
+
def literal(value, **options)
|
2937
|
+
options = options.dup
|
2938
|
+
# Internal representation is to not use xsd:string, although it could arguably go the other way.
|
2939
|
+
options.delete(:datatype) if options[:datatype] == RDF::XSD.string
|
2940
|
+
debug("literal") do
|
2941
|
+
"value: #{value.inspect}, " +
|
2942
|
+
"options: #{options.inspect}, " +
|
2943
|
+
"validate: #{validate?.inspect}, "
|
2944
|
+
end
|
2945
|
+
RDF::Literal.new(value, validate: validate?, **options)
|
2946
|
+
end
|
2947
|
+
|
2948
|
+
# Take collection of objects and create RDF Collection using rdf:first, rdf:rest and rdf:nil
|
2949
|
+
# @param [Hash] data Production Data
|
2950
|
+
# @return [Array] list of patterns
|
2951
|
+
def expand_collection(first, values)
|
2952
|
+
# Add any triples generated from deeper productions
|
2953
|
+
patterns = values.map {|v| v[:pattern]}.flatten.compact
|
2954
|
+
|
2955
|
+
# Create list items for each element in data[:GraphNode]
|
2956
|
+
list = values.map {|v| v[:object]}.compact
|
2957
|
+
last = list.pop
|
2958
|
+
|
2959
|
+
list.each do |r|
|
2960
|
+
patterns << add_pattern(:Collection, subject: first, predicate: RDF["first"], object: r)
|
2961
|
+
rest = bnode()
|
2962
|
+
patterns << add_pattern(:Collection, subject: first, predicate: RDF["rest"], object: rest)
|
2963
|
+
first = rest
|
2964
|
+
end
|
2965
|
+
|
2966
|
+
if last
|
2967
|
+
patterns << add_pattern(:Collection, subject: first, predicate: RDF["first"], object: last)
|
2968
|
+
end
|
2969
|
+
patterns << add_pattern(:Collection, subject: first, predicate: RDF["rest"], object: RDF["nil"])
|
2970
|
+
patterns
|
2971
|
+
end
|
2972
|
+
|
2973
|
+
# add a pattern
|
2974
|
+
#
|
2975
|
+
# @param [String] production Production generating pattern
|
2976
|
+
# @param [Boolean] tripleTerm For Triple Term
|
2977
|
+
# @param [Hash{Symbol => Object}] options
|
2978
|
+
def add_pattern(production, tripleTerm: false, **options)
|
2979
|
+
progress(production, "[:pattern, #{options[:subject]}, #{options[:predicate]}, #{options[:object]}]")
|
2980
|
+
triple = {}
|
2981
|
+
triple[:tripleTerm] = true if tripleTerm
|
2982
|
+
options.each_pair do |r, v|
|
2983
|
+
if v.is_a?(Array) && v.flatten.length == 1
|
2984
|
+
v = v.flatten.first
|
2985
|
+
end
|
2986
|
+
if validate? && !v.is_a?(RDF::Term)
|
2987
|
+
error("add_pattern", "Expected #{r} to be a resource, but it was #{v.inspect}",
|
2988
|
+
production: production)
|
2989
|
+
end
|
2990
|
+
triple[r] = v
|
2991
|
+
end
|
2992
|
+
RDF::Query::Pattern.new(triple)
|
2993
|
+
end
|
2994
|
+
|
2995
|
+
##
|
2996
|
+
# Merge query modifiers, datasets, and projections
|
2997
|
+
#
|
2998
|
+
# This includes tranforming aggregates if also used with a GROUP BY
|
2999
|
+
#
|
3000
|
+
# @see http://www.w3.org/TR/sparql11-query/#convertGroupAggSelectExpressions
|
3001
|
+
def merge_modifiers(data)
|
3002
|
+
debug("merge modifiers") {data.inspect}
|
3003
|
+
query = data[:query] || SPARQL::Algebra::Operator::BGP.new
|
3004
|
+
|
3005
|
+
vars = Array(data[:Var])
|
3006
|
+
order = Array(data[:order])
|
3007
|
+
extensions = data[:extend] || []
|
3008
|
+
having = data[:having] || []
|
3009
|
+
values = data[:values] || []
|
3010
|
+
|
3011
|
+
# extension variables must not appear in projected variables.
|
3012
|
+
# Add them to the projection otherwise
|
3013
|
+
extensions.each do |(var, _)|
|
3014
|
+
raise Error, "Extension variable #{var} also in SELECT" if vars.map(&:to_s).include?(var.to_s)
|
3015
|
+
vars << var
|
3016
|
+
end
|
3017
|
+
|
3018
|
+
# If any extension contains an aggregate, and there is now group, implicitly group by 1
|
3019
|
+
if !data[:group] &&
|
3020
|
+
extensions.any? {|(_, function)| function.aggregate?} ||
|
3021
|
+
having.any? {|c| c.aggregate? }
|
3022
|
+
debug {"Implicit group"}
|
3023
|
+
data[:group] = []
|
3024
|
+
end
|
3025
|
+
|
3026
|
+
# Add datasets and modifiers in order
|
3027
|
+
if data[:group]
|
3028
|
+
group_vars = data[:group]
|
3029
|
+
|
3030
|
+
# For creating temporary variables
|
3031
|
+
agg = 0
|
3032
|
+
|
3033
|
+
# Find aggregated varirables in extensions
|
3034
|
+
aggregates = []
|
3035
|
+
aggregated_vars = extensions.map do |(var, function)|
|
3036
|
+
var if function.aggregate?
|
3037
|
+
end.compact
|
3038
|
+
|
3039
|
+
# Common function for replacing aggregates with temporary variables,
|
3040
|
+
# as defined in http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#convertGroupAggSelectExpressions
|
3041
|
+
aggregate_expression = lambda do |expr|
|
3042
|
+
# Replace unaggregated variables in expr
|
3043
|
+
# - For each unaggregated variable V in X
|
3044
|
+
expr.replace_vars! do |v|
|
3045
|
+
aggregated_vars.include?(v) ? v : SPARQL::Algebra::Expression[:sample, v]
|
3046
|
+
end
|
3047
|
+
|
3048
|
+
# Replace aggregates in expr as above
|
3049
|
+
expr.replace_aggregate! do |function|
|
3050
|
+
if avf = aggregates.detect {|(_, f)| f.equal?(function)}
|
3051
|
+
avf.first
|
3052
|
+
else
|
3053
|
+
# Allocate a temporary variable for this function, and retain the mapping for outside the group
|
3054
|
+
av = RDF::Query::Variable.new(".#{agg}", distinguished: false)
|
3055
|
+
agg += 1
|
3056
|
+
aggregates << [av, function]
|
3057
|
+
av
|
3058
|
+
end
|
3059
|
+
end
|
3060
|
+
end
|
3061
|
+
|
3062
|
+
# If there are extensions, they are aggregated if necessary and bound
|
3063
|
+
# to temporary variables
|
3064
|
+
extensions.map! do |(var, expr)|
|
3065
|
+
[var, aggregate_expression.call(expr)]
|
3066
|
+
end
|
3067
|
+
|
3068
|
+
# Having clauses
|
3069
|
+
having.map! do |expr|
|
3070
|
+
aggregate_expression.call(expr)
|
3071
|
+
end
|
3072
|
+
|
3073
|
+
query = if aggregates.empty?
|
3074
|
+
SPARQL::Algebra::Expression[:group, group_vars, query]
|
3075
|
+
else
|
3076
|
+
SPARQL::Algebra::Expression[:group, group_vars, aggregates, query]
|
3077
|
+
end
|
3078
|
+
end
|
3079
|
+
|
3080
|
+
query = SPARQL::Algebra::Expression[:join, query, values] unless values.empty?
|
3081
|
+
|
3082
|
+
query = SPARQL::Algebra::Expression[:extend, extensions, query] unless extensions.empty?
|
3083
|
+
|
3084
|
+
query = SPARQL::Algebra::Expression[:filter, *having, query] unless having.empty?
|
3085
|
+
|
3086
|
+
query = SPARQL::Algebra::Expression[:order, data[:order], query] unless order.empty?
|
3087
|
+
|
3088
|
+
# If SELECT * was used, emit a projection with empty variables, vs no projection at all. Only if :all_vars is true
|
3089
|
+
query = if vars == %w(*)
|
3090
|
+
options[:all_vars] ? SPARQL::Algebra::Expression[:project, [], query] : query
|
3091
|
+
elsif !vars.empty?
|
3092
|
+
SPARQL::Algebra::Expression[:project, vars, query]
|
3093
|
+
else
|
3094
|
+
query
|
3095
|
+
end
|
3096
|
+
|
3097
|
+
query = SPARQL::Algebra::Expression[data[:DISTINCT_REDUCED], query] if data[:DISTINCT_REDUCED]
|
3098
|
+
|
3099
|
+
query = SPARQL::Algebra::Expression[:slice, data[:slice][0], data[:slice][1], query] if data[:slice]
|
3100
|
+
|
3101
|
+
query = SPARQL::Algebra::Expression[:dataset, data[:dataset], query] if data[:dataset] && !data[:dataset].empty?
|
3102
|
+
|
3103
|
+
query
|
3104
|
+
end
|
3105
|
+
|
3106
|
+
# Add joined expressions in for prod1 (op prod2)* to form (op (op 1 2) 3)
|
3107
|
+
def add_operator_expressions(lhs, *exprs)
|
3108
|
+
# Iterate through expression to create binary operations
|
3109
|
+
exprs.each do |op, rhs|
|
3110
|
+
lhs = SPARQL::Algebra::Expression.for(op, lhs, rhs)
|
3111
|
+
end
|
3112
|
+
lhs
|
3113
|
+
end
|
3114
|
+
end # class Parser
|
3115
|
+
end # module SPARQL::Grammar
|