kwalify 0.4.1 → 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.
@@ -1,6 +1,6 @@
1
1
  ###
2
- ### $Rev: 22 $
3
- ### $Release: 0.4.1 $
2
+ ### $Rev: 42 $
3
+ ### $Release: 0.5.0 $
4
4
  ### copyright(c) 2005 kuwata-lab all rights reserved.
5
5
  ###
6
6
 
@@ -14,26 +14,32 @@ module Kwalify
14
14
 
15
15
 
16
16
  ##----- begin
17
- # filename: lib/kwalify/main-program.rb
18
- @@messages[:action_required] = "command-line option '-f' or '-m' required."
19
- @@messages[:meta_schema_empty] = "%s: empty.\n"
20
- @@messages[:meta_validation_valid] = "%s: ok.\n"
21
- @@messages[:meta_validation_invalid] = "%s: NG!\n"
17
+ # filename: lib/kwalify/main.rb
18
+ @@messages[:command_option_noaction] = "command-line option '-f' or '-m' required."
19
+ @@messages[:meta_empty] = "%s: empty.\n"
20
+ @@messages[:meta_valid] = "%s: ok.\n"
21
+ @@messages[:meta_invalid] = "%s: NG!\n"
22
22
  @@messages[:schema_empty] = "%s#%d: empty.\n"
23
23
  @@messages[:validation_valid] = "%s#%d: valid.\n"
24
24
  @@messages[:validation_invalid] = "%s#%d: INVALID\n"
25
+ @@messages[:command_property_invalid] = "%s: invalid property."
26
+ @@messages[:command_option_noarg] = "-%s: argument required."
27
+ @@messages[:command_option_noschema] = "-%s: schema filename required."
28
+ @@messages[:command_option_invalid] = "-%s: invalid command option."
25
29
  # --
26
30
  # filename: lib/kwalify/rule.rb
27
31
  @@messages[:schema_notmap] = "schema definition is not a mapping."
32
+ @@messages[:key_unknown] = "unknown key."
28
33
  @@messages[:type_notstr] = "not a string."
29
34
  @@messages[:type_unknown] = "unknown type."
30
35
  @@messages[:required_notbool] = "not a boolean."
36
+ @@messages[:pattern_notstr] = "not a string (or regexp)"
31
37
  @@messages[:pattern_notmatch] = "should be '/..../'."
32
38
  @@messages[:pattern_syntaxerr] = "has regexp error."
33
39
  @@messages[:enum_notseq] = "not a sequence."
34
40
  @@messages[:enum_notscalar] = "not available with seq or map."
35
- @@messages[:enum_duplicate] = "duplicated enum value."
36
41
  @@messages[:enum_type_unmatch] = "%s type expected."
42
+ @@messages[:enum_duplicate] = "duplicated enum value."
37
43
  @@messages[:assert_notstr] = "not a string."
38
44
  @@messages[:assert_noval] = "'val' is not used."
39
45
  @@messages[:assert_syntaxerr] = "expression syntax error."
@@ -43,12 +49,20 @@ module Kwalify
43
49
  @@messages[:range_undefined] = "undefined key."
44
50
  @@messages[:range_twomax] = "both 'max' and 'max-ex' are not available at once."
45
51
  @@messages[:range_twomin] = "both 'min' and 'min-ex' are not available at once."
52
+ @@messages[:range_maxltmin] = "max '%s' is less than min '%s'."
53
+ @@messages[:range_maxleminex] = "max '%s' is less than or equal to min-ex '%s'."
54
+ @@messages[:range_maxexlemin] = "max-ex '%s' is less than or equal to min '%s'."
55
+ @@messages[:range_maxexleminex] = "max-ex '%s' is less than or equal to min-ex '%s'."
46
56
  @@messages[:length_notmap] = "not a mapping."
47
57
  @@messages[:length_nottext] = "is available only with string or text."
48
58
  @@messages[:length_notint] = "not an integer."
49
59
  @@messages[:length_undefined] = "undefined key."
50
60
  @@messages[:length_twomax] = "both 'max' and 'max-ex' are not available at once."
51
61
  @@messages[:length_twomin] = "both 'min' and 'min-ex' are not available at once."
62
+ @@messages[:length_maxltmin] = "max '%s' is less than min '%s'."
63
+ @@messages[:length_maxleminex] = "max '%s' is less than or equal to min-ex '%s'."
64
+ @@messages[:length_maxexlemin] = "max-ex '%s' is less than or equal to min '%s'."
65
+ @@messages[:length_maxexleminex] = "max-ex '%s' is less than or equal to min-ex '%s'."
52
66
  @@messages[:ident_notbool] = "not a boolean."
53
67
  @@messages[:ident_notscalar] = "is available only with a scalar type."
54
68
  @@messages[:ident_onroot] = "is not available on root element."
@@ -61,7 +75,6 @@ module Kwalify
61
75
  @@messages[:sequence_toomany] = "required just one element."
62
76
  @@messages[:mapping_notmap] = "not a mapping."
63
77
  @@messages[:mapping_noelem] = "required at least one element."
64
- @@messages[:key_unknown] = "unknown key."
65
78
  @@messages[:seq_nosequence] = "type 'seq' requires 'sequence:'."
66
79
  @@messages[:seq_conflict] = "not available with sequence."
67
80
  @@messages[:map_nomapping] = "type 'map' requires 'mapping:'."
@@ -87,6 +100,22 @@ module Kwalify
87
100
  @@messages[:required_nokey] = "key '%s:' is required."
88
101
  @@messages[:key_undefined] = "key '%s' is undefined."
89
102
  # --
103
+ # filename: lib/kwalify/yaml-parser.rb
104
+ @@messages[:flow_hastail] = "flow style sequence is closed but got '%s'."
105
+ @@messages[:flow_eof] = "found EOF when parsing flow style."
106
+ @@messages[:flow_noseqitem] = "sequence item required (or last comma is extra)."
107
+ @@messages[:flow_seqnotclosed] = "flow style sequence requires ']'."
108
+ @@messages[:flow_mapnoitem] = "mapping item required (or last comma is extra)."
109
+ @@messages[:flow_mapnotclosed] = "flow style mapping requires '}'."
110
+ @@messages[:flow_nocolon] = "':' expected but got '%s'."
111
+ @@messages[:anchor_duplicated] = "anchor '%s' is already used."
112
+ @@messages[:alias_extradata] = "alias cannot take any data."
113
+ @@messages[:anchor_notfound] = "anchor '%s' not found"
114
+ @@messages[:sequence_noitem] = "sequence item is expected."
115
+ @@messages[:sequence_badindent] = "illegal indent of sequence."
116
+ @@messages[:mapping_noitem] = "mapping item is expected."
117
+ @@messages[:mapping_badindent] = "illegal indent of mapping."
118
+ # --
90
119
  ##----- end
