shex 0.3.0 → 0.4.0

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.
@@ -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