shex 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  module ShEx::Algebra
2
2
  ##
3
3
  class Or < Operator
4
- include Satisfiable
4
+ include ShapeExpression
5
5
  NAME = :or
6
6
 
7
7
  def initialize(*args, **options)
@@ -10,8 +10,8 @@ module ShEx::Algebra
10
10
  raise ArgumentError, "wrong number of arguments (given #{args.length}, expected 2..)"
11
11
  end
12
12
 
13
- # All arguments must be Satisfiable
14
- raise ArgumentError, "All operands must be Shape operands" unless args.all? {|o| o.is_a?(Satisfiable)}
13
+ # All arguments must be ShapeExpression
14
+ raise ArgumentError, "All operands must be Shape operands or resource" unless args.all? {|o| o.is_a?(ShapeExpression) || o.is_a?(RDF::Resource)}
15
15
  super
16
16
  end
17
17
 
@@ -27,22 +27,35 @@ module ShEx::Algebra
27
27
 
28
28
  #
29
29
  # S is a ShapeOr and there is some shape expression se2 in shapeExprs such that satisfies(n, se2, G, m).
30
- # @param (see Satisfiable#satisfies?)
31
- # @return (see Satisfiable#satisfies?)
32
- # @raise (see Satisfiable#satisfies?)
30
+ # @param (see ShapeExpression#satisfies?)
31
+ # @return (see ShapeExpression#satisfies?)
32
+ # @raise (see ShapeExpression#satisfies?)
33
33
  def satisfies?(focus, depth: 0)
34
34
  status "", depth: depth
35
- expressions = operands.select {|o| o.is_a?(Satisfiable)}
36
35
  unsatisfied = []
37
36
  expressions.any? do |op|
38
37
  begin
39
- matched_op = op.satisfies?(focus, depth: depth + 1)
38
+ matched_op = case op
39
+ when RDF::Resource
40
+ schema.enter_shape(op, focus) do |shape|
41
+ if shape
42
+ shape.satisfies?(focus, depth: depth + 1)
43
+ else
44
+ status "Satisfy as #{op} was re-entered for #{focus}", depth: depth
45
+ shape
46
+ end
47
+ end
48
+ when ShapeExpression
49
+ op.satisfies?(focus, depth: depth + 1)
50
+ end
40
51
  return satisfy focus: focus, satisfied: matched_op, depth: depth
41
52
  rescue ShEx::NotSatisfied => e
42
53
  status "unsatisfied #{focus}", depth: depth
43
54
  op = op.dup
44
- op.satisfied = e.expression.satisfied
45
- op.unsatisfied = e.expression.unsatisfied
55
+ if op.respond_to?(:satisfied)
56
+ op.satisfied = e.expression.satisfied
57
+ op.unsatisfied = e.expression.unsatisfied
58
+ end
46
59
  unsatisfied << op
47
60
  status "unsatisfied: #{e.message}", depth: depth
48
61
  false
@@ -53,6 +66,26 @@ module ShEx::Algebra
53
66
  focus: focus, unsatisfied: unsatisfied, depth: depth
54
67
  end
55
68
 
69
+ ##
70
+ # expressions must be ShapeExpressions
71
+ #
72
+ # @return [Operator] `self`
73
+ # @raise [ShEx::StructureError] if the value is invalid
74
+ def validate!
75
+ expressions.each do |op|
76
+ case op
77
+ when ShapeExpression
78
+ when RDF::Resource
79
+ ref = schema.find(op)
80
+ ref.is_a?(ShapeExpression) ||
81
+ structure_error("#{json_type} must reference a ShapeExpression: #{ref}")
82
+ else
83
+ structure_error("#{json_type} must reference a ShapeExpression: #{ref}")
84
+ end
85
+ end
86
+ super
87
+ end
88
+
56
89
  def json_type
57
90
  "ShapeOr"
58
91
  end
@@ -43,12 +43,12 @@ module ShEx::Algebra
43
43
  # One or more schemas, or paths to ShEx schema resources used for finding external shapes.
44
44
  # @return [Operand] Returns operand graph annotated with satisfied and unsatisfied operations.