91
120
 
92
121
 
@@ -1,6 +1,6 @@
1
1
  ###
2
- ### $Rev: 35 $
3
- ### $Release: 0.4.1 $
2
+ ### $Rev: 42 $
3
+ ### $Release: 0.5.0 $
4
4
  ### copyright(c) 2005 kuwata-lab all rights reserved.
5
5
  ###
6
6
 
@@ -11,7 +11,21 @@ require 'yaml'
11
11
 
12
12
  module Kwalify
13
13
 
14
- META_SCHEMA = <<'END'
14
+
15
+ ##
16
+ ## ex.
17
+ ## meta_validator = Kwalify::MetaValidator.instance()
18
+ ## schema = File.load_file('schema.yaml')
19
+ ## errors = meta_validator.validate(schema)
20
+ ## if !errors.empty?
21
+ ## errors.each do |error|
22
+ ## puts "[#{error.path}] #{error.message}"
23
+ ## end
24
+ ## end
25
+ ##
26
+ class MetaValidator < Validator
27
+
28
+ META_SCHEMA = <<'END'
15
29
  name: MAIN
16
30
  type: map
17
31
  required: yes
@@ -53,6 +67,7 @@ mapping: &main-rule
53
67
  type: seq
54
68
  sequence:
55
69
  - type: scalar
70
+ unique: yes
56
71
  "pattern":
57
72
  type: str
58
73
  "assert":
@@ -69,8 +84,6 @@ mapping: &main-rule
69
84
  type: scalar
70
85
  "min-ex":
71
86
  type: scalar
72
- #complement":
73
- # type: boolean
74
87
  "length":
75
88
  type: map
76
89
  mapping:
@@ -106,18 +119,6 @@ mapping: &main-rule
106
119
  END
107
120
 
108
121
 
109
- ##
110
- ## ex.
111
- ## meta_validator = Kwalify.meta_validator()
112
- ## schema = File.load_file('schema.yaml')
113
- ## errors = meta_validator.validate(schema)
114
- ## if !errors.empty?
115
- ## errors.each do |error|
116
- ## puts "[#{error.path}] #{error.message}"
117
- ## end
118
- ## end
119
- ##
120
- class MetaValidator < Validator
121
122
  def initialize(schema, &block)
122
123
  super
123
124
  end
@@ -128,14 +129,11 @@ END
128
129
  #
129
130
  hash = value
130
131
  type = hash['type']
131
- type = Kwalify::DEFAULT_TYPE if type == nil
132
- unless type.is_a?(String)
133
- errors << validate_error(:type_notstr, rule, "#{path}/type", type.to_s)
134
- end
135
- klass = Kwalify.get_type_class(type)
136
- unless klass
137
- errors << validate_error(:type_unknown, rule, "#{path}/type", type.to_s)
138
- end
132
+ type = Types::DEFAULT_TYPE if type == nil
133
+ klass = Types.type_class(type)
134
+ #unless klass
135
+ # errors << validate_error(:type_unknown, rule, "#{path}/type", type)
136
+ #end
139
137
  #
140
138
  if hash.key?('pattern')
141
139
  val = hash['pattern']
@@ -148,15 +146,15 @@ END
148
146
  end
149
147
  #
150
148
  if hash.key?('enum')
151
- if type == 'seq' || type == 'map' # unless Kwalify.scalar_class?(klass)
149
+ if Types.collection_type?(type)
152
150
  errors << validate_error(:enum_notscalar, rule, path, 'enum:')
153
151
  else
154
- elem_table = {}
152
+ #elem_table = {}
155
153
  hash['enum'].each do |elem|
156
- if elem_table[elem]
157
- errors << validate_error(:enum_duplicate, rule, "#{path}/enum", elem.to_s)
158
- end
159
- elem_table[elem] = true
154
+ #if elem_table[elem]
155
+ # errors << validate_error(:enum_duplicate, rule, "#{path}/enum", elem.to_s)
156
+ #end
157
+ #elem_table[elem] = true
160
158
  unless elem.is_a?(klass)
161
159
  errors << validate_error(:enum_type_unmatch, rule, "#{path}/enum", elem, [Kwalify.word(type)])
162
160
  end
@@ -166,7 +164,7 @@ END
166
164
  #
167
165
  if hash.key?('assert')
168
166
  val = hash['assert']
169
- val =~ /\bval\b/ or errors << validate_error(:assert_noval, rule, "#{path}/assert", val)
167
+ #val =~ /\bval\b/ or errors << validate_error(:assert_noval, rule, "#{path}/assert", val)
170
168
  begin
171
169
  eval "proc { |val| #{val} }"
172
170
  rescue SyntaxError => ex
@@ -177,9 +175,10 @@ END
177
175
  if hash.key?('range')
178
176
  val = hash['range']
179
177
  curr_path = path + "/range"
180
- if ! val.is_a?(Hash)
181
- errors << validate_error(:range_notmap, rule, curr_path, val)
182
- elsif type == 'seq' || type == 'map' || type == 'bool' || type == 'any'
178
+ #if ! val.is_a?(Hash)
179
+ # errors << validate_error(:range_notmap, rule, curr_path, val)
180
+ #elsif ...
181
+ if Types.collection_type?(type) || type == 'bool' || type == 'any'
183
182
  errors << validate_error(:range_notscalar, rule, path, 'range:')
184
183
  else
185
184
  val.each do |rkey, rval|
@@ -200,35 +199,63 @@ END
200
199
  if val.key?('min') && val.key?('min-ex')
201
200
  errors << validate_error(:range_twomin, rule, curr_path, nil)
202
201
  end
202
+ max, min, max_ex, min_ex = val['max'], val['min'], val['max-ex'], val['min-ex']
203
+ if max
204
+ if min && max < min
205
+ errors << validate_error(:range_maxltmin, rule, curr_path, nil, [max, min])
206
+ elsif min_ex && max <= min_ex
207
+ errors << validate_error(:range_maxleminex, rule, curr_path, nil, [max, min_ex])
208
+ end
209
+ elsif max_ex
210
+ if min && max_ex <= min
211
+ errors << validate_error(:range_maxexlemin, rule, curr_path, nil, [max_ex, min])
212
+ elsif min_ex && max_ex <= min_ex
213
+ errors << validate_error(:range_maxexleminex, rule, curr_path, nil, [max_ex, min_ex])
214
+ end
215
+ end
203
216
  end
