jcrvalidator 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|