45
45
  # @param [Hash{Symbol => Object}] options
46
- # @option options [String] :base_uri
46
+ # @option options [String] :base_uri (for resolving focus)
47
47
  # @raise [ShEx::NotSatisfied] along with operand graph described for return
48
48
  def execute(focus, graph, map, shapeExterns: [], depth: 0, **options)
49
49
  @graph, @shapes_entered = graph, {}
50
50
  @external_schemas = shapeExterns
51
- focus = value(focus)
51
+ focus = value(focus, options)
52
52
 
53
53
  logger = options[:logger] || @options[:logger]
54
54
  each_descendant do |op|
@@ -66,7 +66,7 @@ module ShEx::Algebra
66
66
  end
67
67
  end
68
68
 
69
- # If `n` is a Blank Node, we won't find it through normal matching, find an equivalent node in the graph having the same label
69
+ # If `n` is a Blank Node, we won't find it through normal matching, find an equivalent node in the graph having the same id
70
70
  graph_focus = graph.enum_term.detect {|t| t.node? && t.id == focus.id} if focus.is_a?(RDF::Node)
71
71
  graph_focus ||= focus
72
72
 
@@ -89,10 +89,10 @@ module ShEx::Algebra
89
89
  satisfied_shapes = {}
90
90
  satisfied_schema.operands << [:shapes, satisfied_shapes] unless shapes.empty?
91
91
 
92
- # Match against all shapes associated with the labels for focus
93
- Array(@map[focus]).each do |label|
94
- enter_shape(label, focus) do |shape|
95
- satisfied_shapes[label] = shape.satisfies?(graph_focus, depth: depth + 1)
92
+ # Match against all shapes associated with the ids for focus
93
+ Array(@map[focus]).each do |id|
94
+ enter_shape(id, focus) do |shape|
95
+ satisfied_shapes[id] = shape.satisfies?(graph_focus, depth: depth + 1)
96
96
  end
97
97
  end
98
98
  status "schema satisfied", depth: depth
@@ -131,23 +131,24 @@ module ShEx::Algebra
131
131
 
132
132
  ##
133
133
  # Indicate that a shape has been entered with a specific focus node. Any future attempt to enter the same shape with the same node raises an exception.
134
- # @param [RDF::Resource] label
134
+ # @param [RDF::Resource] id
135
135
  # @param [RDF::Resource] node
136
136
  # @yield :shape
137
- # @yieldparam [Satisfiable] shape, or `nil` if shape already entered
138
- # @return [Satisfiable]
139
- def enter_shape(label, node, &block)
140
- shape = shapes.detect {|s| s.label == label}
141
- structure_error("No shape found for #{label}") unless shape
142
- @shapes_entered[label] ||= {}
143
- if @shapes_entered[label][node]
137
+ # @yieldparam [ShapeExpression] shape, or `nil` if shape already entered
138
+ # @return (see ShapeExpression#satisfies?)
139
+ # @raise (see ShapeExpression#satisfies?)
140
+ def enter_shape(id, node, &block)
141
+ shape = shapes.detect {|s| s.id == id}
142
+ structure_error("No shape found for #{id}") unless shape
143
+ @shapes_entered[id] ||= {}
144
+ if @shapes_entered[id][node]
144
145
  block.call(false)
145
146
  else
146
- @shapes_entered[label][node] = self
147
+ @shapes_entered[id][node] = self
147
148
  begin
148
149
  block.call(shape)
149
150
  ensure
150
- @shapes_entered[label].delete(node)
151
+ @shapes_entered[id].delete(node)
151
152
  end
152
153
  end
153
154
  end
@@ -174,12 +175,26 @@ module ShEx::Algebra
174
175
  @start ||= operands.detect {|op| op.is_a?(Start)}
175
176
  end
176
177
 
178
+ ##
179
+ # Find a ShapeExpression or TripleExpression by identifier
180
+ # @param [#to_s] id
181
+ # @return [TripleExpression, ShapeExpression]
182
+ def find(id)
183
+ each_descendant.detect {|op| op.id == id}
184
+ end
185
+
177
186
  ##