204
217
  #
205
218
  if hash.key?('length')
206
219
  val = hash['length']
207
220
  curr_path = path + "/length"
208
- val.is_a?(Hash) or errors << validate_error(:length_notmap, rule, curr_path, val)
221
+ #val.is_a?(Hash) or errors << validate_error(:length_notmap, rule, curr_path, val)
209
222
  unless type == 'str' || type == 'text'
210
223
  errors << validate_error(:length_nottext, rule, path, 'length:')
211
224
  end
212
- val.each do |lkey, lval|
213
- #case lkey
214
- #when 'max', 'min', 'max-ex', 'min-ex'
215
- unless lval.is_a?(Integer)
216
- errors << validate_error(:length_notint, rule, "#{curr_path}/#{lkey}", lval)
217
- end
218
- #else
219
- # errors << validate_error(:length_undefined, rule, curr_path, "#{lkey}:")
220
- #end
221
- end
225
+ #val.each do |lkey, lval|
226
+ # #case lkey
227
+ # #when 'max', 'min', 'max-ex', 'min-ex'
228
+ # unless lval.is_a?(Integer)
229
+ # errors << validate_error(:length_notint, rule, "#{curr_path}/#{lkey}", lval)
230
+ # end
231
+ # #else
232
+ # # errors << validate_error(:length_undefined, rule, curr_path, "#{lkey}:")
233
+ # #end
234
+ #end
222
235
  if val.key?('max') && val.key?('max-ex')
223
236
  errors << validate_error(:length_twomax, rule, curr_path, nil)
224
237
  end
225
238
  if val.key?('min') && val.key?('min-ex')
226
239
  errors << validate_error(:length_twomin, rule, curr_path, nil)
227
240
  end
241
+ max, min, max_ex, min_ex = val['max'], val['min'], val['max-ex'], val['min-ex']
242
+ if max
243
+ if min && max < min
244
+ errors << validate_error(:length_maxltmin, rule, curr_path, nil, [max, min])
245
+ elsif min_ex && max <= min_ex
246
+ errors << validate_error(:length_maxleminex, rule, curr_path, nil, [max, min_ex])
247
+ end
248
+ elsif max_ex
249
+ if min && max_ex <= min
250
+ errors << validate_error(:length_maxexlemin, rule, curr_path, nil, [max_ex, min])
251
+ elsif min_ex && max_ex <= min_ex
252
+ errors << validate_error(:length_maxexleminex, rule, curr_path, nil, [max_ex, min_ex])
253
+ end
254
+ end
228
255
  end
229
256
  #
230
257
  if hash.key?('unique')
231
- if hash['unique'] && (type == 'map' || type == 'seq')
258
+ if hash['unique'] && Types.collection_type?(type)
232
259
  errors << validate_error(:unique_notscalar, rule, path, "unique:")
233
260
  end
234
261
  if path.empty?
@@ -237,7 +264,7 @@ END
237
264
  end
238
265
  #
239
266
  if hash.key?('ident')
240
- if hash['ident'] && (type == 'map' || type == 'seq')
267
+ if hash['ident'] && Types.collection_type?(type)
241
268
  errors << validate_error(:ident_notscalar, rule, path, "ident:")
242
269
  end
243
270
  if path.empty?
@@ -247,21 +274,18 @@ END
247
274
  #
248
275
  if hash.key?('sequence')
249
276
  val = hash['sequence']
250
- if val != nil && !val.is_a?(Array)
251
- errors << validate_error(:sequence_notseq, rule, "#{path}/sequence", val)
252
- elsif val == nil || val.empty?
277
+ #if val != nil && !val.is_a?(Array)
278
+ # errors << validate_error(:sequence_notseq, rule, "#{path}/sequence", val)
279
+ #elsif ...
280
+ if val == nil || val.empty?
253
281
  errors << validate_error(:sequence_noelem, rule, "#{path}/sequence", val)
254
282
  elsif val.length > 1
255
283
  errors << validate_error(:sequence_toomany, rule, "#{path}/sequence", val)
256
284
  else
257
- child = hash['sequence'][0]
258
- if child.is_a?(Hash)
259
- if child['ident'] && child['type'] != 'map'
260
- errors << validate_error(:ident_notmap, nil, "#{path}/sequence/0", 'ident:')
261
- end
262
- #if child['unique'] && child['type'] != 'map'
263
- # errors << validate_error(:unique_notmap, nil, "#{path}/sequence/0", 'unique:')
264
- #end
285
+ elem = val[0]
286
+ assert_error("elem.class=#{elem.class}") unless elem.is_a?(Hash)
287
+ if elem['ident'] && elem['type'] != 'map'
288
+ errors << validate_error(:ident_notmap, nil, "#{path}/sequence/0", 'ident:')
265
289
  end
266
290
  end
267
291
  end
@@ -281,14 +305,14 @@ END
281
305
  errors << validate_error(:seq_conflict, rule, path, 'pattern:') if hash.key?('pattern')
282
306
  errors << validate_error(:seq_conflict, rule, path, 'mapping:') if hash.key?('mapping')
283
307
  #errors << validate_error(:seq_conflict, rule, path, 'range:') if hash.key?('range')
284
- errors << validate_error(:seq_conflict, rule, path, 'length:') if hash.key?('length')
308
+ #errors << validate_error(:seq_conflict, rule, path, 'length:') if hash.key?('length')
285
309
  elsif type == 'map'
286
310
  errors << validate_error(:map_nomapping, rule, path, nil) unless hash.key?('mapping')
287
311
  #errors << validate_error(:map_conflict, rule, path, 'enum:') if hash.key?('enum')
288
312
  errors << validate_error(:map_conflict, rule, path, 'pattern:') if hash.key?('pattern')
289
313
  errors << validate_error(:map_conflict, rule, path, 'sequence:') if hash.key?('sequence')
290
314
  #errors << validate_error(:map_conflict, rule, path, 'range:') if hash.key?('range')
291
- errors << validate_error(:map_conflict, rule, path, 'length:') if hash.key?('length')
315
+ #errors << validate_error(:map_conflict, rule, path, 'length:') if hash.key?('length')
292
316
  else
293
317
  errors << validate_error(:scalar_conflict, rule, path, 'sequence:') if hash.key?('sequence')
294
318
  errors << validate_error(:scalar_conflict, rule, path, 'mapping:') if hash.key?('mapping')
@@ -301,13 +325,21 @@ END
301
325
 
302
326
  end # end of def validate_hook()
303
327
 
