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