178
187
  # Validate shapes, in addition to other operands
179
- # @return [SPARQL::Algebra::Expression] `self`
188
+ # @return [Operator] `self`
180
189
  # @raise [ArgumentError] if the value is invalid
181
190
  def validate!
182
- shapes.each {|op| op.validate! if op.respond_to?(:validate!)}
191
+ shapes.each do |op|
192
+ op.validate! if op.respond_to?(:validate!)
193
+ if op.is_a?(RDF::Resource)
194
+ ref = find(op)
195
+ structure_error("Missing reference: #{op}") if ref.nil?
196
+ end
197
+ end
183
198
  super
184
199
  end
185
200
  end
@@ -1,7 +1,7 @@
1
1
  module ShEx::Algebra
2
2
  ##
3
3
  class Shape < Operator
4
- include Satisfiable
4
+ include ShapeExpression
5
5
  NAME = :shape
6
6
 
7
7
  ##
@@ -29,11 +29,10 @@ module ShEx::Algebra
29
29
  end
30
30
 
31
31
  # The `satisfies` semantics for a `Shape` depend on a matches function defined below. For a node `n`, shape `S`, graph `G`, and shapeMap `m`, `satisfies(n, S, G, m)`.
32
- # @param (see Satisfiable#satisfies?)
33
- # @return (see Satisfiable#satisfies?)
34
- # @raise (see Satisfiable#satisfies?)
32
+ # @param (see ShapeExpression#satisfies?)
33
+ # @return (see ShapeExpression#satisfies?)
34
+ # @raise (see ShapeExpression#satisfies?)
35
35
  def satisfies?(focus, depth: 0)
36
- expression = self.expression
37
36
  # neigh(G, n) is the neighbourhood of the node n in the graph G.
38
37
  #
39
38
  # neigh(G, n) = arcsOut(G, n) ∪ arcsIn(G, n)
@@ -43,7 +42,12 @@ module ShEx::Algebra
43
42
 
44
43
  # `matched` is the subset of statements which match `expression`.
45
44
  status("arcsIn: #{arcs_in.count}, arcsOut: #{arcs_out.count}", depth: depth)
46
- matched_expression = expression.matches(arcs_in, arcs_out, depth: depth + 1) if expression
45
+ matched_expression = case expression
46
+ when RDF::Resource
47
+ ref.matches(arcs_in, arcs_out, depth: depth + 1)
48
+ when TripleExpression
49
+ expression.matches(arcs_in, arcs_out, depth: depth + 1)
50
+ end
47
51
  matched = Array(matched_expression && matched_expression.matched)
48
52
 
49
53
  # `remainder` is the set of unmatched statements
@@ -101,12 +105,22 @@ module ShEx::Algebra
101
105
  not_satisfied e.message, focus: focus, unsatisfied: e.expression, depth: depth
102
106
  end
103
107
 
104
-
105
108
  ##
106
- # The optional TripleExpression for this Shape.
107
- # @return [TripleExpression]
108
- def expression
109
- operands.detect {|op| op.is_a?(TripleExpression)}
109
+ # expression must be a TripleExpression
110
+ #
111
+ # @return [Operator] `self`
112
+ # @raise [ShEx::StructureError] if the value is invalid
113
+ def validate!
114
+ case expression
115
+ when nil, TripleExpression
116
+ when RDF::Resource
117
+ ref = schema.find(expression)
118
+ ref.is_a?(TripleExpression) ||
119
+ structure_error("#{json_type} must reference a TripleExpression: #{ref}")
120
+ else
121
+ structure_error("#{json_type} must reference a TripleExpression: #{ref}")
122
+ end
123
+ super
110
124
  end
111
125
 
112
126
  private
@@ -2,21 +2,18 @@ require 'sparql/algebra'
2
2
 
3
3
  module ShEx::Algebra
4
4
  # Implements `satisfies?` and `not_satisfies?`
5
- module Satisfiable
5
+ module ShapeExpression
6
6
  ##
7
7
  # Satisfies method
8
8
  # @param [RDF::Resource] focus