328
+
329
+ schema = YAML.load(META_SCHEMA)
330
+ @instance = MetaValidator.new(schema)
331
+
332
+ def self.instance()
333
+ return @instance
334
+ end
335
+
336
+
304
337
  end # end of class MetaValidator
305
338
 
306
339
 
307
- schema = YAML.load(META_SCHEMA)
308
- META_VALIDATOR = MetaValidator.new(schema)
340
+ META_VALIDATOR = MetaValidator.instance()
309
341
 
310
- def self.meta_validator
342
+ def self.meta_validator # obsolete
311
343
  return META_VALIDATOR
312
344
  end
313
345
 
@@ -1,6 +1,6 @@
1
1
  ###
2
- ### $Rev: 39 $
3
- ### $Release: 0.4.1 $
2
+ ### $Rev: 42 $
3
+ ### $Release: 0.5.0 $
4
4
  ### copyright(c) 2005 kuwata-lab all rights reserved.
5
5
  ###
6
6
 
@@ -14,273 +14,375 @@ module Kwalify
14
14
  include Kwalify::ErrorHelper
15
15
 
16
16
  def initialize(hash=nil, parent=nil)
17
- configure(hash, "", {}) if hash
17
+ init(hash, "", {}) if hash
18
18
  @parent = parent
19
19
  end
20
+
20
21
  attr_accessor :parent
22
+ #attr_reader :id
23
+ attr_reader :name
24
+ attr_reader :desc
25
+ attr_reader :enum
26
+ attr_reader :required
27
+ attr_reader :type
28
+ attr_reader :type_class
29
+ attr_reader :pattern
30
+ attr_reader :regexp
31
+ attr_reader :sequence
32
+ attr_reader :mapping
33
+ attr_reader :assert
34
+ attr_reader :assert_proc
35
+ attr_reader :range
36
+ attr_reader :length
37
+ attr_reader :ident
38
+ attr_reader :unique
39
+
21
40
 
22
- def configure(hash, path="", rule_table={})
41
+ def init(hash, path="", rule_table={})
23
42
  unless hash.is_a?(Hash)
24
43
  #* key=:schema_notmap msg="schema definition is not a mapping."
25
44
  raise Kwalify.schema_error(:schema_notmap, nil, (!path || path.empty? ? "/" : path), nil)
26
45
  end
27
-
28
46
  rule = self
29
47
  rule_table[hash.__id__] = rule
48
+ ## 'type:' entry
49
+ _init_type_value(hash['type'], rule, path)
50
+ ## other entries
51
+ hash.each do |key, val|
52
+ code = key.intern
53
+ curr_path = "#{path}/#{key}"
54
+ case code
55
+ #when "id"
56
+ # @id = val
57
+ when :type ; # done
58
+ when :name ; _init_name_value( val, rule, path)
59
+ when :desc ; _init_desc_value( val, rule, path)
60
+ when :required ; _init_required_value(val, rule, path)
61
+ when :pattern ; _init_pattern_value( val, rule, path)
62
+ when :enum ; _init_enum_value( val, rule, path)
63
+ when :assert ; _init_assert_value( val, rule, path)
64
+ when :range ; _init_range_value( val, rule, path)
65
+ when :length ; _init_length_value( val, rule, path)
66
+ when :ident ; _init_ident_value( val, rule, path)
67
+ when :unique ; _init_unique_value( val, rule, path)
68
+ when :sequence ; _init_sequence_value(val, rule, path, rule_table)
69
+ when :mapping ; _init_mapping_value( val, rule, path, rule_table)
70
+ else
71
+ #* key=:key_unknown msg="unknown key."
72
+ raise schema_error(:key_unknown, rule, curr_path, "#{key}:")
73
+ end
74
+ end
75
+ check_confliction(hash, rule, path)
76
+ return self
77
+ end # end of def init
78
+
79
+
80
+ private
30
81
 
31
- ## 'type:'
32
- @type = hash['type']
33
- @type = Kwalify::DEFAULT_TYPE if @type == nil
82
+
83
+ def _init_type_value(val, rule, path)
84
+ @type = val
85
+ @type = Types::DEFAULT_TYPE if @type == nil
34
86
  unless @type.is_a?(String)
35
87
  #* key=:type_notstr msg="not a string."
36
88
  raise schema_error(:type_notstr, rule, "#{path}/type", @type.to_s)
37
89
  end
38
- @klass = Kwalify.get_type_class(@type)
39
- #if @klass == nil
90
+ @type_class = Types.type_class(@type)
91
+ #if @type_class == nil
40
92
  # begin
41
- # @klass = Kernel.const_get(@type)
93
+ # @type_class = Kernel.const_get(@type)
42
94
  # rescue NameError
43
95
  # end
44
96
  #end
45
- unless @klass
97
+ unless @type_class
46
98
  #* key=:type_unknown msg="unknown type."
47
99
  raise schema_error(:type_unknown, rule, "#{path}/type", @type.to_s)
48
100
  end
101
+ end
49
102
 
50
- ## other key
51
- hash.each do |key, val|
52
- curr_path = "#{path}/#{key}"
53
- case key
54
- #when "id"
55
- # @id = val
56
- when "name"
57
- @name = val
58
103
 
59
- when "desc"
60
- @desc = val
104
+ def _init_name_value(val, rule, path)
105
+ @name = val
106
+ end
61
107
 
62
- when "type"
63
- # done
64
108
 
65
- when "required"
66
- @required = val
67
- unless val.is_a?(Boolean) #|| val == nil
68
- #* key=:required_notbool msg="not a boolean."
69
- raise schema_error(:required_notbool, rule, curr_path, val)
70
- end
109
+ def _init_desc_value(val, rule, path)
110
+ @desc = val
111
+ end
71
112
 
72
- when "pattern"
73
- unless val =~ /\A\/(.*)\/([mi]?[mi]?)\z/
74
- #* key=:pattern_notmatch msg="should be '/..../'."
75
- raise schema_error(:pattern_notmatch, rule, curr_path, val)
76
- end
77
- pat = $1; opt = $2
78
- flag = 0
79
- flag += Regexp::IGNORECASE if opt.include?("i")
80
- flag += Regexp::MULTILINE if opt.include?("m")
81
- begin
82
- @pattern = Regexp.compile(pat, flag)
83
- rescue RegexpError => ex
84
- #* key=:pattern_syntaxerr msg="has regexp error."
85
- raise schema_error(:pattern_syntaxerr, rule, curr_path, val)
86
- end
87
113
 
