jcrvalidator 0.5.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 +7 -0
- data/bin/jcr +26 -0
- data/lib/jcr/check_groups.rb +195 -0
- data/lib/jcr/evaluate_array_rules.rb +270 -0
- data/lib/jcr/evaluate_group_rules.rb +46 -0
- data/lib/jcr/evaluate_member_rules.rb +61 -0
- data/lib/jcr/evaluate_object_rules.rb +115 -0
- data/lib/jcr/evaluate_rules.rb +211 -0
- data/lib/jcr/evaluate_value_rules.rb +279 -0
- data/lib/jcr/find_roots.rb +106 -0
- data/lib/jcr/jcr.rb +228 -0
- data/lib/jcr/map_rule_names.rb +82 -0
- data/lib/jcr/parser.rb +398 -0
- data/lib/jcr/process_directives.rb +83 -0
- data/lib/jcr.rb +1 -0
- metadata +60 -0
data/lib/jcr/parser.rb
ADDED
@@ -0,0 +1,398 @@
|
|
1
|
+
# Copyright (C) 2014,2015 American Registry for Internet Numbers (ARIN)
|
2
|
+
#
|
3
|
+
# Permission to use, copy, modify, and/or distribute this software for any
|
4
|
+
# purpose with or without fee is hereby granted, provided that the above
|
5
|
+
# copyright notice and this permission notice appear in all copies.
|
6
|
+
#
|
7
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
13
|
+
# IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
14
|
+
require 'pp'
|
15
|
+
require 'parslet'
|
16
|
+
|
17
|
+
|
18
|
+
module JCR
|
19
|
+
|
20
|
+
class Parser < Parslet::Parser
|
21
|
+
|
22
|
+
root(:jcr)
|
23
|
+
|
24
|
+
rule(:jcr) { ( spcCmnt | directive ).repeat >> root_rule.maybe >> ( spcCmnt | directive | rule ).repeat }
|
25
|
+
#! jcr = *( sp-cmt / directive ) [ root_rule ]
|
26
|
+
#! *( sp-cmt / directive / rule )
|
27
|
+
#!
|
28
|
+
|
29
|
+
rule(:spcCmnt) { spaces | comment }
|
30
|
+
#/ spcCmnt -> sp-cmt
|
31
|
+
#! spcCmnt = spaces / comment
|
32
|
+
rule(:spcCmnt?) { spcCmnt.repeat }
|
33
|
+
#/ spcCmnt? -> *sp-cmt
|
34
|
+
rule(:spaces) { match('\s').repeat(1) }
|
35
|
+
#! spaces = 1*( WSP / CR / LF )
|
36
|
+
rule(:spaces?) { spaces.maybe }
|
37
|
+
#/ spaces? -> [ spaces ]
|
38
|
+
rule(:comment) { str(';') >> ( str('\;') | match('[^\r\n;]') ).repeat >> match('[\r\n;]') }
|
39
|
+
#! comment = ";" *( "\;" / comment-char ) comment-end-char
|
40
|
+
#! comment-char = HTAB / %x20-3A / %x3C-10FFFF
|
41
|
+
#! ; Any char other than ";" / CR / LF
|
42
|
+
#! comment-end-char = CR / LF / ";"
|
43
|
+
#!
|
44
|
+
|
45
|
+
rule(:directive) { ( str('#') >> spaces? >> directive_def >> match('[\r\n]') ).as(:directive) }
|
46
|
+
#! directive = "#" spaces? directive_def eol
|
47
|
+
rule(:directive_def) { jcr_version_d | ruleset_id_d | import_d | tbd_directive_d }
|
48
|
+
#! directive_def = jcr_version_d / ruleset_id_d / import_d /
|
49
|
+
#! tbd_directive_d
|
50
|
+
rule(:jcr_version_d) { (str('jcr-version') >> spaces >> integer.as(:major_version) >> str('.') >> integer.as(:minor_version)).as(:jcr_version_d) }
|
51
|
+
#! jcr_version_d = jcr-version-kw spaces major_version "." minor_version
|
52
|
+
#> jcr-version-kw = "jcr-version"
|
53
|
+
#! major_version = integer
|
54
|
+
#! minor_version = integer
|
55
|
+
rule(:ruleset_id_d) { (str('ruleset-id') >> spaces >> ruleset_id.as(:ruleset_id)).as(:ruleset_id_d) }
|
56
|
+
#! ruleset_id_d = ruleset-id-kw spaces ruleset_id
|
57
|
+
#> ruleset-id-kw = "ruleset-id"
|
58
|
+
rule(:import_d) { (str('import') >> spaces >> ruleset_id.as(:ruleset_id) >> ( spaces >> str('as') >> spaces >> ruleset_id_alias ).maybe).as(:import_d) }
|
59
|
+
#! import_d = import-kw spaces ruleset_id
|
60
|
+
#! [ spaces as_kw spaces ruleset_id_alias ]
|
61
|
+
#> import-kw = "import"
|
62
|
+
#> as-kw = "as"
|
63
|
+
rule(:ruleset_id) { match('[a-zA-Z]') >> match('[\S]').repeat }
|
64
|
+
#! ruleset_id = ALPHA *not-space
|
65
|
+
#! not-space = %x21-10FFFF
|
66
|
+
rule(:ruleset_id_alias) { name.as(:ruleset_id_alias) }
|
67
|
+
#! ruleset_id_alias = name
|
68
|
+
rule(:tbd_directive_d) { name.as(:directive_name) >> ( spaces >> match('[^\r\n]').repeat.as(:directive_parameters) ).maybe }
|
69
|
+
#! tbd_directive_d = directive_name [ spaces directive_parameters ]
|
70
|
+
#! directive_name = name
|
71
|
+
#! directive_parameters = not_eol
|
72
|
+
#! not_eol = HTAB / %x20-10FFFF
|
73
|
+
#! eol = CR / LF
|
74
|
+
#!
|
75
|
+
|
76
|
+
rule(:root_rule) { value_rule | member_rule | group_rule } # N.B. Not target_rule_name
|
77
|
+
#! root_rule = value_rule / member_rule / group_rule
|
78
|
+
#!
|
79
|
+
|
80
|
+
rule(:rule) { ( rule_name >> spcCmnt? >> rule_def ).as(:rule) }
|
81
|
+
#! rule = rule_name spcCmnt? rule_def
|
82
|
+
#!
|
83
|
+
|
84
|
+
rule(:rule_name) { name.as(:rule_name) }
|
85
|
+
#! rule_name = name
|
86
|
+
rule(:target_rule_name) { ((ruleset_id_alias >> str('.')).maybe >> rule_name).as(:target_rule_name) }
|
87
|
+
#! target_rule_name = [ ruleset_id_alias "." ] rule_name
|
88
|
+
rule(:name) { match('[a-zA-Z]') >> match('[a-zA-Z0-9\-_]').repeat }
|
89
|
+
#! name = ALPHA *( ALPHA / DIGIT / "-" / "_" )
|
90
|
+
#!
|
91
|
+
|
92
|
+
rule(:rule_def) { type_rule | member_rule | group_rule }
|
93
|
+
#! rule_def = type_rule / member_rule / group_rule
|
94
|
+
rule(:type_rule) { value_rule | type_choice_rule | target_rule_name }
|
95
|
+
#! type_rule = value_rule / type_choice_rule / target_rule_name
|
96
|
+
rule(:value_rule) { primitive_rule | array_rule | object_rule }
|
97
|
+
#! value_rule = primitive_rule / array_rule / object_rule
|
98
|
+
rule(:member_rule) { ( annotations >> member_name_spec >> spcCmnt? >> type_rule ).as(:member_rule) }
|
99
|
+
#! member_rule = annotations
|
100
|
+
#! member_name_spec spcCmnt? type_rule
|
101
|
+
rule(:member_name_spec) { regex.as(:member_regex) | q_string.as(:member_name) }
|
102
|
+
#! member_name_spec = regex / q_string
|
103
|
+
rule(:type_choice_rule) { str(':').as(:type_choice_signifier) >> spcCmnt? >> type_choice }
|
104
|
+
#! type_choice_rule = ":" spcCmnt? type_choice
|
105
|
+
rule(:type_choice) { ( annotations >> str('(') >> type_choice_items >> ( choice_combiner >> type_choice_items ).repeat >> str(')') ).as(:group_rule) }
|
106
|
+
#! type_choice = annotations "(" type_choice_items
|
107
|
+
#! *( choice_combiner type_choice_items ) ")"
|
108
|
+
rule(:type_choice_items) { spcCmnt? >> (type_choice | type_rule) >> spcCmnt? }
|
109
|
+
#! type_choice_items = spcCmnt? ( type_choice / type_rule ) spcCmnt?
|
110
|
+
#!
|
111
|
+
|
112
|
+
rule(:annotations) { ( str('@(') >> spcCmnt? >> annotation_set >> spcCmnt? >> str(')') >> spcCmnt? ).repeat }
|
113
|
+
#! annotations = *( "@(" spcCmnt? annotation_set spcCmnt? ")" spcCmnt? )
|
114
|
+
rule(:annotation_set) { reject_annotation | unordered_annotation | root_annotation | tbd_annotation }
|
115
|
+
#! annotation_set = reject_annotation / unordered_annotation /
|
116
|
+
#! root_annotation / tbd_annotation
|
117
|
+
rule(:reject_annotation) { str('reject').as(:reject_annotation) }
|
118
|
+
#! reject_annotation = reject-kw
|
119
|
+
#> reject-kw = "reject"
|
120
|
+
rule(:unordered_annotation) { str('unordered').as(:unordered_annotation) }
|
121
|
+
#! unordered_annotation = unordered-kw
|
122
|
+
#> unordered-kw = "unordered"
|
123
|
+
rule(:root_annotation) { str('root').as(:root_annotation) }
|
124
|
+
#! root_annotation = root-kw
|
125
|
+
#> root-kw = "root"
|
126
|
+
rule(:tbd_annotation) { name.as(:annotation_name) >> ( spaces >> match('[^)]').as(:annotation_parameters) ).maybe }
|
127
|
+
#! tbd_annotation = annotation_name [ spaces annotation_parameters ]
|
128
|
+
#! annotation_name = name
|
129
|
+
#! annotation_parameters = *( spaces / %x21-28 / %x2A-10FFFF )
|
130
|
+
#! ; Not close bracket - ")"
|
131
|
+
#!
|
132
|
+
|
133
|
+
rule(:primitive_rule) { ( annotations >> str(':') >> spcCmnt? >> primimitive_def ).as(:primitive_rule) }
|
134
|
+
#! primitive_rule = annotations ":" spcCmnt? primimitive_def
|
135
|
+
|
136
|
+
rule(:primimitive_def) {
|
137
|
+
null_type | boolean_type | true_value | false_value |
|
138
|
+
string_type | string_range | string_value |
|
139
|
+
float_type | float_range | float_value |
|
140
|
+
integer_type | integer_range | integer_value |
|
141
|
+
ip4_type | ip6_type | fqdn_type | idn_type |
|
142
|
+
uri_range | uri_type | phone_type | email_type |
|
143
|
+
full_date_type | full_time_type | date_time_type |
|
144
|
+
base64_type | any
|
145
|
+
}
|
146
|
+
#! primimitive_def = null_type / boolean_type / true_value / false_value /
|
147
|
+
#! string_type / string_range / string_value /
|
148
|
+
#! float_type / float_range / float_value /
|
149
|
+
#! integer_type / integer_range / integer_value /
|
150
|
+
#! ip4_type / ip6_type / fqdn_type / idn_type /
|
151
|
+
#! uri_range / uri_type / phone_type / email_type /
|
152
|
+
#! full_date_type / full_time_type / date_time_type /
|
153
|
+
#! base64_type / any
|
154
|
+
rule(:null_type) { str('null').as(:null) }
|
155
|
+
#! null_type = null-kw
|
156
|
+
#> null-kw = "null"
|
157
|
+
rule(:boolean_type) { str('boolean').as(:boolean_v) }
|
158
|
+
#! boolean_type = boolean-kw
|
159
|
+
#> boolean-kw = "boolean"
|
160
|
+
rule(:true_value) { str('true').as(:true_v) }
|
161
|
+
#! true_value = true-kw
|
162
|
+
#> true-kw = "true"
|
163
|
+
rule(:false_value) { str('false').as(:false_v) }
|
164
|
+
#! false_value = false-kw
|
165
|
+
#> false-kw = "false"
|
166
|
+
rule(:string_type) { str('string').as(:string) }
|
167
|
+
#! string_type = string-kw
|
168
|
+
#> string-kw = "string"
|
169
|
+
rule(:string_value) { q_string }
|
170
|
+
#! string_value = q_string
|
171
|
+
rule(:string_range) { regex }
|
172
|
+
#! string_range = regex
|
173
|
+
rule(:float_type) { str('float').as(:float_v) }
|
174
|
+
#! float_type = float-kw
|
175
|
+
#> float-kw = "float"
|
176
|
+
rule(:float_range) {
|
177
|
+
float.as(:float_min) >> str('..') >> float.maybe.as(:float_max) | str('..') >> float.as(:float_max)
|
178
|
+
}
|
179
|
+
#! float_range = float_min ".." [ float_max ] / ".." float_max
|
180
|
+
#! float_min = float
|
181
|
+
#! float_max = float
|
182
|
+
rule(:float_value) { float.as(:float) }
|
183
|
+
#! float_value = float
|
184
|
+
rule(:integer_type) { str('integer').as(:integer_v) }
|
185
|
+
#! integer_type = integer-kw
|
186
|
+
#> integer-kw = "integer"
|
187
|
+
rule(:integer_range) {
|
188
|
+
integer.as(:integer_min) >> str('..') >> integer.maybe.as(:integer_max) | ( str('..') >> integer.as(:integer_max) )
|
189
|
+
}
|
190
|
+
#! integer_range = integer_min ".." [ integer_max ] / ".." integer_max
|
191
|
+
#! integer_min = integer
|
192
|
+
#! integer_max = integer
|
193
|
+
rule(:integer_value) { integer.as(:integer) }
|
194
|
+
#! integer_value = integer
|
195
|
+
rule(:ip4_type) { str('ip4').as(:ip4) }
|
196
|
+
#! ip4_type = ip4-kw
|
197
|
+
#> ip4-kw = "ip4"
|
198
|
+
rule(:ip6_type) { str('ip6').as(:ip6) }
|
199
|
+
#! ip6_type = ip6-kw
|
200
|
+
#> ip6-kw = "ip6"
|
201
|
+
rule(:fqdn_type) { str('fqdn').as(:fqdn) }
|
202
|
+
#! fqdn_type = fqdn-kw
|
203
|
+
#> fqdn-kw = "fqdn"
|
204
|
+
rule(:idn_type) { str('idn').as(:idn) }
|
205
|
+
#! idn_type = idn-kw
|
206
|
+
#> idn-kw = "idn"
|
207
|
+
rule(:uri_range) { str('uri..') >> uri_template }
|
208
|
+
#! uri_range = uri-dotdot-kw uri_template
|
209
|
+
#> uri-dotdot-kw = "uri.."
|
210
|
+
rule(:uri_type) { str('uri').as(:uri) }
|
211
|
+
#! uri_type = uri-kw
|
212
|
+
#> uri-kw = "uri"
|
213
|
+
rule(:phone_type) { str('phone').as(:phone) }
|
214
|
+
#! phone_type = phone-kw
|
215
|
+
#> phone-kw = "phone"
|
216
|
+
rule(:email_type) { str('email').as(:email) }
|
217
|
+
#! email_type = email-kw
|
218
|
+
#> email-kw = "email"
|
219
|
+
rule(:full_date_type) { str('full-date').as(:full_date) }
|
220
|
+
#! full-date_type = full-date-kw
|
221
|
+
#> full-date-kw = "full-date"
|
222
|
+
rule(:full_time_type) { str('full-time').as(:full_time) }
|
223
|
+
#! full-time_type = full-time-kw
|
224
|
+
#> full-time-kw = "full-time"
|
225
|
+
rule(:date_time_type) { str('date-time').as(:date_time) }
|
226
|
+
#! date-time_type = date-time-kw
|
227
|
+
#> date-time-kw = "date-time"
|
228
|
+
rule(:base64_type) { str('base64').as(:base64) }
|
229
|
+
#! base64_type = base64-kw
|
230
|
+
#> base64-kw = "base64"
|
231
|
+
rule(:any) { str('any').as(:any) }
|
232
|
+
#! any = any-kw
|
233
|
+
#> any-kw = "any"
|
234
|
+
#!
|
235
|
+
|
236
|
+
rule(:object_rule) { ( annotations >> (str(':') >> spcCmnt?).maybe >>
|
237
|
+
str('{') >> spcCmnt? >> object_items.maybe >> spcCmnt? >> str('}') ).as(:object_rule) }
|
238
|
+
#! object_rule = annotations [ ":" spcCmnt? ] "{" spcCmnt? [ object_items spcCmnt? ] "}"
|
239
|
+
rule(:object_items) { object_item >> (( spcCmnt? >> sequence_combiner >> spcCmnt? >> object_item ).repeat(1) |
|
240
|
+
( spcCmnt? >> choice_combiner >> spcCmnt? >> object_item ).repeat(1) ).maybe }
|
241
|
+
#! object_items = object_item (*( sequence_combiner object_item ) /
|
242
|
+
#! *( choice_combiner object_item ) )
|
243
|
+
rule(:object_item ) { repetition.maybe >> spcCmnt? >> object_item_types }
|
244
|
+
#! object_item = [ repetition spcCmnt? ] object_item_types
|
245
|
+
rule(:object_item_types) { member_rule | target_rule_name | object_group }
|
246
|
+
#! object_item_types = member_rule / target_rule_name / object_group
|
247
|
+
rule(:object_group) { ( str('(') >> spcCmnt? >> object_items.maybe >> spcCmnt? >> str(')') ).as(:group_rule) }
|
248
|
+
#! object_group = "(" spcCmnt? [ object_items spcCmnt? ] ")"
|
249
|
+
#!
|
250
|
+
|
251
|
+
rule(:array_rule) { ( annotations >> (str(':') >> spcCmnt?).maybe >>
|
252
|
+
str('[') >> spcCmnt? >> array_items.maybe >> spcCmnt? >> str(']') ).as(:array_rule) }
|
253
|
+
#! array_rule = annotations [ ":" spcCmnt? ] "[" spcCmnt? [ array_items spcCmnt? ] "]"
|
254
|
+
rule(:array_items) { array_item >> (( spcCmnt? >> sequence_combiner >> spcCmnt? >> array_item ).repeat(1) |
|
255
|
+
( spcCmnt? >> choice_combiner >> spcCmnt? >> array_item ).repeat(1) ).maybe }
|
256
|
+
#! array_items = array_item (*( sequence_combiner array_item ) /
|
257
|
+
#! *( choice_combiner array_item ) )
|
258
|
+
rule(:array_item) { repetition.maybe >> spcCmnt? >> array_item_types }
|
259
|
+
#! array_item = [ repetition ] spcCmnt? array_item_types
|
260
|
+
rule(:array_item_types) { type_rule | array_group }
|
261
|
+
#! array_item_types = type_rule / array_group
|
262
|
+
rule(:array_group) { ( str('(') >> spcCmnt? >> array_items.maybe >> spcCmnt? >> str(')') ).as(:group_rule) }
|
263
|
+
#! array_group = "(" spcCmnt? [ array_items spcCmnt? ] ")"
|
264
|
+
#!
|
265
|
+
|
266
|
+
rule(:group_rule) { ( annotations >> str('(') >> spcCmnt? >> group_items.maybe >> spcCmnt? >> str(')') ).as(:group_rule) }
|
267
|
+
#! group_rule = annotations "(" spcCmnt? [ group_items spcCmnt? ] ")"
|
268
|
+
rule(:group_items) { group_item >> (( spcCmnt? >> sequence_combiner >> spcCmnt? >> group_item ).repeat(1) |
|
269
|
+
( spcCmnt? >> choice_combiner >> spcCmnt? >> group_item ).repeat(1) ).maybe }
|
270
|
+
#! group_items = group_item (*( sequence_combiner group_item ) /
|
271
|
+
#! *( choice_combiner group_item ) )
|
272
|
+
rule(:group_item) { repetition.maybe >> spcCmnt? >> group_item_types }
|
273
|
+
#! group_item = [ repetition ] spcCmnt? group_item_types
|
274
|
+
rule(:group_item_types) { type_rule | member_rule | group_group }
|
275
|
+
#! group_item_types = type_rule / member_rule / group_group
|
276
|
+
rule(:group_group) { group_rule }
|
277
|
+
#! group_group = group_rule
|
278
|
+
#!
|
279
|
+
|
280
|
+
rule(:sequence_combiner) { str(',').as(:sequence_combiner) }
|
281
|
+
#! sequence_combiner = spcCmnt? "," spcCmnt?
|
282
|
+
rule(:choice_combiner) { str('|').as(:choice_combiner) }
|
283
|
+
#! choice_combiner = spcCmnt? "|" spcCmnt?
|
284
|
+
#!
|
285
|
+
|
286
|
+
rule(:repetition) { optional | one_or_more | min_max_repetition | specific_repetition }
|
287
|
+
#! repetition = optional / one_or_more / min_max_repetition /
|
288
|
+
#! min_repetition / max_repetition /
|
289
|
+
#! zero_or_more / specific_repetition
|
290
|
+
rule(:optional) { str('?').as(:optional) }
|
291
|
+
#! optional = "?"
|
292
|
+
rule(:one_or_more) { str('+').as(:one_or_more) }
|
293
|
+
#! one_or_more = "+"
|
294
|
+
#! zero_or_more = "*"
|
295
|
+
rule(:min_max_repetition) { # This includes zero_or_more, min_only and max_only cases
|
296
|
+
p_integer.maybe.as(:repetition_min) >> spcCmnt? >> str('*').as(:repetition_interval) >> spcCmnt? >> p_integer.maybe.as(:repetition_max) }
|
297
|
+
#! min_max_repetition = min_repeat spcCmnt? "*" spcCmnt? max_repeat
|
298
|
+
#! min_repetition = min_repeat spcCmnt? "*"
|
299
|
+
#! max_repetition = "*" spcCmnt? max_repeat
|
300
|
+
#! min_repeat = p_integer
|
301
|
+
#! max_repeat = p_integer
|
302
|
+
rule(:specific_repetition) { p_integer.as(:specific_repetition) }
|
303
|
+
#! specific_repetition = p_integer
|
304
|
+
#!
|
305
|
+
|
306
|
+
rule(:integer) { str('-').maybe >> match('[0-9]').repeat(1) }
|
307
|
+
#! integer = ["-"] 1*DIGIT
|
308
|
+
rule(:p_integer) { match('[0-9]').repeat(1) }
|
309
|
+
#! p_integer = 1*DIGIT
|
310
|
+
#!
|
311
|
+
|
312
|
+
rule(:float) { str('-').maybe >> match('[0-9]').repeat(1) >> str('.' ) >> match('[0-9]').repeat(1) }
|
313
|
+
#! float = [ minus ] int frac [ exp ]
|
314
|
+
#! ; From RFC 7159 except 'frac' required
|
315
|
+
#! minus = %x2D ; -
|
316
|
+
#! plus = %x2B ; +
|
317
|
+
#! int = zero / ( digit1-9 *DIGIT )
|
318
|
+
#! digit1-9 = %x31-39 ; 1-9
|
319
|
+
#! frac = decimal-point 1*DIGIT
|
320
|
+
#! decimal-point = %x2E ; .
|
321
|
+
#! exp = e [ minus / plus ] 1*DIGIT
|
322
|
+
#! e = %x65 / %x45 ; e E
|
323
|
+
#! zero = %x30 ; 0
|
324
|
+
#!
|
325
|
+
|
326
|
+
rule(:q_string) {
|
327
|
+
str('"') >>
|
328
|
+
( str('\\') >> match('[^\r\n]') | str('"').absent? >> match('[^\r\n]') ).repeat.as(:q_string) >>
|
329
|
+
str('"')
|
330
|
+
}
|
331
|
+
#! q_string = quotation-mark *char quotation-mark
|
332
|
+
#! ; From RFC 7159
|
333
|
+
#! char = unescaped /
|
334
|
+
#! escape (
|
335
|
+
#! %x22 / ; " quotation mark U+0022
|
336
|
+
#! %x5C / ; \ reverse solidus U+005C
|
337
|
+
#! %x2F / ; / solidus U+002F
|
338
|
+
#! %x62 / ; b backspace U+0008
|
339
|
+
#! %x66 / ; f form feed U+000C
|
340
|
+
#! %x6E / ; n line feed U+000A
|
341
|
+
#! %x72 / ; r carriage return U+000D
|
342
|
+
#! %x74 / ; t tab U+0009
|
343
|
+
#! %x75 4HEXDIG ) ; uXXXX U+XXXX
|
344
|
+
#! escape = %x5C ; \
|
345
|
+
#! quotation-mark = %x22 ; "
|
346
|
+
#! unescaped = %x20-21 / %x23-5B / %x5D-10FFFF
|
347
|
+
#!
|
348
|
+
|
349
|
+
rule(:regex) { str('/') >> (str('\\/') | match('[^/]+')).repeat.as(:regex) >> str('/') >> regex_modifiers.maybe }
|
350
|
+
#! regex = "/" *( escape "/" / not-slash ) "/" [ regex_modifiers ]
|
351
|
+
#! not-slash = HTAB / CR / LF / %x20-2E / %x30-10FFFF
|
352
|
+
#! ; Any char except "/"
|
353
|
+
rule(:regex_modifiers) { match('[isx]').repeat.as(:regex_modifiers) }
|
354
|
+
#! regex_modifiers = *( "i" / "s" / "x" )
|
355
|
+
#!
|
356
|
+
|
357
|
+
rule(:uri_template) { ( match('[a-zA-Z{}]').repeat(1) >> str(':') >> match('[\S]').repeat(1) ).as(:uri_template) }
|
358
|
+
#! uri_template = 1*ALPHA ":" not-space
|
359
|
+
|
360
|
+
end
|
361
|
+
|
362
|
+
class Transformer < Parslet::Transform
|
363
|
+
|
364
|
+
rule(:rule_def=>simple(:primimitive_def)) { puts "found rule definition" }
|
365
|
+
rule(:primimitive_def => simple(:x)) { puts "value sought is " + x }
|
366
|
+
|
367
|
+
end
|
368
|
+
|
369
|
+
def self.parse(str)
|
370
|
+
|
371
|
+
parser = Parser.new
|
372
|
+
parser.parse(str)
|
373
|
+
|
374
|
+
end
|
375
|
+
|
376
|
+
def self.parse_and_transform(str)
|
377
|
+
# provided for the fun of it
|
378
|
+
|
379
|
+
parser = Parser.new
|
380
|
+
tree = parser.parse(str)
|
381
|
+
pp tree
|
382
|
+
|
383
|
+
transformer = Transformer.new
|
384
|
+
transformer.apply( tree )
|
385
|
+
|
386
|
+
end
|
387
|
+
|
388
|
+
def self.print_tree( tree )
|
389
|
+
|
390
|
+
tree.each do |node|
|
391
|
+
puts "named rule: " + node[:rule][:rule_name] if node[:rule]
|
392
|
+
end
|
393
|
+
|
394
|
+
end
|
395
|
+
|
396
|
+
end
|
397
|
+
|
398
|
+
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# Copyright (c) 2015 American Registry for Internet Numbers
|
2
|
+
#
|
3
|
+
# Permission to use, copy, modify, and/or distribute this software for any
|
4
|
+
# purpose with or without fee is hereby granted, provided that the above
|
5
|
+
# copyright notice and this permission notice appear in all copies.
|
6
|
+
#
|
7
|
+
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
8
|
+
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
9
|
+
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
10
|
+
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
11
|
+
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
12
|
+
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
13
|
+
# IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
14
|
+
|
15
|
+
require 'net/http'
|
16
|
+
require 'uri'
|
17
|
+
|
18
|
+
require 'jcr/parser'
|
19
|
+
require 'jcr/evaluate_rules'
|
20
|
+
require 'jcr/map_rule_names'
|
21
|
+
require 'jcr/jcr'
|
22
|
+
|
23
|
+
module JCR
|
24
|
+
|
25
|
+
def self.process_directives( ctx )
|
26
|
+
|
27
|
+
tree = ctx.tree
|
28
|
+
if tree.is_a? Hash
|
29
|
+
tree = [ tree ]
|
30
|
+
end
|
31
|
+
|
32
|
+
tree.each do |node|
|
33
|
+
if node[:directive]
|
34
|
+
d = node[:directive]
|
35
|
+
case
|
36
|
+
when d[:ruleset_id_d]
|
37
|
+
process_ruleset_id( d[:ruleset_id_d], ctx )
|
38
|
+
when d[:import_d]
|
39
|
+
process_import( d[:import_d], ctx )
|
40
|
+
when d[:jcr_version_d]
|
41
|
+
process_jcrversion( d[:jcr_version_d], ctx )
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.process_ruleset_id( directive, ctx )
|
48
|
+
ctx.id = directive[:ruleset_id].to_str
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.process_jcrversion( directive, ctx )
|
52
|
+
major = directive[:major_version].to_str.to_i
|
53
|
+
minor = directive[:minor_version].to_str.to_i
|
54
|
+
if major != 0
|
55
|
+
raise "jcr version #{major}.#{minor} is incompatible with 0.5"
|
56
|
+
end
|
57
|
+
if minor != 5
|
58
|
+
raise "jcr version #{major}.#{minor} is incompatible with 0.5"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.process_import( directive, ctx )
|
63
|
+
|
64
|
+
ruleset_id = directive[:ruleset_id].to_str
|
65
|
+
ruleset_alias = directive[:ruleset_id_alias].to_str
|
66
|
+
u = ctx.map_ruleset_alias( ruleset_alias, ruleset_id )
|
67
|
+
uri = URI.parse( u )
|
68
|
+
ruleset = nil
|
69
|
+
case uri.scheme
|
70
|
+
when "http","https"
|
71
|
+
response = Net::HTTP.get_response uri
|
72
|
+
ruleset = response.body
|
73
|
+
else
|
74
|
+
ruleset = File.open( uri.path )
|
75
|
+
end
|
76
|
+
|
77
|
+
import_ctx = JCR.ingest_ruleset( ruleset, false, ruleset_alias )
|
78
|
+
ctx.mapping.merge!( import_ctx.mapping )
|
79
|
+
ctx.roots.concat( import_ctx.roots )
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
data/lib/jcr.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'jcr/jcr'
|
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: jcrvalidator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Newton
|
8
|
+
- Pete Cordell
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2015-12-31 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: A JSON Content Rules (JCR) Validator library and command line utility.
|
15
|
+
email: andy@arin.net
|
16
|
+
executables:
|
17
|
+
- jcr
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- bin/jcr
|
22
|
+
- lib/jcr.rb
|
23
|
+
- lib/jcr/check_groups.rb
|
24
|
+
- lib/jcr/evaluate_array_rules.rb
|
25
|
+
- lib/jcr/evaluate_group_rules.rb
|
26
|
+
- lib/jcr/evaluate_member_rules.rb
|
27
|
+
- lib/jcr/evaluate_object_rules.rb
|
28
|
+
- lib/jcr/evaluate_rules.rb
|
29
|
+
- lib/jcr/evaluate_value_rules.rb
|
30
|
+
- lib/jcr/find_roots.rb
|
31
|
+
- lib/jcr/jcr.rb
|
32
|
+
- lib/jcr/map_rule_names.rb
|
33
|
+
- lib/jcr/parser.rb
|
34
|
+
- lib/jcr/process_directives.rb
|
35
|
+
homepage: https://github.com/arineng/jcrvalidator
|
36
|
+
licenses:
|
37
|
+
- ISC
|
38
|
+
metadata: {}
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubyforge_project:
|
55
|
+
rubygems_version: 2.4.5
|
56
|
+
signing_key:
|
57
|
+
specification_version: 4
|
58
|
+
summary: JCR Validator
|
59
|
+
test_files: []
|
60
|
+
has_rdoc:
|