9
9
  # @param [Integer] depth for logging
10
10
  # @param [Hash{Symbol => Object}] options
11
11
  # Other, operand-specific options
12
- # @return [Operator] with `matched` and `satisfied` accessors for matched triples and sub-expressions
12
+ # @return [ShapeExpression] with `matched` and `satisfied` accessors for matched triples and sub-expressions
13
13
  # @raise [ShEx::NotMatched] with `expression` accessor to access `matched` and `unmatched` statements along with `satisfied` and `unsatisfied` operations.
14
14
  # @see [https://shexspec.github.io/spec/#shape-expression-semantics]
15
15
  def satisfies?(focus, depth: 0, **options)
16
16
  raise NotImplementedError, "#satisfies? Not implemented in #{self.class}"
17
17
  end
18
-
19
- # This operator includes Satisfiable
20
- def satisfiable?; true; end
21
18
  end
22
19
  end
@@ -1,20 +1,50 @@
1
1
  module ShEx::Algebra
2
2
  ##
3
3
  class Start < Operator::Unary
4
- include Satisfiable
4
+ include ShapeExpression
5
5
  NAME = :start
6
6
 
7
7
  #
8
- # @param (see Satisfiable#satisfies?)
9
- # @return (see Satisfiable#satisfies?)
10
- # @raise (see Satisfiable#satisfies?)
8
+ # @param (see ShapeExpression#satisfies?)
9
+ # @return (see ShapeExpression#satisfies?)
10
+ # @raise (see ShapeExpression#satisfies?)
11
11
  def satisfies?(focus, depth: 0)
12
12
  status "", depth: depth
13
- matched_op = operands.first.satisfies?(focus, depth: depth + 1)
13
+ matched_op = case expression
14
+ when RDF::Resource
15
+ schema.enter_shape(expression, focus) do |shape|
16
+ if shape
17
+ shape.satisfies?(focus, depth: depth + 1)
18
+ else
19
+ status "Satisfy as #{expression} was re-entered for #{focus}", depth: depth
20
+ nil
21
+ end
22
+ end
23
+ when ShapeExpression
24
+ expression.satisfies?(focus, depth: depth + 1)
25
+ end
14
26
  satisfy focus: focus, satisfied: matched_op, depth: depth
15
27
  rescue ShEx::NotSatisfied => e
16
28
  not_satisfied e.message, focus: focus, unsatisfied: e.expression, depth: depth
17
29
  raise
18
30
  end
31
+
32
+ ##
33
+ # expression must be a ShapeExpression
34
+ #
35
+ # @return [Operator] `self`
36
+ # @raise [ShEx::StructureError] if the value is invalid
37
+ def validate!
38
+ case expression
39
+ when ShapeExpression
40
+ when RDF::Resource
41
+ ref = schema.find(expression)
42
+ ref.is_a?(ShapeExpression) ||
43
+ structure_error("#{json_type} must reference a ShapeExpression: #{ref}")
44
+ else
45
+ structure_error("#{json_type} must reference a ShapeExpression: #{ref}")
46
+ end
47
+ super
48
+ end
19
49
  end
20
50
  end
@@ -29,10 +29,21 @@ module ShEx::Algebra
29
29
  statements.select {|st| st.predicate == predicate}.each do |statement|
30
30
  break if num_iters == max # matched enough
31
31
 
32
- value = inverse? ? statement.subject : statement.object
32
+ focus = inverse? ? statement.subject : statement.object
33
33
 
34
34
  begin
35
- shape && (matched_shape = shape.satisfies?(value, depth: depth + 1))
35
+ matched_shape = if expression.is_a?(RDF::Resource)
36
+ schema.enter_shape(expression, focus) do |shape|
37
+ if shape
38
+ shape.satisfies?(focus, depth: depth + 1)
39
+ else
40
+ status "Satisfy as #{expression} was re-entered for #{focus}", depth: depth
41
+ nil
42
+ end
43
+ end
44
+ elsif expression
45
+ expression.satisfies?(focus, depth: depth + 1)
46
+ end
36
47
  status "matched #{statement.to_sxp}", depth: depth