88
- when "enum"
89
- @enum = val
90
- unless val.is_a?(Array)
91
- #* key=:enum_notseq msg="not a sequence."
92
- raise schema_error(:enum_notseq, rule, curr_path, val)
93
- end
94
- if @type == 'seq' || @type == 'map' # unless Kwalify.scalar_class?(@klass)
95
- #* key=:enum_notscalar msg="not available with seq or map."
96
- raise schema_error(:enum_notscalar, rule, path, 'enum:')
97
- end
98
- elem_table = {}
99
- @enum.each do |elem|
100
- unless !elem_table[elem]
101
- #* key=:enum_duplicate msg="duplicated enum value."
102
- raise schema_error(:enum_duplicate, rule, curr_path, elem.to_s)
103
- end
104
- elem_table[elem] = true
105
- unless elem.is_a?(@klass)
106
- #* key=:enum_type_unmatch msg="%s type expected."
107
- raise schema_error(:enum_type_unmatch, rule, curr_path, elem, [Kwalify.word(@type)])
108
- end
109
- end
114
+ def _init_required_value(val, rule, path)
115
+ @required = val
116
+ unless val.is_a?(Boolean) #|| val == nil
117
+ #* key=:required_notbool msg="not a boolean."
118
+ raise schema_error(:required_notbool, rule, "#{path}/required", val)
119
+ end
120
+ end
110
121
 
111
- when "assert" # or "cond-expr" ?
112
- @assert = val
113
- unless val.is_a?(String)
114
- #* key=:assert_notstr msg="not a string."
115
- raise schema_error(:assert_notstr, rule, curr_path, val)
116
- end
117
- unless val =~ /\bval\b/
118
- #* key=:assert_noval msg="'val' is not used."
119
- raise schema_error(:assert_noval, rule, curr_path, val)
120
- end
121
- begin
122
- @assert_proc = eval "proc { |val| #{val} }"
123
- rescue SyntaxError => ex
124
- #* key=:assert_syntaxerr msg="expression syntax error."
125
- raise schema_error(:assert_syntaxerr, rule, curr_path, val)
126
- end
122
+ def _init_pattern_value(val, rule, path)
123
+ @pattern = val
124
+ unless val.is_a?(String) || val.is_a?(Regexp)
125
+ #* key=:pattern_notstr msg="not a string (or regexp)"
126
+ raise schema_error(:pattern_notstr, rule, "#{path}/pattern", val)
127
+ end
128
+ unless val =~ /\A\/(.*)\/([mi]?[mi]?)\z/
129
+ #* key=:pattern_notmatch msg="should be '/..../'."
130
+ raise schema_error(:pattern_notmatch, rule, "#{path}/pattern", val)
131
+ end
132
+ pat = $1; opt = $2
133
+ flag = 0
134
+ flag += Regexp::IGNORECASE if opt.include?("i")
135
+ flag += Regexp::MULTILINE if opt.include?("m")
136
+ begin
137
+ @regexp = Regexp.compile(pat, flag)
138
+ rescue RegexpError => ex
139
+ #* key=:pattern_syntaxerr msg="has regexp error."
140
+ raise schema_error(:pattern_syntaxerr, rule, "#{path}/pattern", val)
141
+ end
142
+ end
127
143
 
128
- when "range"
129
- @range = val
130
- unless val.is_a?(Hash)
131
- #* key=:range_notmap msg="not a mapping."
132
- raise schema_error(:range_notmap, rule, curr_path, val)
133
- end
134
- if @type == 'map' || @type == 'seq' || @type == 'bool'
135
- #* key=:range_notscalar msg="is available only with scalar type."
136
- raise schema_error(:range_notscalar, rule, path, 'range:')
137
- end
138
- val.each do |rkey, rval|
139
- case rkey
140
- when 'max', 'min', 'max-ex', 'min-ex'
141
- unless rval.is_a?(@klass)
142
- typename = Kwalify.word(@type) || @type
143
- #* key=:range_type_unmatch msg="not a %s."
144
- raise schema_error(:range_type_unmatch, rule, "#{curr_path}/#{rkey}", rval, [typename])
145
- end
146
- else
147
- #* key=:range_undefined msg="undefined key."
148
- raise schema_error(:range_undefined, rule, "#{curr_path}/#{rkey}", "#{rkey}:")
149
- end
150
- end
151
- if val.key?('max') && val.key?('max-ex')
152
- #* key=:range_twomax msg="both 'max' and 'max-ex' are not available at once."
153
- raise schema_error(:range_twomax, rule, curr_path, nil)
154
- end
155
- if val.key?('min') && val.key?('min-ex')
156
- #* key=:range_twomin msg="both 'min' and 'min-ex' are not available at once."
157
- raise schema_error(:range_twomin, rule, curr_path, nil)
158
- end
159
144
 
160
- when "length" # or "width"
161
- @length = val
162
- unless val.is_a?(Hash)
163
- #* key=:length_notmap msg="not a mapping."
164
- raise schema_error(:length_notmap, rule, curr_path, val)
165
- end
166
- unless @type == 'str' || @type == 'text'
167
- #* key=:length_nottext msg="is available only with string or text."
168
- raise schema_error(:length_nottext, rule, path, 'length:')
169
- end
170
- val.each do |lkey, lval|
171
- case lkey
172
- when 'max', 'min', 'max-ex', 'min-ex'
173
- unless lval.is_a?(Integer)
174
- #* key=:length_notint msg="not an integer."
175
- raise schema_error(:length_notint, rule, "#{curr_path}/#{lkey}", lval)
176
- end
177
- else
178
- #* key=:length_undefined msg="undefined key."
179
- raise schema_error(:length_undefined, rule, "#{curr_path}/#{lkey}", "#{lkey}:")
180
- end
181
- end
182
- if val.key?('max') && val.key?('max-ex')
183
- #* key=:length_twomax msg="both 'max' and 'max-ex' are not available at once."
184
- raise schema_error(:length_twomax, rule, curr_path, nil)
185
- end
186
- if val.key?('min') && val.key?('min-ex')
187
- #* key=:length_twomin msg="both 'min' and 'min-ex' are not available at once."
188
- raise schema_error(:length_twomin, rule, curr_path, nil)
189
- end
145
+ def _init_enum_value(val, rule, path)
146
+ @enum = val
147
+ unless val.is_a?(Array)
148
+ #* key=:enum_notseq msg="not a sequence."
149
+ raise schema_error(:enum_notseq, rule, "#{path}/enum", val)
150
+ end
151
+ if Types.collection_type?(@type) # unless Kwalify.scalar_class?(@type_class)
152
+ #* key=:enum_notscalar msg="not available with seq or map."
153
+ raise schema_error(:enum_notscalar, rule, path, 'enum:')
154
+ end
155
+ elem_table = {}
156
+ @enum.each do |elem|
157
+ unless elem.is_a?(@type_class)
158
+ #* key=:enum_type_unmatch msg="%s type expected."
159
+ raise schema_error(:enum_type_unmatch, rule, "#{path}/enum", elem, [Kwalify.word(@type)])
160
+ end
161
+ if elem_table[elem]
162
+ #* key=:enum_duplicate msg="duplicated enum value."
163
+ raise schema_error(:enum_duplicate, rule, "#{path}/enum", elem.to_s)
164
+ end
165
+ elem_table[elem] = true
166
+ end
167
+ end
190
168
 
