ClsRuby 1.0.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.
Files changed (71) hide show
  1. data/LICENSE +26 -0
  2. data/README +55 -0
  3. data/THANKS +0 -0
  4. data/docs/base_formatting_methods +89 -0
  5. data/docs/base_parsing_methods +79 -0
  6. data/docs/constructor_params +131 -0
  7. data/docs/examples/log_single_line_format +3 -0
  8. data/docs/examples/service_description +3 -0
  9. data/docs/examples/sms-hist +3 -0
  10. data/docs/examples/tag_any +3 -0
  11. data/docs/fragments/custom_tag_field.rb +20 -0
  12. data/docs/fragments/custom_tag_include.rb +21 -0
  13. data/docs/fragments/field.cls +2 -0
  14. data/docs/fragments/include.cls +4 -0
  15. data/docs/fragments/inherit_tag_params.rb +21 -0
  16. data/docs/fragments/message.cls +6 -0
  17. data/docs/fragments/tag_field.rb +24 -0
  18. data/docs/fragments/tag_message.rb +74 -0
  19. data/docs/fragments/tags_order.rb +41 -0
  20. data/docs/principles +402 -0
  21. data/docs/std_tags_short_description +278 -0
  22. data/docs/syntax +227 -0
  23. data/docs/why_cls +178 -0
  24. data/examples/hex_stream.txt +1 -0
  25. data/examples/log_single_line_formatter.rb +79 -0
  26. data/examples/service_description.day_time.cfg +11 -0
  27. data/examples/service_description.rb +119 -0
  28. data/examples/sms-hist.rb +164 -0
  29. data/examples/space_concat.txt +3 -0
  30. data/examples/tag_any.rb +28 -0
  31. data/lib/cls-ruby/basic_scalars.rb +270 -0
  32. data/lib/cls-ruby/constraints/one_of.rb +36 -0
  33. data/lib/cls-ruby/default_formatter.rb +50 -0
  34. data/lib/cls-ruby/ex.rb +121 -0
  35. data/lib/cls-ruby/formatter.rb +31 -0
  36. data/lib/cls-ruby/lexers/char_classifier.rb +157 -0
  37. data/lib/cls-ruby/lexers/first_stage.rb +112 -0
  38. data/lib/cls-ruby/lexers/lexer.rb +74 -0
  39. data/lib/cls-ruby/oneline_formatter.rb +35 -0
  40. data/lib/cls-ruby/parser.rb +249 -0
  41. data/lib/cls-ruby/tag.rb +428 -0
  42. data/lib/cls-ruby/tag_any.rb +111 -0
  43. data/lib/cls-ruby/tag_no_value.rb +55 -0
  44. data/lib/cls-ruby/tag_scalar.rb +197 -0
  45. data/lib/cls-ruby/tag_scalar_helpers.rb +70 -0
  46. data/lib/cls-ruby/tag_scalar_vector.rb +148 -0
  47. data/lib/cls-ruby/tag_vector_of_different_tags.rb +172 -0
  48. data/lib/cls-ruby/tag_vector_of_tags.rb +116 -0
  49. data/lib/cls-ruby/vector_of_tags_impl.rb +129 -0
  50. data/lib/cls-ruby.rb +5 -0
  51. data/tests/tc_child_tag.rb +51 -0
  52. data/tests/tc_constraint_one_of.rb +47 -0
  53. data/tests/tc_format_helper.rb +27 -0
  54. data/tests/tc_formatters.rb +125 -0
  55. data/tests/tc_lexer.rb +124 -0
  56. data/tests/tc_lexer_char_classifier.rb +121 -0
  57. data/tests/tc_lexer_first_stage.rb +72 -0
  58. data/tests/tc_parser_simple.rb +93 -0
  59. data/tests/tc_scalar_parsers.rb +189 -0
  60. data/tests/tc_tag.rb +68 -0
  61. data/tests/tc_tag_no_value.rb +46 -0
  62. data/tests/tc_tag_scalar_int.rb +83 -0
  63. data/tests/tc_tag_scalar_nonspace_string.rb +46 -0
  64. data/tests/tc_tag_scalar_string.rb +47 -0
  65. data/tests/tc_tag_scalar_vector_int.rb +88 -0
  66. data/tests/tc_tag_scalar_vector_string.rb +48 -0
  67. data/tests/tc_tag_scalar_vector_string_empty.rb +40 -0
  68. data/tests/tc_tag_vector_of_different_tags.rb +109 -0
  69. data/tests/tc_tag_vector_of_tags.rb +103 -0
  70. data/tests/ts_cls_ruby.rb +7 -0
  71. metadata +140 -0