37
48
  if matched_shape
38
49
  matched_shape.matched = [statement]
@@ -46,7 +57,7 @@ module ShEx::Algebra
46
57
  status "not satisfied: #{e.message}", depth: depth
47
58
  unsatisfied << e.expression
48
59
  statement = statement.dup.extend(ReferencedStatement)
49
- statement.referenced = shape
60
+ statement.referenced = expression
50
61
  unmatched << statement
51
62
  end
52
63
  end
@@ -70,7 +81,25 @@ module ShEx::Algebra
70
81
  end
71
82
 
72
83
  def predicate
73
- operands.detect {|o| o.is_a?(RDF::URI)}
84
+ @predicate ||= operands.detect {|o| o.is_a?(Array) && o.first == :predicate}.last
85
+ end
86
+
87
+ ##
88
+ # expression must be a ShapeExpression
89
+ #
90
+ # @return [Operator] `self`
91
+ # @raise [ShEx::StructureError] if the value is invalid
92
+ def validate!
93
+ case expression
94
+ when nil, ShapeExpression
95
+ when RDF::Resource
96
+ ref = schema.find(expression)
97
+ ref.is_a?(ShapeExpression) ||
98
+ structure_error("#{json_type} must reference a ShapeExpression: #{ref}")
99
+ else
100
+ structure_error("#{json_type} must reference a ShapeExpression: #{ref}")
101
+ end
102
+ super
74
103
  end
75
104
 
76
105
  ##
@@ -83,9 +112,5 @@ module ShEx::Algebra
83
112
  def inverse?
84
113
  operands.include?(:inverse)
85
114
  end
86
-
87
- def shape
88
- operands.detect {|o| o.is_a?(Satisfiable)}
89
- end
90
115
  end
91
116
  end
@@ -53,7 +53,7 @@ module ShEx::Algebra
53
53
  end
54
54
 
55
55
  module ReferencedStatement
56
- # @return [ShEx::Algebra::Satisfiable] referenced operand which satisfied some of this statement
56
+ # @return [ShEx::Algebra::ShapeExpression] referenced operand which satisfied some of this statement
57
57
  attr_accessor :referenced
58
58
 
59
59
  def to_sxp_bin
@@ -156,7 +156,10 @@ module ShEx
156
156
  production(:shexDoc) do |input, data, callback|
157
157
  data[:start] = data[:start] if data[:start]
158
158
 
159
- expressions = Array(data[:codeDecl])
159
+ expressions = []
160
+ expressions << [:base, data[:baseDecl]] if data[:baseDecl]
161
+ expressions << [:prefix, data[:prefixDecl]] if data[:prefixDecl]
162
+ expressions += Array(data[:codeDecl])
160
163
  expressions << Algebra::Start.new(data[:start]) if data[:start]
161
164
  expressions << data[:shapes].unshift(:shapes) if data[:shapes]
162
165
 
@@ -168,13 +171,14 @@ module ShEx
168
171
 
169
172
  # [3] baseDecl ::= "BASE" IRIREF
170
173
  production(:baseDecl) do |input, data, callback|
171
- self.base_uri = iri(data[:iri])
174
+ input[:baseDecl] = self.base_uri = iri(data[:iri])
172
175
  end
173
176
 
174
177
  # [4] prefixDecl ::= "PREFIX" PNAME_NS IRIREF
175
178
  production(:prefixDecl) do |input, data, callback|
176
179
  pfx = data[:prefix]
177
180
  self.prefix(pfx, data[:iri])
181
+ (input[:prefixDecl] ||= []) << [pfx.to_s, data[:iri]]
178
182
  end
179
183
 
180
184
  # [5] notStartAction ::= start | shapeExprDecl
@@ -188,14 +192,14 @@ module ShEx
188
192
 
189
193
  # [9] shapeExprDecl ::= shapeLabel (shapeExpression|"EXTERNAL")
190
194
  production(:shapeExprDecl) do |input, data, callback|
191
- label = Array(data[:shapeLabel]).first
195
+ id = Array(data[:shapeLabel]).first
192
196
  expression = case data[:shapeExpression]