191
- when "ident"
192
- @ident = val
193
- @required = true
194
- unless val.is_a?(Boolean)
195
- #* key=:ident_notbool msg="not a boolean."
196
- raise schema_error(:ident_notbool, rule, curr_path, val)
197
- end
198
- if @type == 'map' || @type == 'seq'
199
- #* key=:ident_notscalar msg="is available only with a scalar type."
200
- raise schema_error(:ident_notscalar, rule, path, "ident:")
201
- end
202
- if path.empty?
203
- #* key=:ident_onroot msg="is not available on root element."
204
- raise schema_error(:ident_onroot, rule, "/", "ident:")
205
- end
206
- unless @parent && @parent.type == 'map'
207
- #* key=:ident_notmap msg="is available only with an element of mapping."
208
- raise schema_error(:ident_notmap, rule, path, "ident:")
209
- end
210
169
 
211
- when "unique"
212
- @unique = val
213
- unless val.is_a?(Boolean)
214
- #* key=:unique_notbool msg="not a boolean."
215
- raise schema_error(:unique_notbool, rule, curr_path, val)
216
- end
217
- if @type == 'map' || @type == 'seq'
218
- #* key=:unique_notscalar msg="is available only with a scalar type."
219
- raise schema_error(:unique_notscalar, rule, path, "unique:")
220
- end
221
- if path.empty?
222
- #* key=:unique_onroot msg="is not available on root element."
223
- raise schema_error(:unique_onroot, rule, "/", "unique:")
224
- end
225
- #unless @parent && @parent.type == 'map'
226
- # #* key=:unique_notmap msg="is available only with an element of mapping."
227
- # raise schema_error(:unique_notmap, rule, path, "unique:")
228
- #end
229
-
230
- when "sequence"
231
- if val != nil && !val.is_a?(Array)
232
- #* key=:sequence_notseq msg="not a sequence."
233
- raise schema_error(:sequence_notseq, rule, curr_path, val)
234
- elsif val == nil || val.empty?
235
- #* key=:sequence_noelem msg="required one element."
236
- raise schema_error(:sequence_noelem, rule, curr_path, val)
237
- elsif val.length > 1
238
- #* key=:sequence_toomany msg="required just one element."
239
- raise schema_error(:sequence_toomany, rule, curr_path, val)
240
- else
241
- elem = val[0]
242
- elem ||= {}
243
- i = 0 # or 1? *index*
244
- rule = rule_table[elem.__id__]
245
- rule ||= Rule.new(nil, self).configure(elem, "#{curr_path}/#{i}", rule_table)
246
- @sequence = [ rule ]
247
- end
170
+ def _init_assert_value(val, rule, path)
171
+ @assert = val
172
+ unless val.is_a?(String)
173
+ #* key=:assert_notstr msg="not a string."
174
+ raise schema_error(:assert_notstr, rule, "#{path}/assert", val)
175
+ end
176
+ unless val =~ /\bval\b/
177
+ #* key=:assert_noval msg="'val' is not used."
178
+ raise schema_error(:assert_noval, rule, "#{path}/assert", val)
179
+ end
180
+ begin
181
+ @assert_proc = eval "proc { |val| #{val} }"
182
+ rescue SyntaxError => ex
183
+ #* key=:assert_syntaxerr msg="expression syntax error."
184
+ raise schema_error(:assert_syntaxerr, rule, "#{path}/assert", val)
185
+ end
186
+ end
248
187
 
249
- when "mapping"
250
- if val != nil && !val.is_a?(Hash)
251
- #* key=:mapping_notmap msg="not a mapping."
252
- raise schema_error(:mapping_notmap, rule, curr_path, val)
253
- elsif val == nil || (val.empty? && !val.default)
254
- #* key=:mapping_noelem msg="required at least one element."
255
- raise schema_error(:mapping_noelem, rule, curr_path, val)
256
- else
257
- @mapping = {}
258
- if val.default
259
- elem = val.default # hash
260
- rule = rule_table[elem.__id__]
261
- rule ||= Rule.new(nil, self).configure(elem, "#{curr_path}/=", rule_table)
262
- @mapping.default = rule
263
- end
264
- val.each do |key, elem|
265
- ##* key=:key_duplicate msg="key duplicated."
266
- #raise schema_error(:key_duplicate, rule, curr_path, key) if @mapping.key?(key)
267
- elem ||= {}
268
- rule = rule_table[elem.__id__]
269
- rule ||= Rule.new(nil, self).configure(elem, "#{curr_path}/#{key}", rule_table)
270
- if key == '='
271
- @mapping.default = rule
272
- else
273
- @mapping[key] = rule
274
- end
275
- end if val
188
+
189
+ def _init_range_value(val, rule, path)
190
+ @range = val
191
+ curr_path = "#{path}/range"
192
+ unless val.is_a?(Hash)
193
+ #* key=:range_notmap msg="not a mapping."
194
+ raise schema_error(:range_notmap, rule, curr_path, val)
195
+ end
196
+ if Types.collection_type?(@type) || @type == 'bool'
197
+ #* key=:range_notscalar msg="is available only with scalar type."
198
+ raise schema_error(:range_notscalar, rule, path, 'range:')
199
+ end
200
+ val.each do |k, v|
201
+ case k
202
+ when 'max', 'min', 'max-ex', 'min-ex'
203
+ unless v.is_a?(@type_class)
204
+ typename = Kwalify.word(@type) || @type
205
+ #* key=:range_type_unmatch msg="not a %s."
206
+ raise schema_error(:range_type_unmatch, rule, "#{curr_path}/#{k}", v, [typename])
276
207
  end
