shex 0.2.0 → 0.3.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.
- checksums.yaml +4 -4
- data/README.md +119 -2
- data/VERSION +1 -1
- data/etc/doap.ttl +2 -2
- data/lib/shex.rb +21 -2
- data/lib/shex/algebra.rb +41 -3
- data/lib/shex/algebra/and.rb +27 -6
- data/lib/shex/algebra/annotation.rb +19 -0
- data/lib/shex/algebra/each_of.rb +32 -19
- data/lib/shex/algebra/external.rb +9 -6
- data/lib/shex/algebra/inclusion.rb +29 -18
- data/lib/shex/algebra/node_constraint.rb +45 -36
- data/lib/shex/algebra/not.rb +19 -4
- data/lib/shex/algebra/one_of.rb +26 -16
- data/lib/shex/algebra/operator.rb +350 -34
- data/lib/shex/algebra/or.rb +26 -9
- data/lib/shex/algebra/satisfiable.rb +5 -9
- data/lib/shex/algebra/schema.rb +87 -75
- data/lib/shex/algebra/semact.rb +69 -19
- data/lib/shex/algebra/shape.rb +28 -19
- data/lib/shex/algebra/shape_ref.rb +36 -10
- data/lib/shex/algebra/start.rb +5 -5
- data/lib/shex/algebra/stem.rb +18 -3
- data/lib/shex/algebra/stem_range.rb +24 -5
- data/lib/shex/algebra/triple_constraint.rb +26 -13
- data/lib/shex/algebra/triple_expression.rb +3 -2
- data/lib/shex/algebra/value.rb +5 -5
- data/lib/shex/extensions/extension.rb +160 -0
- data/lib/shex/extensions/test.rb +26 -0
- data/lib/shex/parser.rb +12 -25
- data/lib/shex/shex_context.rb +85 -0
- data/lib/shex/version.rb +19 -0
- metadata +35 -11
- data/lib/shex/algebra/base.rb +0 -6
- data/lib/shex/algebra/prefix.rb +0 -6
- data/lib/shex/algebra/unary_shape.rb +0 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d83ac4fdd795f4d27280e23fc431a42faa72dd7
|
4
|
+
data.tar.gz: 61b80075c76f018481226ed563fa7ec44fe0c35f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a158d18cdfbe1c0ae951549bbafc0e8d2d312cc08d259eefe76729e192db380b60a63b0d4a525cc4c49eee8f3092b9fd82cee03fe174cf8ab334c57bb943a4f
|
7
|
+
data.tar.gz: 5078624090859f18d37daf162baadcca943533c4bd35eb3e52299c737a18b3c7ab85e1d3e0d4819f3d7a12b9c97e308e580b7d408a43d866ee1264331bb01d73
|
data/README.md
CHANGED
@@ -19,10 +19,12 @@ This is a pure-Ruby library for working with the [Shape Expressions Language][Sh
|
|
19
19
|
|
20
20
|
The ShEx gem implements a [ShEx][ShExSpec] Shape Expression engine.
|
21
21
|
|
22
|
-
* `ShEx::Parser` parses ShExC formatted documents generating executable operators which can be serialized as [S-Expressions](http://en.wikipedia.org/wiki/S-expression).
|
22
|
+
* `ShEx::Parser` parses ShExC and ShExJ formatted documents generating executable operators which can be serialized as [S-Expressions](http://en.wikipedia.org/wiki/S-expression).
|
23
23
|
* `ShEx::Algebra` executes operators against Any `RDF::Graph`, including compliant [RDF.rb][].
|
24
|
+
* [Implementation Report](file.earl.html)
|
24
25
|
|
25
|
-
##
|
26
|
+
## Examples
|
27
|
+
### Validating a node using ShExC
|
26
28
|
|
27
29
|
require 'rubygems'
|
28
30
|
require 'rdf/turtle'
|
@@ -46,6 +48,121 @@ The ShEx gem implements a [ShEx][ShExSpec] Shape Expression engine.
|
|
46
48
|
}
|
47
49
|
schema.satisfies?("http://rubygems.org/gems/shex", graph, map)
|
48
50
|
# => true
|
51
|
+
### Validating a node using ShExC
|
52
|
+
|
53
|
+
require 'rubygems'
|
54
|
+
require 'rdf/turtle'
|
55
|
+
require 'shex'
|
56
|
+
|
57
|
+
shexj: %({
|
58
|
+
"type": "Schema",
|
59
|
+
"prefixes": {
|
60
|
+
"doap": "http://usefulinc.com/ns/doap#",
|
61
|
+
"dc": "http://purl.org/dc/terms/"
|
62
|
+
},
|
63
|
+
"shapes": {
|
64
|
+
"TestShape": {
|
65
|
+
"type": "Shape",
|
66
|
+
"extra": ["http://www.w3.org/1999/02/22-rdf-syntax-ns#type"],
|
67
|
+
"expression": {
|
68
|
+
"type": "EachOf",
|
69
|
+
"expressions": [
|
70
|
+
{
|
71
|
+
"type": "TripleConstraint",
|
72
|
+
"predicate": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type",
|
73
|
+
"valueExpr": {
|
74
|
+
"type": "NodeConstraint",
|
75
|
+
"values": ["http://usefulinc.com/ns/doap#Project"]
|
76
|
+
}
|
77
|
+
},
|
78
|
+
{
|
79
|
+
"type": "OneOf",
|
80
|
+
"expressions": [
|
81
|
+
{
|
82
|
+
"type": "EachOf",
|
83
|
+
"expressions": [
|
84
|
+
{
|
85
|
+
"type": "TripleConstraint",
|
86
|
+
"predicate": "http://usefulinc.com/ns/doap#name",
|
87
|
+
"valueExpr": {"type": "NodeConstraint", "nodeKind": "literal"}
|
88
|
+
},
|
89
|
+
{
|
90
|
+
"type": "TripleConstraint",
|
91
|
+
"predicate": "http://usefulinc.com/ns/doap#description",
|
92
|
+
"valueExpr": {"type": "NodeConstraint", "nodeKind": "literal"}
|
93
|
+
}
|
94
|
+
]
|
95
|
+
},
|
96
|
+
{
|
97
|
+
"type": "EachOf",
|
98
|
+
"expressions": [
|
99
|
+
{
|
100
|
+
"type": "TripleConstraint",
|
101
|
+
"predicate": "http://purl.org/dc/terms/title",
|
102
|
+
"valueExpr": {"type": "NodeConstraint", "nodeKind": "literal"}
|
103
|
+
},
|
104
|
+
{
|
105
|
+
"type": "TripleConstraint",
|
106
|
+
"predicate": "http://purl.org/dc/terms/description",
|
107
|
+
"valueExpr": {"type": "NodeConstraint", "nodeKind": "literal"}
|
108
|
+
}
|
109
|
+
]
|
110
|
+
}
|
111
|
+
],
|
112
|
+
"min": 1, "max": "*"
|
113
|
+
},
|
114
|
+
{
|
115
|
+
"type": "TripleConstraint",
|
116
|
+
"predicate": "http://usefulinc.com/ns/doap#category",
|
117
|
+
"valueExpr": {"type": "NodeConstraint", "nodeKind": "iri"},
|
118
|
+
"min": 0, "max": "*"
|
119
|
+
},
|
120
|
+
{
|
121
|
+
"type": "TripleConstraint",
|
122
|
+
"predicate": "http://usefulinc.com/ns/doap#developer",
|
123
|
+
"valueExpr": {"type": "NodeConstraint", "nodeKind": "iri"},
|
124
|
+
"min": 1, "max": "*"
|
125
|
+
},
|
126
|
+
{
|
127
|
+
"type": "TripleConstraint",
|
128
|
+
"predicate": "http://usefulinc.com/ns/doap#implements",
|
129
|
+
"valueExpr": {
|
130
|
+
"type": "NodeConstraint",
|
131
|
+
"values": ["https://shexspec.github.io/spec/"]
|
132
|
+
}
|
133
|
+
}
|
134
|
+
]
|
135
|
+
}
|
136
|
+
}
|
137
|
+
}
|
138
|
+
})
|
139
|
+
graph = RDF::Graph.load("etc/doap.ttl")
|
140
|
+
schema = ShEx.parse(shexj, format: :shexj)
|
141
|
+
map = {"http://rubygems.org/gems/shex" => "TestShape"}
|
142
|
+
schema.satisfies?("http://rubygems.org/gems/shex", graph, map)
|
143
|
+
# => true
|
144
|
+
|
145
|
+
## Extensions
|
146
|
+
ShEx has an extension mechanism using [Semantic Actions](https://shexspec.github.io/spec/#semantic-actions). Extensions may be implemented in Ruby ShEx by sub-classing {ShEx::Extension} and implementing {ShEx::Extension#visit} and possibly {ShEx::Extension#initialize}, {ShEx::Extension#enter}, {ShEx::Extension#exit}, and {ShEx::Extension#close}. The `#visit` method will be called as part of the `#satisfies?` operation.
|
147
|
+
|
148
|
+
require 'shex'
|
149
|
+
class ShEx::Test < ShEx::Extension("http://shex.io/extensions/Test/")
|
150
|
+
# (see ShEx::Extension#initialize)
|
151
|
+
def initialize(schema: nil, logger: nil, depth: 0, **options)
|
152
|
+
...
|
153
|
+
end
|
154
|
+
|
155
|
+
# (see ShEx::Extension#visit)
|
156
|
+
def visit(code: nil, matched: nil, expression: nil, depth: 0, **options)
|
157
|
+
...
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
The `#enter` method will be called on any {ShEx::Algebra::TripleExpression} that includes a {ShEx::Algebra::SemAct} referencing the extension, while the `#exit` method will be called on exit, even if not satisfied.
|
162
|
+
|
163
|
+
The `#initialize` method is called when {ShEx::Algebra::Schema#execute} starts and `#close` called on exit, even if not satisfied.
|
164
|
+
|
165
|
+
To make sure your extension is found, make sure to require it before the shape is executed.
|
49
166
|
|
50
167
|
## Documentation
|
51
168
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/etc/doap.ttl
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
|
9
9
|
|
10
10
|
<http://rubygems.org/gems/shex> a doap:Project, earl:TestSubject, earl:Software ;
|
11
|
-
doap:name "ShEx" ;
|
11
|
+
doap:name "ShEx.rb" ;
|
12
12
|
doap:homepage <http://ruby-rdf.github.com/shex> ;
|
13
13
|
doap:license <http://creativecommons.org/licenses/publicdomain/> ;
|
14
14
|
doap:shortdesc "ShEx is a Shape Expression engine for Ruby."@en ;
|
@@ -26,7 +26,7 @@
|
|
26
26
|
doap:maintainer <http://greggkellogg.net/foaf#me> ;
|
27
27
|
doap:documenter <http://greggkellogg.net/foaf#me> ;
|
28
28
|
foaf:maker <http://greggkellogg.net/foaf#me> ;
|
29
|
-
dc:title "ShEx" ;
|
29
|
+
dc:title "ShEx.rb" ;
|
30
30
|
dc:description "ShEx is an Shape Expression engine for the RDF.rb library suite."@en ;
|
31
31
|
dc:date "2016-12-09"^^xsd:date ;
|
32
32
|
dc:creator <http://greggkellogg.net/foaf#me> ;
|
data/lib/shex.rb
CHANGED
@@ -6,9 +6,16 @@ module ShEx
|
|
6
6
|
autoload :Algebra, 'shex/algebra'
|
7
7
|
autoload :Meta, 'shex/meta'
|
8
8
|
autoload :Parser, 'shex/parser'
|
9
|
+
autoload :Extension, 'shex/extensions/extension'
|
9
10
|
autoload :Terminals, 'shex/terminals'
|
10
11
|
autoload :VERSION, 'shex/version'
|
11
12
|
|
13
|
+
# Location of the ShEx JSON-LD context
|
14
|
+
CONTEXT = "https://shexspec.github.io/context.jsonld"
|
15
|
+
|
16
|
+
# Extensions defined in this gem
|
17
|
+
EXTENSIONS = %w{test}
|
18
|
+
|
12
19
|
##
|
13
20
|
# Parse the given ShEx `query` string.
|
14
21
|
#
|
@@ -24,10 +31,14 @@ module ShEx
|
|
24
31
|
# @return (see ShEx::Parser#parse)
|
25
32
|
# @raise (see ShEx::Parser#parse)
|
26
33
|
def self.parse(expression, format: 'shexc', **options)
|
27
|
-
case format
|
34
|
+
case format.to_s
|
28
35
|
when 'shexc' then Parser.new(expression, options).parse
|
29
36
|
when 'shexj'
|
37
|
+
expression = expression.read if expression.respond_to?(:read)
|
38
|
+
Algebra.from_shexj(JSON.parse expression)
|
30
39
|
when 'sxp'
|
40
|
+
expression = expression.read if expression.respond_to?(:read)
|
41
|
+
Algebra.from_sxp(JSON.parse expression)
|
31
42
|
else raise "Unknown expression format: #{format.inspect}"
|
32
43
|
end
|
33
44
|
end
|
@@ -85,6 +96,15 @@ module ShEx
|
|
85
96
|
shex.satisfies?(focus, queryable, {focus => shape}, options)
|
86
97
|
end
|
87
98
|
|
99
|
+
##
|
100
|
+
# Alias for `ShEx::Extension.create`.
|
101
|
+
#
|
102
|
+
# @param (see ShEx::Extension#create)
|
103
|
+
# @return [Class]
|
104
|
+
def self.Extension(uri)
|
105
|
+
Extension.send(:create, uri)
|
106
|
+
end
|
107
|
+
|
88
108
|
class Error < StandardError
|
89
109
|
# The status code associated with this error
|
90
110
|
attr_reader :code
|
@@ -167,7 +187,6 @@ module ShEx
|
|
167
187
|
# ParseError includes `token` and `lineno` associated with the expression.
|
168
188
|
#
|
169
189
|
# @param [String, #to_s] message
|
170
|
-
# @param [Hash{Symbol => Object}] options
|
171
190
|
# @param [String] token (nil)
|
172
191
|
# @param [Integer] lineno (nil)
|
173
192
|
def initialize(message, token: nil, lineno: nil)
|
data/lib/shex/algebra.rb
CHANGED
@@ -9,7 +9,6 @@ module ShEx
|
|
9
9
|
module Algebra
|
10
10
|
autoload :And, 'shex/algebra/and'
|
11
11
|
autoload :Annotation, 'shex/algebra/annotation'
|
12
|
-
autoload :Base, 'shex/algebra/base'
|
13
12
|
autoload :EachOf, 'shex/algebra/each_of'
|
14
13
|
autoload :Inclusion, 'shex/algebra/inclusion'
|
15
14
|
autoload :Not, 'shex/algebra/not'
|
@@ -17,7 +16,6 @@ module ShEx
|
|
17
16
|
autoload :OneOf, 'shex/algebra/one_of'
|
18
17
|
autoload :Operator, 'shex/algebra/operator'
|
19
18
|
autoload :Or, 'shex/algebra/or'
|
20
|
-
autoload :Prefix, 'shex/algebra/prefix'
|
21
19
|
autoload :Satisfiable, 'shex/algebra/satisfiable'
|
22
20
|
autoload :Schema, 'shex/algebra/schema'
|
23
21
|
autoload :SemAct, 'shex/algebra/semact'
|
@@ -29,8 +27,48 @@ module ShEx
|
|
29
27
|
autoload :StemRange, 'shex/algebra/stem_range'
|
30
28
|
autoload :TripleConstraint, 'shex/algebra/triple_constraint'
|
31
29
|
autoload :TripleExpression, 'shex/algebra/triple_expression'
|
32
|
-
autoload :UnaryShape, 'shex/algebra/unary_shape'
|
33
30
|
autoload :Value, 'shex/algebra/value'
|
31
|
+
|
32
|
+
|
33
|
+
##
|
34
|
+
# Creates an operator instance from a parsed ShExJ representation
|
35
|
+
#
|
36
|
+
# @example Simple TripleConstraint
|
37
|
+
# rep = JSON.parse(%({
|
38
|
+
# "type": "TripleConstraint",
|
39
|
+
# "predicate": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
|
40
|
+
# }
|
41
|
+
# ))
|
42
|
+
# TripleConstraint.from(rep) #=> (tripleConstraint a)
|
43
|
+
# @param [Hash] operator
|
44
|
+
# @param [Hash] options ({})
|
45
|
+
# @option options [RDF::URI] :base
|
46
|
+
# @option options [Hash{String => RDF::URI}] :prefixes
|
47
|
+
# @return [Operator]
|
48
|
+
def self.from_shexj(operator, options = {})
|
49
|
+
raise ArgumentError unless operator.is_a?(Hash)
|
50
|
+
klass = case operator['type']
|
51
|
+
when 'Annotation' then Annotation
|
52
|
+
when 'EachOf' then EachOf
|
53
|
+
when 'Inclusion' then Inclusion
|
54
|
+
when 'NodeConstraint' then NodeConstraint
|
55
|
+
when 'OneOf' then OneOf
|
56
|
+
when 'Schema' then Schema
|
57
|
+
when 'SemAct' then SemAct
|
58
|
+
when 'Shape' then Shape
|
59
|
+
when 'ShapeAnd' then And
|
60
|
+
when 'ShapeNot' then Not
|
61
|
+
when 'ShapeOr' then Or
|
62
|
+
when 'ShapeRef' then ShapeRef
|
63
|
+
when 'Stem' then Stem
|
64
|
+
when 'StemRange' then StemRange
|
65
|
+
when 'TripleConstraint' then TripleConstraint
|
66
|
+
when 'Wildcard' then StemRange
|
67
|
+
else raise ArgumentError, "unknown type #{operator['type']}"
|
68
|
+
end
|
69
|
+
|
70
|
+
klass.from_shexj(operator, options)
|
71
|
+
end
|
34
72
|
end
|
35
73
|
end
|
36
74
|
|
data/lib/shex/algebra/and.rb
CHANGED
@@ -6,9 +6,22 @@ module ShEx::Algebra
|
|
6
6
|
|
7
7
|
def initialize(*args, **options)
|
8
8
|
case
|
9
|
-
when args.length
|
10
|
-
raise ArgumentError, "wrong number of arguments (given #{args.length}, expected
|
9
|
+
when args.length < 2
|
10
|
+
raise ArgumentError, "wrong number of arguments (given #{args.length}, expected 2..)"
|
11
11
|
end
|
12
|
+
|
13
|
+
# All arguments must be Satisfiable
|
14
|
+
raise ArgumentError, "All operands must be Shape operands" unless args.all? {|o| o.is_a?(Satisfiable)}
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
##
|
19
|
+
# Creates an operator instance from a parsed ShExJ representation
|
20
|
+
# @param (see Operator#from_shexj)
|
21
|
+
# @return [Operator]
|
22
|
+
def self.from_shexj(operator, options = {})
|
23
|
+
raise ArgumentError unless operator.is_a?(Hash) && operator['type'] == 'ShapeAnd'
|
24
|
+
raise ArgumentError, "missing shapeExprs in #{operator.inspect}" unless operator.has_key?('shapeExprs')
|
12
25
|
super
|
13
26
|
end
|
14
27
|
|
@@ -17,20 +30,28 @@ module ShEx::Algebra
|
|
17
30
|
# @param (see Satisfiable#satisfies?)
|
18
31
|
# @return (see Satisfiable#satisfies?)
|
19
32
|
# @raise (see Satisfiable#satisfies?)
|
20
|
-
def satisfies?(focus)
|
33
|
+
def satisfies?(focus, depth: 0)
|
21
34
|
status ""
|
22
35
|
expressions = operands.select {|o| o.is_a?(Satisfiable)}
|
23
36
|
satisfied = []
|
37
|
+
unsatisfied = expressions.dup
|
24
38
|
|
25
39
|
# Operand raises NotSatisfied, so no need to check here.
|
26
40
|
expressions.each do |op|
|
27
|
-
satisfied << op.satisfies?(focus)
|
41
|
+
satisfied << op.satisfies?(focus, depth: depth)
|
42
|
+
unsatisfied.shift
|
28
43
|
end
|
29
|
-
satisfy satisfied: satisfied
|
44
|
+
satisfy focus: focus, satisfied: satisfied, depth: depth
|
30
45
|
rescue ShEx::NotSatisfied => e
|
31
46
|
not_satisfied e.message,
|
47
|
+
focus: focus,
|
32
48
|
satisfied: satisfied,
|
33
|
-
unsatisfied:
|
49
|
+
unsatisfied: unsatisfied,
|
50
|
+
depth: depth
|
51
|
+
end
|
52
|
+
|
53
|
+
def json_type
|
54
|
+
"ShapeAnd"
|
34
55
|
end
|
35
56
|
end
|
36
57
|
end
|
@@ -2,5 +2,24 @@ module ShEx::Algebra
|
|
2
2
|
##
|
3
3
|
class Annotation < Operator
|
4
4
|
NAME = :annotation
|
5
|
+
|
6
|
+
##
|
7
|
+
# Creates an operator instance from a parsed ShExJ representation
|
8
|
+
# @param (see Operator#from_shexj)
|
9
|
+
# @return [Operator]
|
10
|
+
def self.from_shexj(operator, options = {})
|
11
|
+
raise ArgumentError unless operator.is_a?(Hash) && operator['type'] == "Annotation"
|
12
|
+
raise ArgumentError, "missing predicate in #{operator.inspect}" unless operator.has_key?('predicate')
|
13
|
+
raise ArgumentError, "missing object in #{operator.inspect}" unless operator.has_key?('object')
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_h
|
18
|
+
{
|
19
|
+
'type' => json_type,
|
20
|
+
'predicate' => operands.first.to_s,
|
21
|
+
'object' => serialize_value(operands.last)
|
22
|
+
}
|
23
|
+
end
|
5
24
|
end
|
6
25
|
end
|
data/lib/shex/algebra/each_of.rb
CHANGED
@@ -4,39 +4,51 @@ module ShEx::Algebra
|
|
4
4
|
include TripleExpression
|
5
5
|
NAME = :eachOf
|
6
6
|
|
7
|
+
##
|
8
|
+
# Creates an operator instance from a parsed ShExJ representation
|
9
|
+
# @param (see Operator#from_shexj)
|
10
|
+
# @return [Operator]
|
11
|
+
def self.from_shexj(operator, options = {})
|
12
|
+
raise ArgumentError unless operator.is_a?(Hash) && operator['type'] == 'EachOf'
|
13
|
+
raise ArgumentError, "missing expressions in #{operator.inspect}" unless operator.has_key?('expressions')
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
7
17
|
##
|
8
18
|
# expr is an EachOf and there is some partition of T into T1, T2,… such that for every expression expr1, expr2,… in shapeExprs, matches(Tn, exprn, m)...
|
9
19
|
#
|
10
|
-
# @param
|
11
|
-
# @return
|
12
|
-
# @raise
|
13
|
-
def matches(
|
14
|
-
status ""
|
20
|
+
# @param (see TripleExpression#matches)
|
21
|
+
# @return (see TripleExpression#matches)
|
22
|
+
# @raise (see TripleExpression#matches)
|
23
|
+
def matches(arcs_in, arcs_out, depth: 0)
|
24
|
+
status "", depth: depth
|
15
25
|
results, satisfied, unsatisfied = [], [], []
|
16
26
|
num_iters, max = 0, maximum
|
17
27
|
|
28
|
+
# enter semantic acts
|
29
|
+
semantic_actions.each {|op| op.enter(arcs_in: arcs_in, arcs_out: arcs_out, depth: depth + 1)}
|
30
|
+
|
18
31
|
while num_iters < max
|
19
32
|
begin
|
20
33
|
matched_this_iter = []
|
21
34
|
operands.select {|o| o.is_a?(TripleExpression)}.all? do |op|
|
22
35
|
begin
|
23
|
-
matched_op = op.matches(
|
36
|
+
matched_op = op.matches(arcs_in - matched_this_iter, arcs_out - matched_this_iter, depth: depth + 1)
|
24
37
|
satisfied << matched_op
|
25
38
|
matched_this_iter += matched_op.matched
|
26
39
|
rescue ShEx::NotMatched => e
|
27
|
-
status "not matched: #{e.message}"
|
28
|
-
|
29
|
-
op.unmatched = statements - matched_this_iter
|
30
|
-
unsatisfied << op
|
40
|
+
status "not matched: #{e.message}", depth: depth
|
41
|
+
unsatisfied << e.expression
|
31
42
|
raise
|
32
43
|
end
|
33
44
|
end
|
34
45
|
results += matched_this_iter
|
35
|
-
|
46
|
+
arcs_in -= matched_this_iter
|
47
|
+
arcs_out -= matched_this_iter
|
36
48
|
num_iters += 1
|
37
|
-
status "matched #{results.length} statements after #{num_iters} iterations"
|
49
|
+
status "matched #{results.length} statements after #{num_iters} iterations", depth: depth
|
38
50
|
rescue ShEx::NotMatched => e
|
39
|
-
status "no match after #{num_iters} iterations (ignored)"
|
51
|
+
status "no match after #{num_iters} iterations (ignored)", depth: depth
|
40
52
|
break
|
41
53
|
end
|
42
54
|
end
|
@@ -47,15 +59,16 @@ module ShEx::Algebra
|
|
47
59
|
end
|
48
60
|
|
49
61
|
# Last, evaluate semantic acts
|
50
|
-
semantic_actions.
|
51
|
-
op.satisfies?(results)
|
52
|
-
end unless results.empty?
|
62
|
+
semantic_actions.each {|op| op.satisfies?(nil, matched: results, depth: depth + 1)}
|
53
63
|
|
54
|
-
satisfy matched: results, satisfied: satisfied
|
64
|
+
satisfy matched: results, satisfied: satisfied, depth: depth
|
55
65
|
rescue ShEx::NotMatched, ShEx::NotSatisfied => e
|
56
66
|
not_matched e.message,
|
57
|
-
matched: results, unmatched: (
|
58
|
-
satisfied: satisfied, unsatisfied: unsatisfied
|
67
|
+
matched: results, unmatched: ((arcs_in + arcs_out).uniq - results),
|
68
|
+
satisfied: satisfied, unsatisfied: unsatisfied,
|
69
|
+
depth: depth
|
70
|
+
ensure
|
71
|
+
semantic_actions.each {|op| op.exit(matched: matched, depth: depth + 1)}
|
59
72
|
end
|
60
73
|
end
|
61
74
|
end
|