193
- when Algebra::NodeConstraint, Algebra::Or, Algebra::And, Algebra::Not, Algebra::ShapeRef, Algebra::Shape
197
+ when Algebra::NodeConstraint, Algebra::Or, Algebra::And, Algebra::Not, Algebra::Shape, RDF::Resource
194
198
  data[:shapeExpression]
195
199
  else
196
200
  data[:external] ? Algebra::External.new() : Algebra::Shape.new()
197
201
  end
198
- expression.label = label
202
+ expression.id = id if id && !expression.is_a?(RDF::Resource)
199
203
 
200
204
  (input[:shapes] ||= []) << expression
201
205
  end
@@ -214,7 +218,7 @@ module ShEx
214
218
  def shape_or(input, data)
215
219
  input.merge!(data.dup.keep_if {|k, v| [:closed, :extraPropertySet, :codeDecl].include?(k)})
216
220
  expression = if Array(data[:shapeExpression]).length > 1
217
- Algebra::Or.new(*data[:shapeExpression])
221
+ Algebra::Or.new(*data[:shapeExpression], {})
218
222
  else
219
223
  Array(data[:shapeExpression]).first
220
224
  end
@@ -238,7 +242,7 @@ module ShEx
238
242
  memo.concat(expr.is_a?(Algebra::And) ? expr.operands : [expr])
239
243
  end
240
244
  expression = if expressions.length > 1
241
- Algebra::And.new(*expressions)
245
+ Algebra::And.new(*expressions, {})
242
246
  else
243
247
  expressions.first
244
248
  end
@@ -287,9 +291,8 @@ module ShEx
287
291
  expression = [constraint, shape].compact
288
292
  expression = case expression.length
289
293
  when 0 then nil
290
- when 1
291
- expression.first
292
- else Algebra::And.new(*expression)
294
+ when 1 then expression.first
295
+ else Algebra::And.new(*expression, {})
293
296
  end
294
297
 
295
298
  input[:shapeExpression] = expression if expression
@@ -307,7 +310,7 @@ module ShEx
307
310
  def shape_or_ref(input, data)
308
311
  input.merge!(data.dup.keep_if {|k, v| [:closed, :extraPropertySet, :codeDecl].include?(k)})
309
312
  if data[:shape] || Array(data[:shapeLabel]).first
310
- input[:shapeOrRef] = data[:shape] || Algebra::ShapeRef.new(Array(data[:shapeLabel]).first)
313
+ input[:shapeOrRef] = data[:shape] || Array(data[:shapeLabel]).first
311
314
  end
312
315
  rescue ArgumentError => e
313
316
  error(nil, "Argument Error on ShapeOrRef: #{e.message}")
@@ -335,7 +338,7 @@ module ShEx
335
338
  attrs += Array(data[:numericFacet])
336
339
  attrs += Array(data[:stringFacet])
337
340
 
338
- input[:nodeConstraint] = Algebra::NodeConstraint.new(*attrs.compact)
341
+ input[:nodeConstraint] = Algebra::NodeConstraint.new(*attrs.compact, {})
339
342
  end
340
343
 
341
344
  # [23] nonLiteralKind ::= "IRI" | "BNODE" | "NONLITERAL"
@@ -390,7 +393,7 @@ module ShEx
390
393
  attrs += Array(data[:annotation])
391
394
  attrs += Array(data[:codeDecl])
392
395
 
393
- input[:shape] = Algebra::Shape.new(*attrs) if expression
396
+ input[:shape] = Algebra::Shape.new(*attrs, {}) if expression
394
397
  end
395
398
  private :shape_definition
396
399
 
@@ -403,7 +406,7 @@ module ShEx
403
406
  # [34] oneOfTripleExpr ::= groupTripleExpr ('|' groupTripleExpr)*
404
407
  production(:oneOfTripleExpr) do |input, data, callback|
405
408
  expression = if Array(data[:tripleExpression]).length > 1
406
- Algebra::OneOf.new(*data[:tripleExpression])
409
+ Algebra::OneOf.new(*data[:tripleExpression], {})
407
410
  else