208
+ else
209
+ #* key=:range_undefined msg="undefined key."
210
+ raise schema_error(:range_undefined, rule, "#{curr_path}/#{k}", "#{k}:")
211
+ end
212
+ end
213
+ if val.key?('max') && val.key?('max-ex')
214
+ #* key=:range_twomax msg="both 'max' and 'max-ex' are not available at once."
215
+ raise schema_error(:range_twomax, rule, curr_path, nil)
216
+ end
217
+ if val.key?('min') && val.key?('min-ex')
218
+ #* key=:range_twomin msg="both 'min' and 'min-ex' are not available at once."
219
+ raise schema_error(:range_twomin, rule, curr_path, nil)
220
+ end
221
+ max, min, max_ex, min_ex = val['max'], val['min'], val['max-ex'], val['min-ex']
222
+ if max
223
+ if min && max < min
224
+ #* key=:range_maxltmin msg="max '%s' is less than min '%s'."
225
+ raise validate_error(:range_maxltmin, rule, curr_path, nil, [max, min])
226
+ elsif min_ex && max <= min_ex
227
+ #* key=:range_maxleminex msg="max '%s' is less than or equal to min-ex '%s'."
228
+ raise validate_error(:range_maxleminex, rule, curr_path, nil, [max, min_ex])
229
+ end
230
+ elsif max_ex
231
+ if min && max_ex <= min
232
+ #* key=:range_maxexlemin msg="max-ex '%s' is less than or equal to min '%s'."
233
+ raise validate_error(:range_maxexlemin, rule, curr_path, nil, [max_ex, min])
234
+ elsif min_ex && max_ex <= min_ex
235
+ #* key=:range_maxexleminex msg="max-ex '%s' is less than or equal to min-ex '%s'."
236
+ raise validate_error(:range_maxexleminex, rule, curr_path, nil, [max_ex, min_ex])
237
+ end
238
+ end
239
+ end
277
240
 
241
+
242
+ def _init_length_value(val, rule, path)
243
+ @length = val
244
+ curr_path = "#{path}/length"
245
+ unless val.is_a?(Hash)
246
+ #* key=:length_notmap msg="not a mapping."
247
+ raise schema_error(:length_notmap, rule, curr_path, val)
248
+ end
249
+ unless @type == 'str' || @type == 'text'
250
+ #* key=:length_nottext msg="is available only with string or text."
251
+ raise schema_error(:length_nottext, rule, path, 'length:')
252
+ end
253
+ val.each do |k, v|
254
+ case k
255
+ when 'max', 'min', 'max-ex', 'min-ex'
256
+ unless v.is_a?(Integer)
257
+ #* key=:length_notint msg="not an integer."
258
+ raise schema_error(:length_notint, rule, "#{curr_path}/#{k}", v)
259
+ end
278
260
  else
279
- #* key=:key_unknown msg="unknown key."
280
- raise schema_error(:key_unknown, rule, curr_path, "#{key}:")
261
+ #* key=:length_undefined msg="undefined key."
262
+ raise schema_error(:length_undefined, rule, "#{curr_path}/#{k}", "#{k}:")
263
+ end
264
+ end
265
+ if val.key?('max') && val.key?('max-ex')
266
+ #* key=:length_twomax msg="both 'max' and 'max-ex' are not available at once."
267
+ raise schema_error(:length_twomax, rule, curr_path, nil)
268
+ end
269
+ if val.key?('min') && val.key?('min-ex')
270
+ #* key=:length_twomin msg="both 'min' and 'min-ex' are not available at once."
271
+ raise schema_error(:length_twomin, rule, curr_path, nil)
272
+ end
273
+ max, min, max_ex, min_ex = val['max'], val['min'], val['max-ex'], val['min-ex']
274
+ if max
275
+ if min && max < min
276
+ #* key=:length_maxltmin msg="max '%s' is less than min '%s'."
277
+ raise validate_error(:length_maxltmin, rule, curr_path, nil, [max, min])
278
+ elsif min_ex && max <= min_ex
279
+ #* key=:length_maxleminex msg="max '%s' is less than or equal to min-ex '%s'."
280
+ raise validate_error(:length_maxleminex, rule, curr_path, nil, [max, min_ex])
281
+ end
282
+ elsif max_ex
283
+ if min && max_ex <= min
284
+ #* key=:length_maxexlemin msg="max-ex '%s' is less than or equal to min '%s'."
285
+ raise validate_error(:length_maxexlemin, rule, curr_path, nil, [max_ex, min])
286
+ elsif min_ex && max_ex <= min_ex
287
+ #* key=:length_maxexleminex msg="max-ex '%s' is less than or equal to min-ex '%s'."
288
+ raise validate_error(:length_maxexleminex, rule, curr_path, nil, [max_ex, min_ex])
289
+ end
290
+ end
291
+ end
292
+
293
+
294
+ def _init_ident_value(val, rule, path)
295
+ @ident = val
296
+ @required = true
297
+ unless val.is_a?(Boolean)
298
+ #* key=:ident_notbool msg="not a boolean."
299
+ raise schema_error(:ident_notbool, rule, "#{path}/ident", val)
300
+ end
301
+ if @type == 'map' || @type == 'seq'
302
+ #* key=:ident_notscalar msg="is available only with a scalar type."
303
+ raise schema_error(:ident_notscalar, rule, path, "ident:")
304
+ end
305
+ if path.empty?
306
+ #* key=:ident_onroot msg="is not available on root element."
307
+ raise schema_error(:ident_onroot, rule, "/", "ident:")
308
+ end
309
+ unless @parent && @parent.type == 'map'
310
+ #* key=:ident_notmap msg="is available only with an element of mapping."
311
+ raise schema_error(:ident_notmap, rule, path, "ident:")
312
+ end
313
+ end
314
+
315
+
316
+ def _init_unique_value(val, rule, path)
317
+ @unique = val
318
+ unless val.is_a?(Boolean)
319
+ #* key=:unique_notbool msg="not a boolean."
320
+ raise schema_error(:unique_notbool, rule, "#{path}/unique", val)
321
+ end
322
+ if @type == 'map' || @type == 'seq'
323
+ #* key=:unique_notscalar msg="is available only with a scalar type."
324
+ raise schema_error(:unique_notscalar, rule, path, "unique:")
325
+ end
326
+ if path.empty?
327
+ #* key=:unique_onroot msg="is not available on root element."
328
+ raise schema_error(:unique_onroot, rule, "/", "unique:")
329
+ end
330
+ end
331
+
332
+
333
+ def _init_sequence_value(val, rule, path, rule_table)
334
+ if val != nil && !val.is_a?(Array)
335
+ #* key=:sequence_notseq msg="not a sequence."
336
+ raise schema_error(:sequence_notseq, rule, "#{path}/sequence", val)
337
+ elsif val == nil || val.empty?
338
+ #* key=:sequence_noelem msg="required one element."
339
+ raise schema_error(:sequence_noelem, rule, "#{path}/sequence", val)
340
+ elsif val.length > 1
341
+ #* key=:sequence_toomany msg="required just one element."
342
+ raise schema_error(:sequence_toomany, rule, "#{path}/sequence", val)
343
+ else
344
+ elem = val[0]
345
+ elem ||= {}
346
+ i = 0 # or 1? *index*
347
+ rule = rule_table[elem.__id__]
348
+ rule ||= Rule.new(nil, self).init(elem, "#{path}/sequence/#{i}", rule_table)
349
+ @sequence = [ rule ]
350
+ end
351
+ end
352
+
353
+
354
+ def _init_mapping_value(val, rule, path, rule_table)
355
+ if val != nil && !val.is_a?(Hash)
356
+ #* key=:mapping_notmap msg="not a mapping."
357
+ raise schema_error(:mapping_notmap, rule, "#{path}/mapping", val)
358
+ elsif val == nil || (val.empty? && !val.default)
359
+ #* key=:mapping_noelem msg="required at least one element."
360
+ raise schema_error(:mapping_noelem, rule, "#{path}/mapping", val)
361
+ else
362
+ @mapping = {}
363
+ if val.default
364
+ elem = val.default # hash
365
+ rule = rule_table[elem.__id__]
366
+ rule ||= Rule.new(nil, self).init(elem, "#{path}/mapping/=", rule_table)
367
+ @mapping.default = rule
281
368
  end
