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