@@ -0,0 +1,428 @@
1
+ #
2
+ # ������� ����� CLS �����.
3
+ #
4
+
5
+ module ClsRuby
6
+
7
+ # ������� ����� CLS �����.
8
+ #
9
+ class Tag
10
+ # �����������.
11
+ #
12
+ # ��������� ��������� � ���� Hash. ������������ �����:
13
+ # :name => ��� ����.
14
+ # :owner => ������������ ���. ������������� ���������
15
+ # ���� � ������ �������� ����� � ��������.
16
+ # :mandatory => true ��� false. ������� ����, ��� ���
17
+ # ������ ���� ������������.
18
+ # �� ��������� ��� ��������� ������������.
19
+ # ��������� ����� ������������.
20
+ def initialize( args = {} )
21
+ @tag_params = tag_default_params.merge( args )
22
+ @tag_name = tag_params.fetch( :name, nil )
23
+
24
+ owner = tag_params.fetch( :owner, nil )
25
+ owner.tag_add( self ) if owner
26
+
27
+ @tag_mandatory = tag_params.fetch( :mandatory, false )
28
+ @tag_defined = false
29
+
30
+ @tag_children = []
31
+
32
+ tag_init_children_tags
33
+ end
34
+
35
+ # ��� ����.
36
+ #
37
+ # ���������� nil, ���� � ������������ ��� ���� �� ���� ������.
38
+ def tag_name; @tag_name; end
39
+
40
+ # ��������� ����� ���� � ��������� ������.
41
+ #
42
+ # ������������ ��� ���������� � ����������� ������� ��� ������,
43
+ # ����� ���� ��� ����� ����� ��������� ����.
44
+ def tag_compare_name( name )
45
+ @tag_name == name
46
+ end
47
+
48
+ # ���������� ��������� ���� � ������ �������� �����.
49
+ def tag_add( child )
50
+ @tag_children << child
51
+ end
52
+
53
+ # ��������� ������ �������� �����.
54
+ def tag_tags; @tag_children; end
55
+
56
+ # �������� �� ��� ������������?
57
+ #
58
+ # �� ��������� ���������� �������� �������� @tag_mandatory.
59
+ def tag_mandatory?; @tag_mandatory; end
60
+
61
+ # �������� �� ��� ��������� ������������ � �������� �������?
62
+ #
63
+ # �� ��������� ���������� �������� �������� @tag_defined (�� ���������
64
+ # �������� true ���� � ������ tag_on_finish, ���� � ������ tag_make_defined).
65
+ def tag_defined?; @tag_defined; end
66
+
67
+ # ���������� �������, ��� ��� ��������� ���������.
68
+ def tag_make_defined; @tag_defined = true; end
69
+
70
+ # �������� ���������� ����.
71
+ #
72
+ # ��������� ��� � ���������, �������������� ��������.
73
+ #
74
+ # �� ��������� �������� ����� tag_reset � ���� �������� �����, ����� ����
75
+ # ������������� @tag_defined � false.
76
+ def tag_reset
77
+ @tag_children.each do |tag| tag.tag_reset end
78
+
79
+ @tag_defined = false
80
+ end
81
+
82
+ # ��������� �������������� ����.
83
+ #
84
+ # ������ formatter ������������ ��������� TagFormatter.
85
+ #
86
+ # ���������� � ������� ������ ��������� ��������� ��������:
87
+ # * �������� � formatter ����� start;
88
+ # * �������� ����������� ����� tag_on_format;
89
+ # * �������� ����� tag_format � ���� �������� �����;
90
+ # * �������� � formatter ����� finish.
91
+ #
92
+ # ����� �������, ���� ������������ ������ ����� ���������� �����������
93
+ # ����������, �� �� ������ �������������� � ���� ����� tag_on_format.
94
+ #
95
+ def tag_format( formatter )
96
+ if tag_defined?
97
+ formatter.start( tag_name )
98
+
99
+ tag_on_format( formatter )
100
+ tag_tags.each do |child| child.tag_format( formatter ) end
101
+
102
+ formatter.finish
103
+ end
104
+
105
+ self
106
+ end
107
+
108
+ # ������� �� ������ �������� ���� �� ������� ������.
109
+ #
110
+ # � ������� ������ ������ �� ������. ������������ ��� ��������������
111
+ # ����������� ���������� � ����������� �������.
112
+ def tag_on_start( name ); end
113
+
114
+ # ������� �� ���������� �������� ���� �� ������� ������.
115
+ #
116
+ # ������������� ��� �������� ���� � ���� ������� ��������������
117
+ # ������������ ���, �� ��������� ���������� UndefinedMandatoryTagEx.
118
+ #
119
+ # ����� ���� ������ ������ ���� ��������� ������������.
120
+ def tag_on_finish
121
+ @tag_children.each do |tag|
122
+ raise UndefinedMandatoryTagEx.new( tag.tag_name ) if
123
+ tag.tag_mandatory? && !tag.tag_defined?
124
+ end
125
+
126
+ tag_make_defined
127
+ end
128
+
129
+ # ������� �� ���������� ������� ��������� ���� �� ������� ������.
130
+ #
131
+ # ������ �� ������. ����� ������������ ��� ���������� � �����������
132
+ # ������� ��� �������������� ����������� ������� ���-������ ��������.
133
+ def tag_on_tag( tag )
134
+ end
135
+
136
+ # ������� �� ����� :tok_space.
137
+ #
138
+ # ������ �� ������.
139
+ def tag_on_tok_space( token ); end
140
+
141
+ # ������� �� ����� :tok_nonspace.
142
+ #
143
+ # ��������� ���������� UnexpectedTokenEx.
144
+ def tag_on_tok_nonspace( token )
145
+ raise UnexpectedTokenEx.new(
146
+ "unexpected token :tok_nonspace ('#{token}')" )
147
+ end
148
+
149
+ # ������� �� ����� :tok_string.
150
+ #
151
+ # ��������� ���������� UnexpectedTokenEx.
152
+ def tag_on_tok_string( token )
153
+ raise UnexpectedTokenEx.new(
154
+ "unexpected token :tok_string ('#{token}')" )
155
+ end
156
+
157
+ # ���������� ��� �������������� ������������ �����������.
158
+ #
159
+ # � ������� ������ ������ �� ������. ������������ ��� ���������������
160
+ # � ����������� �������.
161
+ def tag_on_format( formatter )
162
+ end
163
+
164
+ # ��������������� ����� ��� �������������� �������� ����� ��
165
+ # ����� �������� ������������ ������ ����.
166
+ #
167
+ # ������ �������������.
168
+ # ����� ���������� ������� ��������� ���������:
169
+ # {params
170
+ # {min <int:1..100>}
171
+ # {max <int:100..1000>}
172
+ # {password <str>}
173
+ # }
174
+ #
175
+ # ��� ����� ����� ��������� ���:
176
+ # class TagParams < ClsRuby::TagNoValue
177
+ # child_tag :min, ClsRuby::TagScalar,
178
+ # :mandatory => true,
179
+ # :format => ClsRuby::SCALAR_INT,
180
+ # :constraint => 1..100
181
+ # child_tag :max, ClsRuby::TagScalar,
182
+ # :mandatory => true,
183
+ # :format => ClsRuby::SCALAR_INT,
184
+ # :constraint => 100..1000
185
+ # child_tag :password, ClsRuby::TagScalar,
186
+ # :mandatory => true,
187
+ # :format => ClsRuby::SCALAR_STRING
188
+ #
189
+ # default_tag_params :name => 'params'
190
+ #
191
+ # def query_params
192
+ # Params.new( @min.value, @max.value, @password.value )
193
+ # end
194
+ # end
195
+ #
196
+ # ���� ���������, ����� instance variables ����������� � ����� ������
197
+ # (��������, op_id), � ��� �� ������� ������ ���� ���� ��������,
198
+ # �� � ������ ���������� child_tag ����� ������� �������� � ������ :name
199
+ # child_tag :op_id, ClsRuby::TagScalar,
200
+ # :name => 'op-id',
201
+ # :mandatory => true,
202
+ # :format => ClsRuby::SCALAR_STRING
203
+ #
204
+ # ������� ������������� ��. � �������� tag_metaclass.
205
+ #
206
+ def Tag.child_tag( name, type, params = {} )
207
+ tag_metaclass.tag_add_child_tag_info( name, type, params )
208
+ end
209
+
210
+ # ��������������� ����� � ���������� � ������ child_tag, �������
211
+ # ��������� ��������� ���������� ������������ �����.
212
+ #
213
+ # ��� �������������:
214
+ # mandatory_child_tag :min, ClsRuby::TagScalar,
215
+ # :format => ClsRuby::SCALAR_INT
216
+ # ��������� ������������ ����� ������������� ������������� child_tag:
217
+ # child_tag :min, ClsRuby::TagScalar,
218
+ # :format => ClsRuby::SCALAR_INT,
219
+ # :mandatory => true
220
+ #
221
+ def Tag.mandatory_child_tag( name, type, params = {} )
222
+ child_tag( name, type, params.merge( :mandatory => true ) )
223
+ end
224
+
225
+ # ��������������� �����, ������� ��������� ������ ���������
226
+ # ���� �� ���������.
227
+ #
228
+ # ���� ��������������� �����-�� ���, ������� � ����������� �������
229
+ # ����� ����� ���������� ���, �� ������ ��� ��� ����� �����
230
+ # ���������:
231
+ # - ��-������, ����� ������� ����������� �����������:
232
+ #
233
+ # class TagMy < ClsRuby::TagNoValue
234
+ # def initialize( params = {} )
235
+ # super( { :name => 'my-tag' }.merge( params ) )
236
+ # end
237
+ # ...
238
+ # end
239
+ # ...
240
+ # t = TagMy.new # ������������ ��� my-tag.
241
+ # c = TagMy.new( :name => 'custom-tag' ) # ��� custom-tag ������ my-tag.
242
+ # - ��-������, ����� ������ �� ������� ����� ������� �����������
243
+ # ���������� default_tag_params:
244
+ #
245
+ # class TagMy < ClsRuby::TagNoValue
246
+ # default_tag_params :name => 'my-tag'
247
+ # ...
248
+ # end
249
+ # ...
250
+ # t = TagMy.new # ������������ ��� my-tag.
251
+ # c = TagMy.new( :name => 'custom-tag' ) # ��� custom-tag ������ my-tag.
252
+ #
253
+ # <b>����������.</b> ���� � ������� ������� ������� ��������� ���
254
+ # ������������ default_tag_params, �� ��� �������� ��������� �� ���������
255
+ # ������������. ������ ���, ��� �������� �� ������� ������� ����������
256
+ # ���������� �� ����������� �������.
257
+ #
258
+ def Tag.default_tag_params( params )
259
+ self.send( :define_method, :tag_default_params ) do
260
+ super.merge( params )
261
+ end
262
+ end
263
+
264
+ private
265
+ # ��������� ��� �������� �������� ��������� ����, ����������� ���
266
+ # ������ ������� child_tag � mandatory_child_tag.
267
+ #
268
+ TagChildTagInfo = Struct.new( :name, :type, :params )
269
+
270
+ # ��������������� ����� ��� ���������� child_tag � mandatory_child_tag.
271
+ #
272
+ # ������� ������ ������� � ���, ����� ��� �������� ������ �������
273
+ # ��������� ������-singleton � ������� ����� instance methods � �������
274
+ # tag_add_child_tag_info � tag_child_tags.
275
+ #
276
+ # ����� � ���, ��� ����� tag_metaclass ���������� �� ��������� ������
277
+ # Tag, �� ����� Tag ����������� �������� tag_add_child_tag_info �
278
+ # tag_child_tags. ���� �� tag_metaclass ���������� �� ���������
279
+ # ������������ �� Tag ������, �� ������������ ���������� ������������
280
+ # ������ (�.�. self ����� ��������� �� ����������� �����).
281
+ #
282
+ # ����� �������, ���� ���� ������� ������������ Tag <- First <- Second
283
+ # � � ������� First, Second ���������� ������ child_tag, ��
284
+ # � ������ First ����� ���� ������ ������-singleton � ���������� ��������
285
+ # ������ ������ First �������� �����. � � ������ Second ����� ���� ������.
286
+ #
287
+ # �������������, ������ �������� � ����, ����� � ������������ Tag �������
288
+ # �������� �� ���� �������-singleton � ������������ ������ ������
289
+ # �������� �����. ��� ����� ������������ ��� ����, ��� self � ������������
290
+ # Tag ��������� �� ���������� ����� (�.�. �� First ��� Second).
291
+ # �������������, ����� ���������, ���� �� � ���� ������ instance method
292
+ # � ������ tag_child_tags � �������� ���. ����� ���� ������� � ��������
293
+ # ������ � �.�.:
294
+ # child_tags = []
295
+ # c = self.class
296
+ # while c
297
+ # if c.respond_to?( :tag_child_tags )
298
+ # child_tags = c.tag_child_tags + child_tags
299
+ # end
300
+ # c = c.superclass
301
+ # end
302
+ #
303
+ #
304
+ # ����� ������� �������� �������� �������� �������� ����� ������������
305
+ # ��� ����, ����� ��������� ������� ������� ���������� ����� -- � �����
306
+ # ������� ���������� child_tag, � ����� ������� �������� ���� ������
307
+ # ����������� � ������������� ����.
308
+ #
309
+ def Tag.tag_metaclass
310
+ class <<self
311
+ # ���������� �������� ���������� ��������� ����.
312
+ #
313
+ # ������������ � ���������� ������� child_tag � mandatory_child_tag.
314
+ #
315
+ # ��������� ��. tag_metaclass.
316
+ def tag_add_child_tag_info( name, type, params )
317
+ @tag_child_tags ||= []
318
+ @tag_child_tags << TagChildTagInfo.new( name, type, params )
319
+ end
320
+
321
+ # ���������� ������ �������� ���� �������� �����, ����������
322
+ # � ������� ������� child_tag � mandatory_child_tag.
323
+ #
324
+ # ��������� ��. tag_metaclass.
325
+ def tag_child_tags
326
+ @tag_child_tags || []
327
+ end
328
+ end
329
+ self
330
+ end
331
+
332
+ # ���������� ������ ����������, ������� ���� �������� �
333
+ # ����������� �������� ������ � ���������� � ����������� ��-���������.
334
+ def tag_params
335
+ @tag_params
336
+ end
337
+
338
+ # ���������� ������ ���������� ���� �� ���������.
339
+ #
340
+ # ���� ������ ����� � ������������ ����������� ���� ���������� �����������
341
+ # � ��� �� ��������������� ������ ����������� ����� �������� ���
342
+ # ������������� ����.
343
+ #
344
+ # ����������� ����� ����� �������������� ������ �����, ����� ���������
345
+ # ����������� ��������� �� ���������.
346
+ #
347
+ # ��. ��� �� default_tag_params
348
+ #
349
+ # � ������� ������ ���������� ������ Hash.
350
+ #
351
+ def tag_default_params
352
+ {}
353
+ end
354
+
355
+ # �����, ������� ���������� � ������������ Tag ��� �������������
356
+ # ���� �������� �����, ��������� � ����������� ������� ��� ������
357
+ # ����������� child_tag � mandatory_child_tag.
358
+ #
359
+ # ��������� ��. tag_metaclass.
360
+ #
361
+ def tag_init_children_tags
362
+ # ������� ��������� ������ ���� �������� �����.
363
+ child_tags = []
364
+ c = self.class
365
+ while c
366
+ if c.respond_to?( :tag_child_tags )
367
+ child_tags = c.tag_child_tags + child_tags
368
+ end
369
+ c = c.superclass
370
+ end
371
+
372
+ # � ����� ��� ���� �������� ����� ���������� ���� instance variables.
373
+ child_tags.each do |info|
374
+ additional_params = { :owner => self }
375
+ additional_params[ :name ] = info.name.to_s unless
376
+ info.params.has_key?( :name )
377
+
378
+ self.instance_variable_set( "@#{info.name}".to_sym,
379
+ info.type.new( info.params.merge( additional_params ) ) )
380
+ end
381
+ end
382
+
383
+ # ��������������� �����, ������� ������� � ���������� ���� ���������
384
+ # ���� � ��������� ��������� ���� �� ��������� ������� �����.
385
+ #
386
+ # ������ ����� ��������� ��������� ���������, ��������, ������ :value,
387
+ # ����� ��� ����� ����� �� � ������������ ����������������. �������
388
+ # ������� ���� ������ �������� ���:
389
+ # def initialize( params )
390
+ # super( params )
391
+ #
392
+ # v = tag_params.fetch( :value, nil )
393
+ # if v
394
+ # ...
395
+ # tag_make_defined
396
+ # end
397
+ # end
398
+ # �������� �������� ����� � ���, ��� ����� ������ ���������� � tag_params,
399
+ # ����� �������� ������ �� ���� ����������, ������� ��������� ��-���������.
400
+ # � �������������� ������ tag_handle_opt_param ���� ��� ����� ��������� ���:
401
+ # def initialize( params )
402
+ # super( params )
403
+ #
404
+ # tag_handle_opt_param( :value ) do |v|
405
+ # ...
406
+ # tag_make_defined
407
+ # end
408
+ # end
409
+ #
410
+ # ���������� �������� �����, ���� ���� ��� ������ � ���� ��������� ���
411
+ # nil, ���� ���� ������ �� ���.
412
+ #
413
+ # :call-seq:
414
+ # tag_handle_opt_param( key ) { |value| ... }
415
+ #
416
+ def tag_handle_opt_param( key, &block )
417
+ v = tag_params.fetch( key, nil )
418
+ if v
419
+ block.call( v )
420
+ else
421
+ nil
422
+ end
423
+ end
424
+
425
+ end
426
+
427
+ end # module ClsRuby
428
+
@@ -0,0 +1,111 @@
1
+ #
2
+ # ����� ����, ������� �������� ��� ���� ���������� ��� DOM-������.
3
+ #
4
+
5
+ require 'cls-ruby/tag.rb'
6
+
7
+ module ClsRuby
8
+
9
+ # ����� ����, ������� �������� ��� ���� ���������� ��� DOM-������.
10
+ #
11
+ # ����� ������������ ��� ������, ����� ��������� ������ �������
12
+ # ���������� �������� ������ (��������, ��� ������������ ��������������
13
+ # � �������� �����) � ��� ���� �� ��������, �� ���� ������� ������� �����.
14
+ #
15
+ # ��� ����� �������������, � �������, ���� � �����-�� ������� ���������
16
+ # ����� �������� ����������� ���������� � �������. ����� ���� �������
17
+ # ���������, ����������� �� ������ ��������� �����:
18
+ # {object
19
+ # {name 'some'}
20
+ # {owner 'owner'}
21
+ # {mode 'mode'}
22
+ # }
23
+ # � ��������� �������������, ��� � ������� � ����� {name}, {owner} � {mode}
24
+ # ����� ���� �������� ����� ����� �����. ��� �����, ��� {object} �����
25
+ # �������� ��������� �������:
26
+ # class TagObject < ClsRuby::TagNoValue
27
+ # def initialize
28
+ # @name = ClsRuby::TagScalar.new( :name => 'name' ... )
29
+ # @owner = ClsRuby::TagScalar.new( :name => 'owner' ... )
30
+ # @mode = ClsRuby::TagScalar.new( :name => 'mode' ... )
31
+ # # � ��� ���� ��� ����� ��������� ��� ��������� ����������.
32
+ # @extension = ClsRuby::TagAny.new
33
+ # end
34
+ # end
35
+ #
36
+ # ����������� ����� TagAny ����� ����� �������� � ������� ������
37
+ # TagAny#content. ���� ����� ���������� ������ ��������� TagAny::TAG.
38
+ # � ���� �������, TagAny::TAG#content ���������� ���������� ���������
39
+ # ���� � ���� ������� ��������� (� ������� ����� ���� �������� �����
40
+ # TagAny::TAG, TagAny::SPACE, TagAny::NONSPACE, TagAny::STRING).
41
+ #
42
+ # ������ TagAny#content � TagAny::TAG#content ���������� �������� � ���
43
+ # ������������������, � ������� ��� ���� ��������� �� �������� ������.
44
+ #
45
+ class TagAny < Tag
46
+ # ������, ������� ��������� ����� �������� ���.
47
+ TAG = Struct.new( :name, :content )
48
+ # ������, ������� ��������� ���� �������� ���� Space.
49
+ SPACE = Struct.new( :value )
50
+ # ������, ������� ��������� ���� �������� ���� NonSpace,
51
+ NONSPACE = Struct.new( :value )
52
+ # ������, ������� ��������� ���� �������� ���� String.
53
+ STRING = Struct.new( :value )
54
+
55
+ # ������ � ����������� ����.
56
+ attr_reader :content
57
+
58
+ def initialize
59
+ super( {} )
60
+ @content = []
61
+ @stack = []
62
+ end
63
+
64
+ def tag_name;
65
+ if 0 != @stack
66
+ @stack.last.name
67
+ else
68
+ '<any>'
69
+ end
70
+ end
71
+
72
+ # ������ ���������� true.
73
+ def tag_compare_name( name ); true; end
74
+
75
+ # ������ ���������� ������ ����.
76
+ def tag_tags
77
+ [ self ]
78
+ end
79
+
80
+ # �������� ����� �������� ���.
81
+ def tag_on_start( name )
82
+ n = TAG.new( name, [] )
83
+ @stack.push( n )
84
+ end
85
+
86
+ # ��������� ��������� �������� ���.
87
+ def tag_on_finish
88
+ l = @stack.pop
89
+ if @stack.empty?
90
+ @content << l
91
+ else
92
+ @stack.last.content << l
93
+ end
94
+ end
95
+
96
+ def tag_on_tok_space( token )
97
+ @stack.last.content << SPACE.new( token )
98
+ end
99
+
100
+ def tag_on_tok_nonspace( token )
101
+ @stack.last.content << NONSPACE.new( token )
102
+ end
103
+
104
+ def tag_on_tok_string( token )
105
+ @stack.last.content << STRING.new( token )
106
+ end
107
+
108
+ end
109
+
110
+ end # module ClsRuby
111
+
@@ -0,0 +1,55 @@
1
+ #
2
+ # ����� ����, ������� �� ����� ����������� �������� � ��������
3
+ # ����������� ��� �������� �����.
4
+ #
5
+
6
+ require 'cls-ruby/tag.rb'
7
+
8
+ module ClsRuby
9
+
10
+ # ����� ����, ������� �� ��������� ������������� ������ ���� �������
11
+ # :tok_string � :tok_nonspace. �� ����� �������������� ���� � ��������
12
+ # ����-������������� (�.�. ����� ��� ���� ��� �������), ���� � ��������
13
+ # ��������� �������� �����.
14
+ #
15
+ # ��������, ��������� ������� ���������:
16
+ # {mode
17
+ # {logging} # ������� ���� ��� �������������.
18
+ # {timeout 100} # �������� ���� � ������������ ����������.
19
+ # {attempts 10}
20
+ # }
21
+ # ����� ���� �������� ����� TagNoValue ����� �������:
22
+ # class TagMode < ClsRuby::TagNoValue
23
+ # def initialize
24
+ # super( :name => 'mode', :mandatory => true, :once => true )
25
+ #
26
+ # @logging = ClsRuby::TagNoValue.new( :name => 'logging', ... )
27
+ # @timeout = ClsRuby::TagScalar.new( :name => 'timeout', ... )
28
+ # @attempts = ClsRuby::TagScalar.new( :name => 'attempts', ... )
29
+ # end
30
+ # end
31
+ #
32
+ # � ������ ��������� ���������� �������������� ����������� ��������: +:once+
33
+ # ���� ��� ����� true, �� ���� ����������� ����������� �� ������� ������
34
+ # ������ ���� ���.
35
+ #
36
+ class TagNoValue < Tag
37
+ def initialize( params = {} )
38
+ super( params )
39
+
40
+ @tag_is_once = tag_params.fetch( :once, false )
41
+ end
42
+
43
+ # ������� ���������� TagAlreadyDefinedEx, ���� ��� ��� ��� ��������
44
+ # � ��� ����� ����������� �� ������� ������ ������ ���� ���.
45
+ def tag_on_start( name )
46
+ raise TagAlreadyDefinedEx.new( "tag '#{name}' already defined" ) if
47
+ tag_defined? && @tag_is_once
48
+
49
+ super( name )
50
+ end
51
+
52
+ end
53
+
54
+ end # module ClsRuby
55
+