ldpath 0.1.0 → 0.2.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/.rubocop.yml +7 -0
- data/.rubocop_hound.yml +1063 -0
- data/.rubocop_todo.yml +36 -0
- data/Gemfile +0 -1
- data/Rakefile +1 -1
- data/bin/ldpath +3 -3
- data/lib/ldpath.rb +3 -3
- data/lib/ldpath/field_mapping.rb +1 -2
- data/lib/ldpath/functions.rb +80 -73
- data/lib/ldpath/parser.rb +323 -258
- data/lib/ldpath/program.rb +23 -24
- data/lib/ldpath/selectors.rb +42 -43
- data/lib/ldpath/tests.rb +28 -31
- data/lib/ldpath/transform.rb +45 -47
- data/lib/ldpath/version.rb +1 -1
- data/spec/ldpath_parser_spec.rb +132 -72
- data/spec/ldpath_program_spec.rb +19 -25
- data/spec/ldpath_transform_spec.rb +114 -36
- data/spec/lib/functions/list_spec.rb +61 -0
- data/spec/spec_helper.rb +1 -1
- metadata +8 -3
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# This configuration was generated by `rubocop --auto-gen-config`
|
2
|
+
# on 2015-05-03 18:22:33 -0700 using RuboCop version 0.30.0.
|
3
|
+
# The point is for the user to remove these configuration records
|
4
|
+
# one by one as the offenses are removed from the code base.
|
5
|
+
# Note that changes in the inspected code, or installation of new
|
6
|
+
# versions of RuboCop, may require this file to be generated again.
|
7
|
+
|
8
|
+
# Offense count: 1
|
9
|
+
# Cop supports --auto-correct.
|
10
|
+
Lint/UnusedBlockArgument:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
# Offense count: 68
|
14
|
+
# Cop supports --auto-correct.
|
15
|
+
Lint/UnusedMethodArgument:
|
16
|
+
Enabled: false
|
17
|
+
|
18
|
+
# Offense count: 4
|
19
|
+
Metrics/AbcSize:
|
20
|
+
Max: 28
|
21
|
+
|
22
|
+
# Offense count: 47
|
23
|
+
# Configuration parameters: AllowURI, URISchemes.
|
24
|
+
Metrics/LineLength:
|
25
|
+
Max: 171
|
26
|
+
|
27
|
+
# Offense count: 7
|
28
|
+
# Cop supports --auto-correct.
|
29
|
+
Style/ExtraSpacing:
|
30
|
+
Enabled: false
|
31
|
+
|
32
|
+
# Offense count: 42
|
33
|
+
# Cop supports --auto-correct.
|
34
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
35
|
+
Style/StringLiterals:
|
36
|
+
Enabled: false
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
data/bin/ldpath
CHANGED
@@ -6,8 +6,8 @@ require 'ldpath'
|
|
6
6
|
require 'byebug'
|
7
7
|
|
8
8
|
begin
|
9
|
-
require 'rest-client'
|
10
|
-
rescue LoadError
|
9
|
+
require 'rest-client'
|
10
|
+
rescue LoadError
|
11
11
|
end
|
12
12
|
|
13
13
|
options = {}
|
@@ -15,7 +15,7 @@ OptionParser.new do |opts|
|
|
15
15
|
opts.banner = "Usage: ldpath [options] URI"
|
16
16
|
|
17
17
|
opts.on("--program=STRING_URI_OR_FILE", "LDPath program to run (- for STDIN)") do |program|
|
18
|
-
if File.exists?
|
18
|
+
if File.exists?(program) || program =~ /^http/
|
19
19
|
options[:program] = open(program).read
|
20
20
|
elsif program.strip == "-"
|
21
21
|
options[:program] = $stdin.read
|
data/lib/ldpath.rb
CHANGED
@@ -10,9 +10,9 @@ module Ldpath
|
|
10
10
|
require 'ldpath/transform'
|
11
11
|
require 'ldpath/functions'
|
12
12
|
require 'ldpath/program'
|
13
|
-
|
13
|
+
|
14
14
|
class << self
|
15
|
-
def evaluate
|
15
|
+
def evaluate(program, uri, context)
|
16
16
|
Ldpath::Program.parse(program).evaluate(uri, context)
|
17
17
|
end
|
18
18
|
|
@@ -26,7 +26,7 @@ module Ldpath
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
def logger=
|
29
|
+
def logger=(logger)
|
30
30
|
@logger = logger
|
31
31
|
end
|
32
32
|
end
|
data/lib/ldpath/field_mapping.rb
CHANGED
@@ -1,2 +1 @@
|
|
1
|
-
|
2
|
-
end
|
1
|
+
Ldpath::FieldMapping = Struct.new(:name, :selector, :field_type)
|
data/lib/ldpath/functions.rb
CHANGED
@@ -1,180 +1,187 @@
|
|
1
|
+
# rubocop:disable Style/MethodName
|
1
2
|
module Ldpath
|
2
3
|
module Functions
|
3
|
-
def concat
|
4
|
+
def concat(uri, context, *args)
|
4
5
|
args.flatten.compact.join
|
5
6
|
end
|
6
|
-
|
7
|
-
def first
|
7
|
+
|
8
|
+
def first(uri, context, *args)
|
8
9
|
args.flatten.compact.first
|
9
10
|
end
|
10
|
-
|
11
|
-
def last
|
11
|
+
|
12
|
+
def last(uri, context, *args)
|
12
13
|
args.flatten.compact.last
|
13
14
|
end
|
14
15
|
|
15
|
-
def count
|
16
|
+
def count(uri, context, *args)
|
16
17
|
args.flatten.compact.length
|
17
18
|
end
|
18
|
-
|
19
|
-
def eq
|
19
|
+
|
20
|
+
def eq(uri, context, *args)
|
20
21
|
a, b, *rem = args.flatten
|
21
22
|
unless rem.empty?
|
22
23
|
raise "Too many arguments to fn:eq"
|
23
24
|
end
|
24
25
|
a == b
|
25
26
|
end
|
26
|
-
|
27
|
-
def ne
|
27
|
+
|
28
|
+
def ne(uri, context, *args)
|
28
29
|
a, b, *rem = args.flatten
|
29
30
|
unless rem.empty?
|
30
31
|
raise "Too many arguments to fn:ne"
|
31
32
|
end
|
32
33
|
a != b
|
33
34
|
end
|
34
|
-
|
35
|
-
def lt
|
35
|
+
|
36
|
+
def lt(uri, context, *args)
|
36
37
|
a, b, *rem = args.flatten
|
37
38
|
unless rem.empty?
|
38
39
|
raise "Too many arguments to fn:lt"
|
39
40
|
end
|
40
41
|
a < b
|
41
42
|
end
|
42
|
-
|
43
|
-
def le
|
43
|
+
|
44
|
+
def le(uri, context, *args)
|
44
45
|
a, b, *rem = args.flatten
|
45
46
|
unless rem.empty?
|
46
47
|
raise "Too many arguments to fn:le"
|
47
48
|
end
|
48
49
|
a <= b
|
49
50
|
end
|
50
|
-
|
51
|
-
def gt
|
51
|
+
|
52
|
+
def gt(uri, context, *args)
|
52
53
|
a, b, *rem = args.flatten
|
53
54
|
unless rem.empty?
|
54
55
|
raise "Too many arguments to fn:gt"
|
55
56
|
end
|
56
57
|
a > b
|
57
58
|
end
|
58
|
-
|
59
|
-
def ge
|
59
|
+
|
60
|
+
def ge(uri, context, *args)
|
60
61
|
a, b, *rem = args.flatten
|
61
62
|
unless rem.empty?
|
62
63
|
raise "Too many arguments to fn:ge"
|
63
64
|
end
|
64
65
|
a >= b
|
65
66
|
end
|
66
|
-
|
67
|
+
|
67
68
|
# collections
|
68
|
-
def flatten
|
69
|
-
|
69
|
+
def flatten(uri, context, lists)
|
70
|
+
Array(lists).flatten.map { |x| RDF::List.new(x, context).to_a }.flatten
|
70
71
|
end
|
71
|
-
|
72
|
-
def get
|
72
|
+
|
73
|
+
def get(uri, context, list, idx)
|
74
|
+
flatten(uri, context, list)[idx.to_i]
|
73
75
|
end
|
74
|
-
|
75
|
-
def subList
|
76
|
-
|
76
|
+
|
77
|
+
def subList(uri, context, list, idx_start, idx_end = nil)
|
78
|
+
arr = flatten(uri, context, list)
|
79
|
+
|
80
|
+
if idx_end
|
81
|
+
arr[(idx_start.to_i..(idx_end.to_i - idx_start.to_i))]
|
82
|
+
else
|
83
|
+
arr.drop(idx_start.to_i)
|
84
|
+
end
|
77
85
|
end
|
78
|
-
|
86
|
+
|
79
87
|
# dates
|
80
|
-
|
81
|
-
def earliest
|
88
|
+
|
89
|
+
def earliest(uri, context, *args)
|
82
90
|
args.flatten.min
|
83
91
|
end
|
84
|
-
|
85
|
-
def latest
|
92
|
+
|
93
|
+
def latest(uri, context, *args)
|
86
94
|
args.flatten.max
|
87
95
|
end
|
88
|
-
|
96
|
+
|
89
97
|
# math
|
90
|
-
|
91
|
-
def min
|
98
|
+
|
99
|
+
def min(uri, context, *args)
|
92
100
|
args.flatten.min
|
93
101
|
end
|
94
|
-
|
95
|
-
def max
|
102
|
+
|
103
|
+
def max(uri, context, *args)
|
96
104
|
args.flatten.max
|
97
105
|
end
|
98
|
-
|
99
|
-
def round
|
100
|
-
args.map do |n|
|
106
|
+
|
107
|
+
def round(uri, context, *args)
|
108
|
+
args.map do |n|
|
101
109
|
Array(n).map do |i|
|
102
110
|
i.respond_to? :round ? i.round : i
|
103
111
|
end
|
104
112
|
end
|
105
113
|
end
|
106
|
-
|
107
|
-
def sum
|
114
|
+
|
115
|
+
def sum(uri, context, *args)
|
108
116
|
args.inject(0) { |sum, n| sum + n }
|
109
117
|
end
|
110
|
-
|
118
|
+
|
111
119
|
# text
|
112
|
-
|
113
|
-
def replace
|
120
|
+
|
121
|
+
def replace(uri, context, str, pattern, replacement)
|
114
122
|
regex = Regexp.parse(pattern)
|
115
123
|
Array(str).map do |x|
|
116
124
|
x.gsub(regex, replacement)
|
117
125
|
end
|
118
126
|
end
|
119
|
-
|
120
|
-
def strlen
|
121
|
-
Array(str).map
|
127
|
+
|
128
|
+
def strlen(uri, context, str)
|
129
|
+
Array(str).map(&:length)
|
122
130
|
end
|
123
|
-
|
124
|
-
def wc
|
131
|
+
|
132
|
+
def wc(uri, context, str)
|
125
133
|
Array(str).map { |x| x.split.length }
|
126
134
|
end
|
127
|
-
|
128
|
-
def strLeft
|
135
|
+
|
136
|
+
def strLeft(uri, context, str, left)
|
129
137
|
Array(str).map { |x| x[0..left.to_i] }
|
130
138
|
end
|
131
|
-
|
132
|
-
def strRight
|
139
|
+
|
140
|
+
def strRight(uri, context, str, right)
|
133
141
|
Array(str).map { |x| x[right.to_i..x.length] }
|
134
142
|
end
|
135
|
-
|
136
|
-
def substr
|
143
|
+
|
144
|
+
def substr(uri, context, str, left, right)
|
137
145
|
Array(str).map { |x| x[left.to_i..right.to_i] }
|
138
146
|
end
|
139
|
-
|
140
|
-
def strJoin
|
147
|
+
|
148
|
+
def strJoin(uri, context, str, sep = "", prefix = "", suffix = "")
|
141
149
|
prefix + Array(str).join(sep) + suffix
|
142
150
|
end
|
143
|
-
|
144
|
-
def equals
|
151
|
+
|
152
|
+
def equals(uri, context, str, other)
|
145
153
|
Array(str).map { |x| x == other }
|
146
154
|
end
|
147
|
-
|
148
|
-
def equalsIgnoreCase
|
155
|
+
|
156
|
+
def equalsIgnoreCase(uri, context, str, other)
|
149
157
|
Array(str).map { |x| x.downcase == other.downcase }
|
150
158
|
end
|
151
|
-
|
152
|
-
def contains
|
159
|
+
|
160
|
+
def contains(uri, context, str, substr)
|
153
161
|
Array(str).map { |x| x.include? substr }
|
154
162
|
end
|
155
|
-
|
156
|
-
def startsWith
|
163
|
+
|
164
|
+
def startsWith(uri, context, str, suffix)
|
157
165
|
Array(str).map { |x| x.start_with? suffix }
|
158
166
|
end
|
159
|
-
|
160
|
-
def endsWith
|
167
|
+
|
168
|
+
def endsWith(uri, context, str, suffix)
|
161
169
|
Array(str).map { |x| x.end_with? suffix }
|
162
170
|
end
|
163
|
-
|
164
|
-
def isEmpty
|
171
|
+
|
172
|
+
def isEmpty(uri, context, str)
|
165
173
|
Array(str).map(&:empty?)
|
166
174
|
end
|
167
175
|
|
168
|
-
def predicates
|
176
|
+
def predicates(uri, context, *args)
|
169
177
|
context.query([uri, nil, nil]).map(&:predicate).uniq
|
170
178
|
end
|
171
179
|
|
172
|
-
def xpath
|
180
|
+
def xpath(uri, context, xpath, node)
|
173
181
|
x = Array(xpath).flatten.first
|
174
182
|
Array(node).flatten.compact.map do |n|
|
175
|
-
Nokogiri::XML(n).xpath(x, prefixes.map { |k,v| [k, v.to_s] }).map(&:text)
|
183
|
+
Nokogiri::XML(n).xpath(x, prefixes.map { |k, v| [k, v.to_s] }).map(&:text)
|
176
184
|
end
|
177
185
|
end
|
178
|
-
|
179
186
|
end
|
180
187
|
end
|
data/lib/ldpath/parser.rb
CHANGED
@@ -2,36 +2,64 @@ require 'parslet'
|
|
2
2
|
|
3
3
|
module Ldpath
|
4
4
|
class Parser < Parslet::Parser
|
5
|
-
root :
|
6
|
-
rule(:
|
7
|
-
rule(:line) { ((wsp >> expression) | expression) >> space_not_newline? >> (newline | eof) }
|
5
|
+
root :doc
|
6
|
+
rule(:doc) { prologue? >> statements? >> eof }
|
8
7
|
|
9
|
-
rule(:
|
10
|
-
rule(:
|
8
|
+
rule(:prologue) { wsp? >> directive?.repeat(1, 1) >> (eol >> wsp? >> directive >> wsp?).repeat >> wsp? >> eol? }
|
9
|
+
rule(:prologue?) { prologue.maybe }
|
10
|
+
rule(:directive) { prefixID | graph | filter | boost }
|
11
|
+
rule(:directive?) { directive.maybe }
|
11
12
|
|
12
|
-
rule(:
|
13
|
-
rule(:
|
14
|
-
rule(:
|
15
|
-
rule(:
|
13
|
+
rule(:statements) { wsp? >> statement?.repeat(1, 1) >> (eol >> wsp? >> statement >> wsp?).repeat >> wsp? >> eol? }
|
14
|
+
rule(:statements?) { statements.maybe }
|
15
|
+
rule(:statement) { mapping }
|
16
|
+
rule(:statement?) { mapping.maybe }
|
16
17
|
|
17
|
-
|
18
|
+
# whitespace rules
|
19
|
+
rule(:eol) { (str("\n") >> str("\r").maybe).repeat(1) }
|
20
|
+
rule(:eol?) { eol.maybe }
|
21
|
+
rule(:eof) { any.absent? }
|
22
|
+
rule(:space) { str("\n").absent? >> match('\s').repeat(1) }
|
23
|
+
rule(:space?) { space.maybe }
|
24
|
+
rule(:wsp) { (space | multiline_comment | single_line_comment).repeat(1) }
|
18
25
|
rule(:wsp?) { wsp.maybe }
|
19
|
-
rule(:multiline_comment) { (str(
|
26
|
+
rule(:multiline_comment) { (str("/*") >> (str("*/").absent? >> any).repeat >> str("*/")) }
|
27
|
+
rule(:single_line_comment) { str("#") >> (eol.absent? >> any).repeat }
|
20
28
|
|
21
|
-
|
22
|
-
|
23
|
-
rule(:
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
rule(:
|
33
|
-
rule(:
|
34
|
-
|
29
|
+
# simple types
|
30
|
+
rule(:integer) { match("[+-]").maybe >> match("\\d+") }
|
31
|
+
rule(:decimal) { match("[+-]").maybe >> match("\\d*") >> str(".") >> match("\\d+") }
|
32
|
+
rule(:double) do
|
33
|
+
match("[+-]").maybe >> (
|
34
|
+
(match("\\d+") >> str('.') >> match("\\d*") >> exponent) |
|
35
|
+
(str('.') >> match("\\d+") >> exponent) |
|
36
|
+
(match("\\d+") >> exponent)
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
rule(:exponent) { match('[Ee]') >> match("[+-]").maybe >> match("\\d+") }
|
41
|
+
rule(:numeric_literal) { integer | decimal | double }
|
42
|
+
rule(:boolean_literal) { str('true') | str('false') }
|
43
|
+
|
44
|
+
rule(:string) { string_literal_quote | string_literal_single_quote | string_literal_long_single_quote | string_literal_long_quote }
|
45
|
+
|
46
|
+
rule(:string_literal_quote) do
|
47
|
+
str('"') >> (match("[^\\\"\\\\\\r\\n]") | echar | uchar).repeat.as(:literal) >> str('"')
|
48
|
+
end
|
49
|
+
|
50
|
+
rule(:string_literal_single_quote) do
|
51
|
+
str("'") >> (match("[^'\\\\\\r\\n]") | echar | uchar).repeat.as(:literal) >> str("'")
|
52
|
+
end
|
53
|
+
|
54
|
+
rule(:string_literal_long_quote) do
|
55
|
+
str('"""') >> (str('"""').absent? >> match("[^\\\\]") | echar | uchar).repeat.as(:literal) >> str('"""')
|
56
|
+
end
|
57
|
+
|
58
|
+
rule(:string_literal_long_single_quote) do
|
59
|
+
str("'''") >> (str("'''").absent? >> match("[^\\\\]") | echar | uchar).repeat.as(:literal) >> str("'''")
|
60
|
+
end
|
61
|
+
|
62
|
+
# operators
|
35
63
|
rule(:self_op) { str(".") }
|
36
64
|
rule(:and_op) { str("&") }
|
37
65
|
rule(:or_op) { str("|") }
|
@@ -40,337 +68,374 @@ module Ldpath
|
|
40
68
|
rule(:star) { str("*") }
|
41
69
|
rule(:not_op) { str("!") }
|
42
70
|
rule(:inverse) { str("^") }
|
43
|
-
rule(:
|
71
|
+
rule(:question) { str("?") }
|
44
72
|
rule(:is) { str "is" }
|
45
73
|
rule(:is_a) { str "is-a" }
|
46
|
-
rule(:func) { str "fn:"}
|
74
|
+
rule(:func) { str "fn:" }
|
47
75
|
rule(:type) { str "^^" }
|
48
76
|
rule(:lang) { str "@" }
|
49
77
|
rule(:loose) { str("~") }
|
50
|
-
|
51
|
-
#
|
52
|
-
rule(:
|
53
|
-
|
54
|
-
|
78
|
+
|
79
|
+
# strings
|
80
|
+
rule(:comma) { str(",") }
|
81
|
+
rule(:scolon) { str(";") }
|
82
|
+
rule(:colon) { str(":") }
|
83
|
+
rule(:dcolon) { str("::") }
|
84
|
+
rule(:assign) { str("=") }
|
85
|
+
rule(:k_prefix) { str("@prefix") }
|
86
|
+
rule(:k_graph) { str("@graph") }
|
87
|
+
rule(:k_filter) { str("@filter") }
|
88
|
+
rule(:k_boost) { str("@boost") }
|
89
|
+
|
90
|
+
# iris
|
91
|
+
rule(:iri) do
|
92
|
+
iriref |
|
93
|
+
prefixed_name
|
94
|
+
end
|
95
|
+
|
96
|
+
rule(:iriref) do
|
97
|
+
str("<") >> (match("[^[[:cntrl:]]<>\"{}|^`\\\\]") | uchar).repeat.as(:iri) >> str('>')
|
98
|
+
end
|
99
|
+
|
100
|
+
rule(:uchar) do
|
101
|
+
str('\u') >> hex.repeat(4, 4) | hex.repeat(6, 6)
|
102
|
+
end
|
103
|
+
|
104
|
+
rule(:echar) do
|
105
|
+
str('\\') >> match("[tbnrf\"'\\\\]")
|
106
|
+
end
|
107
|
+
|
108
|
+
rule(:hex) do
|
109
|
+
match("[[:xdigit:]]")
|
110
|
+
end
|
111
|
+
|
112
|
+
rule(:prefixed_name) do
|
113
|
+
(identifier.as(:prefix) >> str(":") >> identifier.as(:localName)).as(:iri)
|
55
114
|
end
|
56
|
-
|
57
|
-
rule(:
|
58
|
-
|
115
|
+
|
116
|
+
rule(:identifier) { pn_chars_base >> (str(".").maybe >> pn_chars).repeat }
|
117
|
+
|
118
|
+
rule(:pn_chars_base) do
|
119
|
+
# also \u10000-\uEFFFF
|
120
|
+
match("[A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]")
|
59
121
|
end
|
60
|
-
|
61
|
-
rule(:
|
62
|
-
|
122
|
+
|
123
|
+
rule(:pn_chars) do
|
124
|
+
pn_chars_base | match("[0-9\u00B7\u0300-\u036F\u203F-\u2040_-]")
|
63
125
|
end
|
64
|
-
|
65
|
-
rule(:identifier) { match["a-zA-Z0-9_"] >> (match["a-zA-Z0-9_'\\.-"]).repeat }
|
66
126
|
|
67
|
-
|
68
|
-
|
69
|
-
|
127
|
+
# "xyz"; 0.123e52; true
|
128
|
+
rule(:literal) do
|
129
|
+
rdf_literal | numeric_literal | boolean_literal
|
130
|
+
end
|
70
131
|
|
71
|
-
|
72
|
-
|
73
|
-
|
132
|
+
# "xyz"; "xyz"^^a; "xyz"@en
|
133
|
+
rule(:rdf_literal) do
|
134
|
+
string >> (literal_language_test | literal_type_test).maybe
|
135
|
+
end
|
136
|
+
|
137
|
+
rule(:node) do
|
138
|
+
iri.as(:iri) | literal.as(:literal)
|
139
|
+
end
|
74
140
|
|
75
|
-
# @prefix id =
|
76
|
-
rule(:
|
141
|
+
# @prefix id = iri ;
|
142
|
+
rule(:prefixID) do
|
77
143
|
(
|
78
144
|
k_prefix >> wsp? >>
|
79
|
-
identifier.as(:id) >> wsp? >>
|
145
|
+
(identifier | str("")).as(:id) >> wsp? >>
|
80
146
|
colon >> wsp? >>
|
81
|
-
|
82
|
-
).as(:
|
83
|
-
|
84
|
-
|
85
|
-
# @graph
|
86
|
-
rule(:graph)
|
87
|
-
k_graph >> wsp? >>
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
(
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
147
|
+
iriref >> space? >> scolon.maybe
|
148
|
+
).as(:prefixID)
|
149
|
+
end
|
150
|
+
|
151
|
+
# @graph iri, iri, iri ;
|
152
|
+
rule(:graph) do
|
153
|
+
k_graph >> wsp? >>
|
154
|
+
iri_list.as(:graphs) >> wsp? >> scolon
|
155
|
+
end
|
156
|
+
|
157
|
+
# <info:a>, <info:b>
|
158
|
+
rule(:iri_list) do
|
159
|
+
iri.as(:iri) >>
|
160
|
+
(
|
161
|
+
wsp? >>
|
162
|
+
comma >> wsp? >>
|
163
|
+
iri_list.as(:rest)
|
164
|
+
).repeat
|
165
|
+
end
|
99
166
|
|
100
167
|
# @filter test ;
|
101
|
-
rule(:filter)
|
168
|
+
rule(:filter) do
|
102
169
|
(k_filter >> wsp? >> node_test.as(:test) >> wsp? >> scolon).as(:filter)
|
103
|
-
|
170
|
+
end
|
104
171
|
|
105
172
|
# @boost selector ;
|
106
|
-
rule(:boost)
|
173
|
+
rule(:boost) do
|
107
174
|
(k_boost >> wsp? >> selector.as(:selector) >> wsp? >> scolon).as(:boost)
|
108
|
-
|
109
|
-
|
175
|
+
end
|
176
|
+
|
110
177
|
# id = . ;
|
111
|
-
rule(:mapping)
|
178
|
+
rule(:mapping) do
|
112
179
|
(
|
113
|
-
|
180
|
+
label.as(:name) >> wsp? >>
|
114
181
|
assign >> wsp? >>
|
115
182
|
selector.as(:selector) >>
|
116
|
-
(
|
183
|
+
(wsp? >>
|
117
184
|
dcolon >> wsp? >> field_type
|
118
185
|
).maybe >> wsp? >> scolon
|
119
186
|
).as(:mapping)
|
120
|
-
|
187
|
+
end
|
121
188
|
|
122
|
-
rule(:
|
123
|
-
|
124
|
-
|
189
|
+
rule(:label) do
|
190
|
+
iri | identifier
|
191
|
+
end
|
125
192
|
|
126
|
-
|
193
|
+
# xsd:string
|
194
|
+
rule(:field_type) do
|
195
|
+
iri.as(:field_type) >> field_type_options.maybe
|
196
|
+
end
|
197
|
+
|
198
|
+
# ( x = "xyz", y = "abc" )
|
199
|
+
rule(:field_type_options) do
|
127
200
|
str("(") >> wsp? >> (field_type_option >> (wsp? >> comma >> wsp? >> field_type_option).repeat).as(:options) >> wsp? >> str(")")
|
128
|
-
|
201
|
+
end
|
202
|
+
|
203
|
+
# x = "xyz"
|
204
|
+
rule(:field_type_option) do
|
205
|
+
identifier.as(:key) >> wsp? >> assign >> wsp? >> literal.as(:value)
|
206
|
+
end
|
129
207
|
|
130
|
-
rule(:field_type_option) {
|
131
|
-
identifier.as(:key) >> wsp? >> assign >> wsp? >> strlit.as(:value)
|
132
|
-
}
|
133
|
-
|
134
208
|
# selector groups
|
135
|
-
rule(:selector)
|
209
|
+
rule(:selector) do
|
136
210
|
(
|
137
|
-
|
211
|
+
compound_or_path_selector |
|
138
212
|
testing_selector |
|
139
213
|
atomic_selector
|
140
214
|
)
|
141
|
-
|
215
|
+
end
|
142
216
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
217
|
+
# &; |
|
218
|
+
rule(:compound_operator) { and_op | or_op }
|
219
|
+
|
220
|
+
# a & b; a | b; a / b
|
221
|
+
rule(:compound_or_path_selector) do
|
222
|
+
path_selector | compound_selector
|
223
|
+
end
|
224
|
+
|
225
|
+
# a & b; a | b
|
226
|
+
rule(:compound_selector) do
|
227
|
+
atomic_or_testing_or_path_selector.as(:left) >> wsp? >>
|
228
|
+
compound_operator.as(:op) >> wsp? >>
|
229
|
+
selector.as(:right)
|
230
|
+
end
|
231
|
+
|
232
|
+
# a / b
|
233
|
+
rule(:path_selector) do
|
234
|
+
atomic_or_testing_selector.as(:left) >> wsp? >>
|
235
|
+
p_sep.as(:op) >> wsp? >>
|
236
|
+
atomic_or_testing_or_path_selector.as(:right)
|
237
|
+
end
|
238
|
+
|
239
|
+
# info:a[is-a z]
|
240
|
+
rule(:testing_selector) do
|
152
241
|
atomic_selector.as(:delegate) >>
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
242
|
+
str("[") >> wsp? >>
|
243
|
+
node_test.as(:test) >> wsp? >>
|
244
|
+
str("]")
|
245
|
+
end
|
157
246
|
|
158
|
-
rule(:atomic_selector)
|
247
|
+
rule(:atomic_selector) do
|
159
248
|
(
|
160
249
|
self_selector |
|
161
250
|
function_selector |
|
162
251
|
property_selector |
|
163
252
|
loose_property_selector |
|
164
|
-
wildcard_selector |
|
253
|
+
wildcard_selector |
|
165
254
|
reverse_property_selector |
|
166
255
|
string_constant_selector |
|
167
256
|
recursive_path_selector |
|
168
257
|
grouped_selector |
|
169
258
|
tap_selector
|
170
259
|
)
|
171
|
-
|
172
|
-
|
260
|
+
end
|
173
261
|
|
174
|
-
rule(:atomic_or_testing_selector)
|
262
|
+
rule(:atomic_or_testing_selector) do
|
175
263
|
(testing_selector | atomic_selector)
|
176
|
-
|
264
|
+
end
|
177
265
|
|
178
|
-
rule(:atomic_or_testing_or_path_selector)
|
266
|
+
rule(:atomic_or_testing_or_path_selector) do
|
179
267
|
(path_selector | atomic_or_testing_selector)
|
180
|
-
|
181
|
-
|
182
|
-
# Compound selectors
|
183
|
-
## x / y
|
184
|
-
rule(:path_selector) {
|
185
|
-
(
|
186
|
-
atomic_or_testing_selector.as(:left) >> wsp? >>
|
187
|
-
p_sep >> wsp? >>
|
188
|
-
atomic_or_testing_or_path_selector.as(:right)
|
189
|
-
).as(:path)
|
190
|
-
}
|
191
|
-
|
192
|
-
## x & y
|
193
|
-
rule(:intersection_selector) {
|
194
|
-
(
|
195
|
-
atomic_or_testing_or_path_selector.as(:left) >> wsp? >>
|
196
|
-
and_op >> wsp? >>
|
197
|
-
selector.as(:right)
|
198
|
-
).as(:intersection)
|
199
|
-
}
|
200
|
-
|
201
|
-
## x | y
|
202
|
-
rule(:union_selector) {
|
203
|
-
(
|
204
|
-
atomic_or_testing_or_path_selector.as(:left) >> wsp? >>
|
205
|
-
or_op >> wsp? >>
|
206
|
-
selector.as(:right)
|
207
|
-
).as(:union)
|
208
|
-
}
|
268
|
+
end
|
209
269
|
|
210
270
|
# Atomic Selectors
|
211
|
-
rule(:self_selector)
|
271
|
+
rule(:self_selector) do
|
212
272
|
self_op.as(:self)
|
213
|
-
|
214
|
-
|
273
|
+
end
|
274
|
+
|
215
275
|
# fn:x() or fn:x(1,2,3)
|
216
|
-
rule(:function_selector)
|
217
|
-
|
276
|
+
rule(:function_selector) do
|
277
|
+
function_without_args | function_with_arglist
|
278
|
+
end
|
279
|
+
|
280
|
+
rule(:function_without_args) do
|
281
|
+
func >> identifier.as(:fname) >> str("()")
|
282
|
+
end
|
283
|
+
|
284
|
+
rule(:function_with_arglist) do
|
218
285
|
func >> identifier.as(:fname) >> str("(") >> wsp? >> arglist.as(:arglist) >> wsp? >> str(")")
|
219
|
-
|
220
|
-
|
221
|
-
rule(:arglist)
|
222
|
-
selector >>
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
286
|
+
end
|
287
|
+
|
288
|
+
rule(:arglist) do
|
289
|
+
selector >>
|
290
|
+
(
|
291
|
+
wsp? >>
|
292
|
+
comma >> wsp? >>
|
293
|
+
selector
|
294
|
+
).repeat
|
295
|
+
end
|
296
|
+
|
230
297
|
# xyz
|
231
|
-
rule(:loose_property_selector)
|
232
|
-
loose >>
|
233
|
-
|
234
|
-
|
235
|
-
|
298
|
+
rule(:loose_property_selector) do
|
299
|
+
loose.as(:loose) >>
|
300
|
+
wsp? >>
|
301
|
+
iri.as(:property)
|
302
|
+
end
|
236
303
|
|
237
304
|
# xyz
|
238
|
-
rule(:property_selector)
|
239
|
-
|
240
|
-
|
305
|
+
rule(:property_selector) do
|
306
|
+
iri.as(:property)
|
307
|
+
end
|
241
308
|
|
242
309
|
# *
|
243
|
-
rule(:wildcard_selector)
|
310
|
+
rule(:wildcard_selector) do
|
244
311
|
star.as(:wildcard)
|
245
|
-
|
312
|
+
end
|
246
313
|
|
247
314
|
# ^xyz
|
248
|
-
rule(:reverse_property_selector)
|
249
|
-
inverse >>
|
250
|
-
|
251
|
-
|
252
|
-
rule(:string_constant_selector)
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
# (x)
|
257
|
-
rule(:recursive_path_selector)
|
258
|
-
(
|
259
|
-
|
260
|
-
selector.as(:delegate) >> wsp? >>
|
315
|
+
rule(:reverse_property_selector) do
|
316
|
+
inverse.as(:reverse) >> iri.as(:property)
|
317
|
+
end
|
318
|
+
|
319
|
+
rule(:string_constant_selector) do
|
320
|
+
string
|
321
|
+
end
|
322
|
+
|
323
|
+
# (x)?; (x)*; (x)+; (x){3,5}
|
324
|
+
rule(:recursive_path_selector) do
|
325
|
+
str("(") >> wsp? >>
|
326
|
+
selector.as(:delegate) >> wsp? >>
|
261
327
|
str(")") >>
|
262
|
-
(
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
rule(:
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
328
|
+
range.as(:repeat)
|
329
|
+
end
|
330
|
+
|
331
|
+
# ?; *; +; {3,5}; {,5}; {3,}
|
332
|
+
rule(:range) do
|
333
|
+
(
|
334
|
+
star |
|
335
|
+
plus |
|
336
|
+
question |
|
337
|
+
str("{") >> wsp? >> integer.as(:min).maybe >> wsp? >> str(",") >> wsp? >> integer.as(:max).maybe >> wsp? >> str("}")
|
338
|
+
).as(:range)
|
339
|
+
end
|
340
|
+
|
341
|
+
# (<info:a>)
|
342
|
+
rule(:grouped_selector) do
|
343
|
+
str("(") >> wsp? >>
|
344
|
+
selector >> wsp? >>
|
345
|
+
str(")")
|
346
|
+
end
|
347
|
+
|
348
|
+
# ?<a>(<info:a>)
|
349
|
+
rule(:tap_selector) do
|
350
|
+
question >>
|
351
|
+
str("<") >> wsp? >>
|
352
|
+
identifier.as(:identifier) >> wsp? >>
|
353
|
+
str(">") >> wsp? >>
|
354
|
+
(atomic_selector).as(:tap)
|
355
|
+
end
|
356
|
+
|
284
357
|
# Testing Selectors
|
285
|
-
|
286
|
-
rule(:node_test)
|
358
|
+
|
359
|
+
rule(:node_test) do
|
287
360
|
grouped_test |
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
361
|
+
not_test |
|
362
|
+
and_test |
|
363
|
+
or_test |
|
364
|
+
atomic_node_test
|
365
|
+
end
|
293
366
|
|
294
|
-
rule(:atomic_node_test)
|
367
|
+
rule(:atomic_node_test) do
|
295
368
|
literal_language_test |
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
rule(:grouped_test)
|
304
|
-
str("(")
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
rule(:not_test)
|
369
|
+
literal_type_test |
|
370
|
+
is_a_test |
|
371
|
+
path_equality_test |
|
372
|
+
function_test |
|
373
|
+
path_test
|
374
|
+
end
|
375
|
+
|
376
|
+
rule(:grouped_test) do
|
377
|
+
str("(") >> wsp? >>
|
378
|
+
node_test >> wsp? >>
|
379
|
+
str(")")
|
380
|
+
end
|
381
|
+
|
382
|
+
rule(:not_test) do
|
310
383
|
(
|
311
384
|
not_op >> node_test.as(:delegate)
|
312
385
|
).as(:not)
|
313
|
-
|
314
|
-
|
315
|
-
rule(:and_test)
|
386
|
+
end
|
387
|
+
|
388
|
+
rule(:and_test) do
|
316
389
|
(
|
317
|
-
atomic_node_test.as(:left) >> wsp? >>
|
318
|
-
and_op >> wsp? >>
|
390
|
+
atomic_node_test.as(:left) >> wsp? >>
|
391
|
+
and_op >> wsp? >>
|
319
392
|
node_test.as(:right)
|
320
393
|
).as(:and)
|
321
|
-
|
322
|
-
|
323
|
-
rule(:or_test)
|
394
|
+
end
|
395
|
+
|
396
|
+
rule(:or_test) do
|
324
397
|
(
|
325
|
-
atomic_node_test.as(:left) >> wsp? >>
|
326
|
-
or_op >> wsp? >>
|
398
|
+
atomic_node_test.as(:left) >> wsp? >>
|
399
|
+
or_op >> wsp? >>
|
327
400
|
node_test.as(:right)
|
328
401
|
).as(:or)
|
329
|
-
|
402
|
+
end
|
330
403
|
|
331
404
|
# @en
|
332
|
-
rule(:literal_language_test)
|
405
|
+
rule(:literal_language_test) do
|
333
406
|
lang >> identifier.as(:lang)
|
334
|
-
|
335
|
-
|
407
|
+
end
|
408
|
+
|
336
409
|
# ^^xyz
|
337
|
-
rule(:literal_type_test)
|
338
|
-
type >>
|
339
|
-
|
340
|
-
|
341
|
-
rule(:is_a_test)
|
410
|
+
rule(:literal_type_test) do
|
411
|
+
type >> iri.as(:type)
|
412
|
+
end
|
413
|
+
|
414
|
+
rule(:is_a_test) do
|
342
415
|
(
|
343
|
-
is_a >> wsp? >>
|
416
|
+
is_a >> wsp? >>
|
344
417
|
node.as(:right)
|
345
418
|
).as(:is_a)
|
346
|
-
|
347
|
-
|
348
|
-
rule(:path_equality_test)
|
419
|
+
end
|
420
|
+
|
421
|
+
rule(:path_equality_test) do
|
349
422
|
(
|
350
423
|
selector >> wsp? >>
|
351
424
|
is >> wsp? >>
|
352
425
|
node.as(:right)
|
353
426
|
).as(:is)
|
354
|
-
|
355
|
-
|
356
|
-
rule(:function_test) {
|
357
|
-
(
|
358
|
-
func >> identifier.as(:fname) >> str("()") |
|
359
|
-
func >> identifier.as(:fname) >> str("(") >>
|
360
|
-
wsp? >>
|
361
|
-
arglist.as(:arglist) >>
|
362
|
-
wsp? >>
|
363
|
-
str(")")
|
364
|
-
)
|
365
|
-
}
|
427
|
+
end
|
366
428
|
|
367
|
-
rule(:
|
429
|
+
rule(:function_test) do
|
430
|
+
function_without_args | function_with_arglist
|
431
|
+
end
|
432
|
+
|
433
|
+
rule(:path_test) do
|
368
434
|
(
|
369
435
|
path_selector |
|
370
436
|
testing_selector |
|
371
437
|
atomic_selector
|
372
438
|
)
|
373
|
-
|
374
|
-
|
439
|
+
end
|
375
440
|
end
|
376
441
|
end
|