408
411
  Array(data[:tripleExpression]).first
409
412
  end
@@ -413,7 +416,7 @@ module ShEx
413
416
  # [37] groupTripleExpr ::= unaryTripleExpr (';' unaryTripleExpr?)*
414
417
  production(:groupTripleExpr) do |input, data, callback|
415
418
  expression = if Array(data[:tripleExpression]).length > 1
416
- Algebra::EachOf.new(*data[:tripleExpression])
419
+ Algebra::EachOf.new(*data[:tripleExpression], {})
417
420
  else
418
421
  Array(data[:tripleExpression]).first
419
422
  end
@@ -423,7 +426,7 @@ module ShEx
423
426
  # [40] unaryTripleExpr ::= productionLabel? (tripleConstraint | bracketedTripleExpr) | include
424
427
  production(:unaryTripleExpr) do |input, data, callback|
425
428
  expression = data[:tripleExpression]
426
- expression.label = data[:productionLabel] if expression && data[:productionLabel]
429
+ expression.id = data[:productionLabel] if expression && data[:productionLabel]
427
430
 
428
431
  (input[:tripleExpression] ||= []) << expression if expression
429
432
  end
@@ -458,7 +461,7 @@ module ShEx
458
461
  cardinality = data.fetch(:cardinality, {})
459
462
  attrs = [
460
463
  (:inverse if data[:inverse] || data[:not]),
461
- Array(data[:predicate]).first, # predicate
464
+ [:predicate, Array(data[:predicate]).first],
462
465
  data[:shapeExpression],
463
466
  ([:min, cardinality[:min]] if cardinality[:min]),
464
467
  ([:max, cardinality[:max]] if cardinality[:max])
@@ -466,7 +469,7 @@ module ShEx
466
469
  attrs += Array(data[:codeDecl])
467
470
  attrs += Array(data[:annotation])
468
471
 
469
- input[:tripleExpression] = Algebra::TripleConstraint.new(*attrs) unless attrs.empty?
472
+ input[:tripleExpression] = Algebra::TripleConstraint.new(*attrs, {}) unless attrs.empty?
470
473
  end
471
474
 
472
475
  # [44] cardinality ::= '*' | '+' | '?' | REPEAT_RANGE
@@ -499,12 +502,12 @@ module ShEx
499
502
 
500
503
  # [50] include ::= '&' shapeLabel
501
504
  production(:include) do |input, data, callback|
502
- input[:tripleExpression] = Algebra::Inclusion.new(*data[:shapeLabel])
505
+ input[:tripleExpression] = data[:shapeLabel].first
503
506
  end
504
507
 
505
508
  # [51] annotation ::= '//' predicate (iri | literal)
506
509
  production(:annotation) do |input, data, callback|
507
- annotation = Algebra::Annotation.new(data[:predicate].first, (data[:iri] || data[:literal]))
510
+ annotation = Algebra::Annotation.new([:predicate, data[:predicate].first], (data[:iri] || data[:literal]))
508
511
  (input[:annotation] ||= []) << annotation
509
512
  end
510
513
 
@@ -512,7 +515,7 @@ module ShEx
512
515
 
513
516
  # [53] codeDecl ::= '%' iri (CODE | "%")
514
517
  production(:codeDecl) do |input, data, callback|
515
- (input[:codeDecl] ||= []) << Algebra::SemAct.new(*[data[:iri], data[:code]].compact)
518
+ (input[:codeDecl] ||= []) << Algebra::SemAct.new(*[data[:iri], data[:code]].compact, {})
516
519
  end
517
520
 
518
521
  # [13t] literal ::= rdfLiteral | numericLiteral | booleanLiteral
@@ -662,7 +665,7 @@ module ShEx
662
665
  @result.validate! if @result && validate?
663
666
  @result
664
667
  rescue EBNF::LL1::Parser::Error, EBNF::LL1::Lexer::Error => e
665
- raise ShEx::ParseError.new(e.message, lineno: e.lineno, token: e.token)
668
+ raise ShEx::ParseError, e.message, e.backtrace
666
669
  end
667
670
 
668
671
  private