369
+ val.each do |k, v|
370
+ ##* key=:key_duplicate msg="key duplicated."
371
+ #raise schema_error(:key_duplicate, rule, "#{path}/mapping", key) if @mapping.key?(key)
372
+ v ||= {}
373
+ rule = rule_table[v.__id__]
374
+ rule ||= Rule.new(nil, self).init(v, "#{path}/mapping/#{k}", rule_table)
375
+ if k == '='
376
+ @mapping.default = rule
377
+ else
378
+ @mapping[k] = rule
379
+ end
380
+ end if val
282
381
  end
382
+ end
283
383
 
384
+
385
+ def check_confliction(hash, rule, path)
284
386
  if @type == 'seq'
285
387
  #* key=:seq_nosequence msg="type 'seq' requires 'sequence:'."
286
388
  raise schema_error(:seq_nosequence, rule, path, nil) unless hash.key?('sequence')
@@ -310,28 +412,7 @@ module Kwalify
310
412
  raise schema_error(:enum_conflict, rule, path, 'pattern:') if @pattern
311
413
  end
312
414
  end
313
-
314
- return self
315
-
316
- end # end of def configure
317
-
318
- #attr_reader :id
319
- attr_reader :name
320
- attr_reader :desc
321
- attr_reader :enum
322
- attr_reader :required
323
- attr_reader :type
324
- attr_reader :klass
325
- attr_reader :pattern
326
- attr_reader :sequence
327
- attr_reader :mapping
328
- attr_reader :assert
329
- attr_reader :assert_proc
330
- attr_reader :range
331
- attr_reader :length
332
- attr_reader :ident
333
- attr_reader :unique
334
-
415
+ end
335
416
 
336
417
  #def inspect()
337
418
  # str = ""; level = 0; done = {}
@@ -340,7 +421,7 @@ module Kwalify
340
421
  #end
341
422
 
342
423
 
343
- #protected
424
+ protected
344
425
 
345
426
 
346
427
  def _inspect(str="", level=0, done={})
@@ -348,9 +429,9 @@ module Kwalify
348
429
  str << " " * level << "name: #{@name}\n" if @name != nil
349
430
  str << " " * level << "desc: #{@desc}\n" if @desc != nil
350
431
  str << " " * level << "type: #{@type}\n" if @type != nil
351
- str << " " * level << "klass: #{@klass.name}\n" if @klass != nil
432
+ str << " " * level << "klass: #{@type_class.name}\n" if @type_class != nil
352
433
  str << " " * level << "required: #{@required}\n" if @required != nil
353
- str << " " * level << "pattern: #{@pattern.inspect}\n" if @pattern != nil
434
+ str << " " * level << "pattern: #{@regexp.inspect}\n" if @pattern != nil
354
435
  str << " " * level << "assert: #{@assert}\n" if @assert != nil
355
436
  str << " " * level << "ident: #{@ident}\n" if @ident != nil
356
437
  str << " " * level << "unique: #{@unique}\n" if @unique != nil
@@ -360,25 +441,31 @@ module Kwalify
360
441
  str << " " * (level+1) << "- #{item}\n"
361
442
  end
362
443
  end
363
- if @range != nil
444
+ if @range != nil
364
445
  str << " " * level
365
446
  str << "range: { "
366
- str << "max: #{@range['max'].inspect}" if @range['max'] != nil
367
- str << "max-ex: #{@range['max-ex'].inspect}" if @range['max-ex'] != nil
368
- str << ", " if (@range['max'] || @range['max-ex']) && (@range['min'] || @range['min-ex'])
369
- str << "min: #{@range['min'].inspect}" if @range['min'] != nil
370
- str << "min-ex: #{@range['min-ex'].inspect}" if @range['min-ex'] != nil
371
- str << "}\n"
372
- end
373
- if @length != nil
447
+ colon = ""
448
+ %w[max max-ex min min-ex].each do |key|
449
+ val = @range[key]
450
+ if val != nil
451
+ str << colon << "#{key}: #{val.inspect}"
452
+ colon = ", "
453
+ end
454
+ end
455
+ str << " }\n"
456
+ end
457
+ if @length != nil
374
458
  str << " " * level
375
459
  str << "length: { "
376
- str << "max: #{@length['max'].inspect}" if @length['max'] != nil
377
- str << "max-ex: #{@length['max-ex'].inspect}" if @length['max-ex'] != nil
378
- str << ", " if (@length['max'] || @length['max-ex']) && (@length['min'] || @length['min-ex'])
379
- str << "min: #{@length['min'].inspect}" if @length['min'] != nil
380
- str << "min-ex: #{@length['min-ex'].inspect}" if @length['min-ex'] != nil
381
- str << "}\n"
460
+ colon = ""
461
+ %w[max max-ex min min-ex].each do |key|
462
+ val = @length[key]
463
+ if val != nil
464
+ str << colon << "#{key}: #{val.inspect}"
465
+ colon = ", "
466
+ end
467
+ end
468
+ str << " }\n"
382
469
  end
383
470
  @sequence.each do |rule|
384
471
  if done[rule.__id__]