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.
- data/LICENSE +26 -0
- data/README +55 -0
- data/THANKS +0 -0
- data/docs/base_formatting_methods +89 -0
- data/docs/base_parsing_methods +79 -0
- data/docs/constructor_params +131 -0
- data/docs/examples/log_single_line_format +3 -0
- data/docs/examples/service_description +3 -0
- data/docs/examples/sms-hist +3 -0
- data/docs/examples/tag_any +3 -0
- data/docs/fragments/custom_tag_field.rb +20 -0
- data/docs/fragments/custom_tag_include.rb +21 -0
- data/docs/fragments/field.cls +2 -0
- data/docs/fragments/include.cls +4 -0
- data/docs/fragments/inherit_tag_params.rb +21 -0
- data/docs/fragments/message.cls +6 -0
- data/docs/fragments/tag_field.rb +24 -0
- data/docs/fragments/tag_message.rb +74 -0
- data/docs/fragments/tags_order.rb +41 -0
- data/docs/principles +402 -0
- data/docs/std_tags_short_description +278 -0
- data/docs/syntax +227 -0
- data/docs/why_cls +178 -0
- data/examples/hex_stream.txt +1 -0
- data/examples/log_single_line_formatter.rb +79 -0
- data/examples/service_description.day_time.cfg +11 -0
- data/examples/service_description.rb +119 -0
- data/examples/sms-hist.rb +164 -0
- data/examples/space_concat.txt +3 -0
- data/examples/tag_any.rb +28 -0
- data/lib/cls-ruby/basic_scalars.rb +270 -0
- data/lib/cls-ruby/constraints/one_of.rb +36 -0
- data/lib/cls-ruby/default_formatter.rb +50 -0
- data/lib/cls-ruby/ex.rb +121 -0
- data/lib/cls-ruby/formatter.rb +31 -0
- data/lib/cls-ruby/lexers/char_classifier.rb +157 -0
- data/lib/cls-ruby/lexers/first_stage.rb +112 -0
- data/lib/cls-ruby/lexers/lexer.rb +74 -0
- data/lib/cls-ruby/oneline_formatter.rb +35 -0
- data/lib/cls-ruby/parser.rb +249 -0
- data/lib/cls-ruby/tag.rb +428 -0
- data/lib/cls-ruby/tag_any.rb +111 -0
- data/lib/cls-ruby/tag_no_value.rb +55 -0
- data/lib/cls-ruby/tag_scalar.rb +197 -0
- data/lib/cls-ruby/tag_scalar_helpers.rb +70 -0
- data/lib/cls-ruby/tag_scalar_vector.rb +148 -0
- data/lib/cls-ruby/tag_vector_of_different_tags.rb +172 -0
- data/lib/cls-ruby/tag_vector_of_tags.rb +116 -0
- data/lib/cls-ruby/vector_of_tags_impl.rb +129 -0
- data/lib/cls-ruby.rb +5 -0
- data/tests/tc_child_tag.rb +51 -0
- data/tests/tc_constraint_one_of.rb +47 -0
- data/tests/tc_format_helper.rb +27 -0
- data/tests/tc_formatters.rb +125 -0
- data/tests/tc_lexer.rb +124 -0
- data/tests/tc_lexer_char_classifier.rb +121 -0
- data/tests/tc_lexer_first_stage.rb +72 -0
- data/tests/tc_parser_simple.rb +93 -0
- data/tests/tc_scalar_parsers.rb +189 -0
- data/tests/tc_tag.rb +68 -0
- data/tests/tc_tag_no_value.rb +46 -0
- data/tests/tc_tag_scalar_int.rb +83 -0
- data/tests/tc_tag_scalar_nonspace_string.rb +46 -0
- data/tests/tc_tag_scalar_string.rb +47 -0
- data/tests/tc_tag_scalar_vector_int.rb +88 -0
- data/tests/tc_tag_scalar_vector_string.rb +48 -0
- data/tests/tc_tag_scalar_vector_string_empty.rb +40 -0
- data/tests/tc_tag_vector_of_different_tags.rb +109 -0
- data/tests/tc_tag_vector_of_tags.rb +103 -0
- data/tests/ts_cls_ruby.rb +7 -0
- metadata +140 -0
@@ -0,0 +1,197 @@
|
|
1
|
+
#
|
2
|
+
# ����� ���� ��� �������� ��������� �������� (����� �����, ����� � �.�.).
|
3
|
+
#
|
4
|
+
|
5
|
+
require 'cls-ruby/tag'
|
6
|
+
require 'cls-ruby/basic_scalars'
|
7
|
+
require 'cls-ruby/tag_scalar_helpers'
|
8
|
+
|
9
|
+
module ClsRuby
|
10
|
+
|
11
|
+
#
|
12
|
+
# ����� ���� ��� �������� ��������� �������� � ���������� �������������
|
13
|
+
# �� ���.
|
14
|
+
#
|
15
|
+
# ����������� ������������ ��������� �������������� ����� � ���� params:
|
16
|
+
# [:format] ������, ����������� ��������� ScalarFormat. ����
|
17
|
+
# ������ ����� ����������� ��� ��� �������������� �������
|
18
|
+
# �������� ������ � �������� ������� ������������ ����.
|
19
|
+
# [:constraint] ������, ����������� ��������� ScalarChecker. ���� ������,
|
20
|
+
# ���� �� �����, ����� ����������� ��� �������� �����������
|
21
|
+
# �� �������� ������ ��������.
|
22
|
+
# [:value] �������� ����. ���� ���� �������� ������, �� ��� ����� �����������
|
23
|
+
# ������������. ������������ �������� �� ����������.
|
24
|
+
#
|
25
|
+
# ������ �������������:
|
26
|
+
# ����� ���������� ������� ��������� ���������:
|
27
|
+
# {params
|
28
|
+
# {min <int:1..100>}
|
29
|
+
# {max <int:100..1000>}
|
30
|
+
# {password <str>}
|
31
|
+
# }
|
32
|
+
#
|
33
|
+
# ��� ����� ����� ��������� ���:
|
34
|
+
# class TagParams < ClsRuby::Tag
|
35
|
+
# def initialize( params )
|
36
|
+
# super( params )
|
37
|
+
#
|
38
|
+
# @min = ClsRuby::TagScalar.new(
|
39
|
+
# :name => 'min', :owner => self, :mandatory => true,
|
40
|
+
# :format => ClsRuby::SCALAR_INT,
|
41
|
+
# :constraint => 1..100 )
|
42
|
+
# @max = ClsRuby::TagScalar.new(
|
43
|
+
# :name => 'max', :owner => self, :mandatory => true,
|
44
|
+
# :format => ClsRuby::SCALAR_INT,
|
45
|
+
# :constraint => 100..1000 )
|
46
|
+
# @password = ClsRuby::TagScalar.new(
|
47
|
+
# :name => 'password', :owner => self, :mandatory => true,
|
48
|
+
# :format => ClsRuby::SCALAR_STRING )
|
49
|
+
# end
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
# ��� ���������� �������� ������� ��������������� ������� TagScalar#value.
|
53
|
+
# ��, ���� ��� �� ��� ���������, �� TagScalar#value ��������� �������� nil.
|
54
|
+
# ��� ��������� ������ � ��������������� ������ ����� ���������������
|
55
|
+
# ������� fetch:
|
56
|
+
# || ������ ��� �������:
|
57
|
+
# || {age [{hours <uint>}] [{minutes <uint>]} [{seconds <uint>}]}
|
58
|
+
# || � ���������� � ������ value �������� � ��������.
|
59
|
+
# class TagAge < ClsRuby::TagNoValue
|
60
|
+
# child_tag :hours, ClsRuby::TagUintScalar, :constraint => 1..24
|
61
|
+
# child_tag :minutes, ClsRuby::TagUintScalar, :constraint => 1...60
|
62
|
+
# child_tag :seconds, ClsRuby::TagUintScalar, :constraint => 1...60
|
63
|
+
#
|
64
|
+
# def value
|
65
|
+
# @hours.fetch( 0 ) * 3600 +
|
66
|
+
# @minutes.fetch( 0 ) * 60 +
|
67
|
+
# @seconds.fetch( 0 )
|
68
|
+
# end
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
class TagScalar < Tag
|
72
|
+
include TagScalarHelpers::ConstraintValidator
|
73
|
+
include TagScalarHelpers::ParamsExtractor
|
74
|
+
|
75
|
+
# ������ ������������ ����� ��������.
|
76
|
+
attr_reader :value
|
77
|
+
|
78
|
+
# ����������� ��������� ���������� FormatUndefinedEx, ���� � params
|
79
|
+
# ��� ����� :format, ��� ���� ����� ����� ������������� nil.
|
80
|
+
#
|
81
|
+
def initialize( params = {} )
|
82
|
+
super( params )
|
83
|
+
|
84
|
+
tag_scalar_extract_params( tag_params )
|
85
|
+
@value = nil
|
86
|
+
|
87
|
+
v = tag_params.fetch( :value, nil )
|
88
|
+
send( :value=, v ) if v
|
89
|
+
end
|
90
|
+
|
91
|
+
# ������ ��� ������������ � �������� ���������.
|
92
|
+
#
|
93
|
+
# <b>����������</b>. �������� �� ������������ �� �����������.
|
94
|
+
def value=( value )
|
95
|
+
@value = value
|
96
|
+
tag_make_defined
|
97
|
+
self
|
98
|
+
end
|
99
|
+
|
100
|
+
# ��������������� ����� ��� ���������� �������� �� ��������������� ����.
|
101
|
+
#
|
102
|
+
# ���� ��� �� ���������, �� ���������� �������� default.
|
103
|
+
def fetch( default )
|
104
|
+
tag_defined? ? value : default
|
105
|
+
end
|
106
|
+
|
107
|
+
# ���������� ��� � ��������� ���������.
|
108
|
+
def tag_reset
|
109
|
+
@value = nil
|
110
|
+
super
|
111
|
+
end
|
112
|
+
|
113
|
+
# ��������� ���������� TagAlreadyDefinedEx, ���� ��� ��� ���������.
|
114
|
+
def tag_on_start( name )
|
115
|
+
super( name )
|
116
|
+
|
117
|
+
raise TagAlreadyDefinedEx.new( "tag '#{tag_name}' already defined" ) if
|
118
|
+
tag_defined?
|
119
|
+
end
|
120
|
+
|
121
|
+
# ��������� ���������� ValueMissedEx, ���� � ������� �������� ����
|
122
|
+
# �������� �� ���� ����������.
|
123
|
+
def tag_on_finish
|
124
|
+
raise ValueMissedEx.new(
|
125
|
+
"value missed for tag '#{tag_name}'" ) unless @value
|
126
|
+
|
127
|
+
super
|
128
|
+
end
|
129
|
+
|
130
|
+
def tag_on_tok_nonspace( token )
|
131
|
+
tag_scalar_value_must_be_nil
|
132
|
+
@value = tag_scalar_check( token, @format.on_tok_nonspace( token ) )
|
133
|
+
end
|
134
|
+
|
135
|
+
def tag_on_tok_string( token )
|
136
|
+
tag_scalar_value_must_be_nil
|
137
|
+
@value = tag_scalar_check( token, @format.on_tok_string( token ) )
|
138
|
+
end
|
139
|
+
|
140
|
+
def tag_on_format( formatter )
|
141
|
+
formatter.value( @format.format( @value ) )
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
# ��������� ���������� ValueAlreadyDefinedEx, ���� @value ������� �� nil.
|
146
|
+
def tag_scalar_value_must_be_nil
|
147
|
+
raise ValueAlreadyDefinedEx.new(
|
148
|
+
"tag '#{tag_name}' already has value '#{@value}'" ) if @value
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# ������� ����� ���� ��� �������� ����� �������� �� ������.
|
153
|
+
#
|
154
|
+
# ���:
|
155
|
+
# child_tag :min, ClsRuby::TagIntScalar
|
156
|
+
# �������� ������������:
|
157
|
+
# child_tag :min, ClsRuby::TagScalar, :format => ClsRuby::SCALAR_INT
|
158
|
+
#
|
159
|
+
class TagIntScalar < TagScalar
|
160
|
+
default_tag_params :format => SCALAR_INT
|
161
|
+
end
|
162
|
+
|
163
|
+
# ������� ����� ���� ��� �������� ����������� ����� ��������.
|
164
|
+
#
|
165
|
+
# ���:
|
166
|
+
# child_tag :min, ClsRuby::TagUintScalar
|
167
|
+
# �������� ������������:
|
168
|
+
# child_tag :min, ClsRuby::TagScalar, :format => ClsRuby::SCALAR_UINT
|
169
|
+
#
|
170
|
+
class TagUintScalar < TagScalar
|
171
|
+
default_tag_params :format => SCALAR_UINT
|
172
|
+
end
|
173
|
+
|
174
|
+
# ������� ����� ���� ��� �������� ��������� ��������.
|
175
|
+
#
|
176
|
+
# ���:
|
177
|
+
# child_tag :min, ClsRuby::TagStringScalar
|
178
|
+
# �������� ������������:
|
179
|
+
# child_tag :min, ClsRuby::TagScalar, :format => ClsRuby::SCALAR_STRING
|
180
|
+
#
|
181
|
+
class TagStringScalar < TagScalar
|
182
|
+
default_tag_params :format => SCALAR_STRING
|
183
|
+
end
|
184
|
+
|
185
|
+
# ������� ����� ���� ��� �������� ������������ ��������.
|
186
|
+
#
|
187
|
+
# ���:
|
188
|
+
# child_tag :min, ClsRuby::TagFloatScalar
|
189
|
+
# �������� ������������:
|
190
|
+
# child_tag :min, ClsRuby::TagScalar, :format => ClsRuby::SCALAR_FLOAT
|
191
|
+
#
|
192
|
+
class TagFloatScalar < TagScalar
|
193
|
+
default_tag_params :format => SCALAR_FLOAT
|
194
|
+
end
|
195
|
+
|
196
|
+
end # module ClsRuby
|
197
|
+
|
@@ -0,0 +1,70 @@
|
|
1
|
+
#
|
2
|
+
# ��������������� ������ � ������ ��� ���������� TagScalar � TagScalarVector.
|
3
|
+
#
|
4
|
+
|
5
|
+
module ClsRuby
|
6
|
+
|
7
|
+
module TagScalarHelpers
|
8
|
+
|
9
|
+
# ������, ������� ������������� ����� ��� ���������� �� Hash ����������
|
10
|
+
# ���� ������������� ��� TagScalar/TagScalarVector ���������� (�.�. :format,
|
11
|
+
# :constraint).
|
12
|
+
#
|
13
|
+
# ������ ���� �������� � ������, � ������� ���� ��������� instance variables:
|
14
|
+
# [@constraint] �������������� ������ �� ������, ����������� ScalarChecker.
|
15
|
+
# ���� � params ���� :constraint �� �����, �� ������
|
16
|
+
# ���������� �������� �������� nil.
|
17
|
+
# [@format] ������������ ������ �� ������, ����������� ��������� ScalarFormat.
|
18
|
+
#
|
19
|
+
module ParamsExtractor
|
20
|
+
# ��������� ���������� �� params �������� � ������� :format, :constraint.
|
21
|
+
#
|
22
|
+
# ��������� ���������� FormatUndefinedEx, ���� ������ ����������� ��
|
23
|
+
# ��������.
|
24
|
+
def tag_scalar_extract_params( params )
|
25
|
+
@format = params.fetch( :format, nil )
|
26
|
+
raise FormatUndefinedEx.new(
|
27
|
+
"format undefined for scalar '#{tag_name}'" ) unless @format
|
28
|
+
|
29
|
+
@constraint = params.fetch( :constraint, nil )
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# ������, ������� ������������� ����� ��� �������� ������������
|
34
|
+
# ���������� ������������ ���������� ��������.
|
35
|
+
#
|
36
|
+
# ������ ���� �������� � ������, � ������� ���� ��������� instance variables:
|
37
|
+
# [@constraint] �������������� ������ �� ������, ����������� ScalarChecker.
|
38
|
+
# �� ����� �������������� ��� �������� ������������ ������������
|
39
|
+
# �������� (���� ������� �� nil).
|
40
|
+
#
|
41
|
+
module ConstraintValidator
|
42
|
+
# ��������� �������� ���������� �������� ���������� ������.
|
43
|
+
#
|
44
|
+
# ��������� ���������� ValueParsingErrorEx, ���� _parsed_value_ ����� nil.
|
45
|
+
#
|
46
|
+
# ���� ��������� @constraint, �� ���������� �������� � ��� �������.
|
47
|
+
# ��������� ���������� InvalidValueEx, ���� ��������� �����������
|
48
|
+
# ��������.
|
49
|
+
#
|
50
|
+
# � ������ ������ ���������� parsed_value.
|
51
|
+
#
|
52
|
+
def tag_scalar_check( token, parsed_value )
|
53
|
+
raise ValueParsingErrorEx.new(
|
54
|
+
"unable to parse token '#{token}' " +
|
55
|
+
"for tag '#{tag_name}'" ) unless parsed_value
|
56
|
+
|
57
|
+
if @constraint
|
58
|
+
raise InvalidValueEx.new(
|
59
|
+
"invalid value '#{parsed_value}' for tag '#{tag_name}'" ) \
|
60
|
+
unless @constraint === parsed_value
|
61
|
+
end
|
62
|
+
|
63
|
+
parsed_value
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end # module TagScalarHelpers
|
68
|
+
|
69
|
+
end # module ClsRuby
|
70
|
+
|
@@ -0,0 +1,148 @@
|
|
1
|
+
#
|
2
|
+
# ����� ���� ��� �������� ������������������� ��������� ��������
|
3
|
+
# (����� �����, ����� � �.�.).
|
4
|
+
#
|
5
|
+
|
6
|
+
require 'cls-ruby/tag'
|
7
|
+
require 'cls-ruby/basic_scalars'
|
8
|
+
require 'cls-ruby/tag_scalar_helpers'
|
9
|
+
|
10
|
+
module ClsRuby
|
11
|
+
|
12
|
+
#
|
13
|
+
# ����� ���� ��� �������� ������������������� ��������� �������� � ����������
|
14
|
+
# ������������� �� ������ �� ���.
|
15
|
+
#
|
16
|
+
# ����������� ������������ ��������� �������������� ����� � ���� params:
|
17
|
+
# [:format] ������, ����������� ��������� ScalarFormat. ����
|
18
|
+
# ������ ����� ����������� ��� ��� �������������� �������
|
19
|
+
# �������� ������ � �������� ������� ������������ ����.
|
20
|
+
# [:constraint] ������, ����������� ��������� ScalarChecker. ���� ������,
|
21
|
+
# ���� �� �����, ����� ����������� ��� �������� �����������
|
22
|
+
# �� �������� ������ ��������.
|
23
|
+
# [:can_be_empty] true, ���� ����������� ������ ������������������ (��
|
24
|
+
# ��������� � ������������������ ������ ���� ���� �� ����
|
25
|
+
# �������).
|
26
|
+
# [:value] �������� ����. ���� ���� �������� ������, �� ��� ����� �����������
|
27
|
+
# ������������. ���������, ��� ��������� ����� Array.
|
28
|
+
# ������������ �������� �� ����������.
|
29
|
+
#
|
30
|
+
# ������ �������������:
|
31
|
+
# ����� ���������� ������� ��������� ���������:
|
32
|
+
# {params
|
33
|
+
# {init_bytes <uint:0..255>*}
|
34
|
+
# {shutdown_bytes <uint:0..255>*}
|
35
|
+
# {devices <str>+}
|
36
|
+
# }
|
37
|
+
# ��������:
|
38
|
+
# {params
|
39
|
+
# {init_bytes 0 0 254 254 0 0}
|
40
|
+
# {shutdown_bytes 0xff 0xff 0xff}
|
41
|
+
# {devices "com1" "com2" "com3" }
|
42
|
+
# }
|
43
|
+
#
|
44
|
+
# ��� ����� ����� ��������� ���:
|
45
|
+
# class TagParams < ClsRuby::Tag
|
46
|
+
# child_tag :init_bytes, ClsRuby::TagScalarVector,
|
47
|
+
# :format => ClsRuby::SCALAR_UINT,
|
48
|
+
# :constraint => 0..255,
|
49
|
+
# :can_be_empty => true
|
50
|
+
# child_tag :shutdown_bytes, ClsRuby::TagScalarVector,
|
51
|
+
# :format => ClsRuby::SCALAR_UINT,
|
52
|
+
# :constraint => 0..255,
|
53
|
+
# :can_be_empty => true
|
54
|
+
# child_tag :devices, ClsRuby::TagScalarVector,
|
55
|
+
# :format => ClsRuby::SCALAR_STRING,
|
56
|
+
# :mandatory => true
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# ��� ���������� �������� ������� ��������������� �������
|
60
|
+
# TagScalarVector#value. ��, ���� ��� �� ��� ���������, ��
|
61
|
+
# TagScalarVector#value ��������� �������� []. ��� ��������� ������ �
|
62
|
+
# ��������������� ������ ����� ��������������� ������� fetch:
|
63
|
+
# tag = ClsRuby::TagScalarVector.new( :name => 'init_bytes',
|
64
|
+
# :format => ClsRuby::SCALAR_UINT,
|
65
|
+
# :constraint => 0..255 )
|
66
|
+
# ...
|
67
|
+
# bytes = tag.fetch( [ 0, 0, 0 ] )
|
68
|
+
#
|
69
|
+
class TagScalarVector < Tag
|
70
|
+
include TagScalarHelpers::ConstraintValidator
|
71
|
+
include TagScalarHelpers::ParamsExtractor
|
72
|
+
|
73
|
+
# ������ ������������ ����� ��������.
|
74
|
+
# ������������ ������ ������, ���� �� ���� �������� �� ���� ���������.
|
75
|
+
attr_reader :value
|
76
|
+
|
77
|
+
# ����������� ��������� ���������� FormatUndefinedEx, ���� � params
|
78
|
+
# ��� ����� :format, ��� ���� ����� ����� ������������� nil.
|
79
|
+
#
|
80
|
+
def initialize( params = {} )
|
81
|
+
super( params )
|
82
|
+
|
83
|
+
tag_scalar_extract_params( tag_params )
|
84
|
+
@can_be_empty = tag_params.fetch( :can_be_empty, false )
|
85
|
+
@value = []
|
86
|
+
|
87
|
+
v = tag_params.fetch( :value, nil )
|
88
|
+
send( :value=, v ) if v
|
89
|
+
end
|
90
|
+
|
91
|
+
# ������ ��� ������������ � ��������� ����������.
|
92
|
+
#
|
93
|
+
# ������ �������� �������������.
|
94
|
+
#
|
95
|
+
# +����������+. �������� �� ������������ �� �����������.
|
96
|
+
#
|
97
|
+
# [values] ������ �������� ��� ����.
|
98
|
+
def value=( values )
|
99
|
+
@value = values
|
100
|
+
tag_make_defined
|
101
|
+
self
|
102
|
+
end
|
103
|
+
|
104
|
+
# ��������������� ����� ��� ���������� �������� �� ��������������� ����.
|
105
|
+
#
|
106
|
+
# ���� ��� �� ���������, �� ���������� �������� default.
|
107
|
+
def fetch( default )
|
108
|
+
tag_defined? ? value : default
|
109
|
+
end
|
110
|
+
|
111
|
+
def tag_reset
|
112
|
+
@value = []
|
113
|
+
super
|
114
|
+
end
|
115
|
+
|
116
|
+
# ��������� ���������� TagAlreadyDefinedEx, ���� ��� ��� ���������.
|
117
|
+
def tag_on_start( name )
|
118
|
+
super( name )
|
119
|
+
|
120
|
+
raise TagAlreadyDefinedEx.new( "tag '#{tag_name}' already defined" ) if
|
121
|
+
tag_defined?
|
122
|
+
end
|
123
|
+
|
124
|
+
# ��������� ���������� ValueMissedEx, ���� � ������� �������� ����
|
125
|
+
# �������� �� ���� ����������.
|
126
|
+
def tag_on_finish
|
127
|
+
raise ValueMissedEx.new(
|
128
|
+
"value missed for tag '#{tag_name}'" ) \
|
129
|
+
if !@can_be_empty && 0 == @value.size
|
130
|
+
|
131
|
+
super
|
132
|
+
end
|
133
|
+
|
134
|
+
def tag_on_tok_nonspace( token )
|
135
|
+
@value << tag_scalar_check( token, @format.on_tok_nonspace( token ) )
|
136
|
+
end
|
137
|
+
|
138
|
+
def tag_on_tok_string( token )
|
139
|
+
@value << tag_scalar_check( token, @format.on_tok_string( token ) )
|
140
|
+
end
|
141
|
+
|
142
|
+
def tag_on_format( formatter )
|
143
|
+
@value.each do |v| formatter.value( @format.format( v ) ) end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end # module ClsRuby
|
148
|
+
|
@@ -0,0 +1,172 @@
|
|
1
|
+
#
|
2
|
+
# �����, ������� ��������� ��������� �� ������� ������ ������������������
|
3
|
+
# ����������� �����.
|
4
|
+
#
|
5
|
+
|
6
|
+
require 'cls-ruby/ex'
|
7
|
+
require 'cls-ruby/vector_of_tags_impl'
|
8
|
+
|
9
|
+
module ClsRuby
|
10
|
+
|
11
|
+
# �����, ������� ��������� ��������� �� ������� ������ ������������������
|
12
|
+
# ����� � ������� ������� (�������� ������ �����).
|
13
|
+
#
|
14
|
+
# ��������, ���������� ����:
|
15
|
+
# {include <str>}
|
16
|
+
# {exclude <str>}
|
17
|
+
# ��� ������ � �������� ��� ������ �����:
|
18
|
+
# class Filter
|
19
|
+
# INCLUDE = 1
|
20
|
+
# EXCLUDE = 2
|
21
|
+
#
|
22
|
+
# attr_reader :type, :regex
|
23
|
+
#
|
24
|
+
# def initialize( type, regex )
|
25
|
+
# @type, @regex = type, regex
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# class TagIncludeExclude < ClsRuby::TagStringScalar
|
30
|
+
# def initialize( params = {} )
|
31
|
+
# super( params )
|
32
|
+
#
|
33
|
+
# @type = Filter::INCLUDE
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# def tag_on_start( name )
|
37
|
+
# @type = name == 'include' ? INCLUDE : EXCLUDE
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# def value
|
41
|
+
# Filter.new( @type, super )
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
#
|
45
|
+
# ����� ��������� ��������� ������� �����, � ������� ���� {include}
|
46
|
+
# � {exclude} ����� ����������� ����� ������ ����. ��������:
|
47
|
+
# {filter
|
48
|
+
# {(include|exclude) <str>}*
|
49
|
+
# }
|
50
|
+
# ������ ����� ��������� ������� �� ���������� �� ������� ������.
|
51
|
+
#
|
52
|
+
# ��� ����, ����� �������� ������������ ��� ����� ��� ��������� �����
|
53
|
+
# TagExcludeInclude ����� ��������������� ����� TagVectorOfDifferentTags:
|
54
|
+
# class TagFilter < ClsRuby::TagNoValue
|
55
|
+
# child_tag :filters, ClsRuby::TagVectorOfDifferentTags,
|
56
|
+
# :nested_tags => [
|
57
|
+
# { :name => 'include', :type => TagIncludeExclude },
|
58
|
+
# { :name => 'exclude', :type => TagIncludeExclude } ]
|
59
|
+
# ...
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# ������� ������ TagVectorOfDifferentTags ������� � ���, ���
|
63
|
+
# TagVectorOfDifferentTags ������ ���� Proxy. �� ����������� �����������
|
64
|
+
# ������� ������� ������ Tag �:
|
65
|
+
# - � ������ tag_compare_name ��������� ���������� ������ �� ����, ��������
|
66
|
+
# � ��������� :nested_tags;
|
67
|
+
# - � ������ tag_on_start ������� ��������� ��������� ������� ���� ����,
|
68
|
+
# ������� ��� ����� ���������� :type (� ����������� ���� ������� ��� �����
|
69
|
+
# TagIncludeExclude), ����� ���� ������ ������������ ��� ��������� ���;
|
70
|
+
# - ������������ ������ tag_on_tag, tag_on_tok_*, tag_tags, tag_on_finish
|
71
|
+
# ���������� ����;
|
72
|
+
# - � ������ tag_on_finish, ���� ��������� ��� ��������� � tag_on_finish
|
73
|
+
# ��� ������, ��������� ��������� ��� � ������ ����������� ���������
|
74
|
+
# �����.
|
75
|
+
#
|
76
|
+
# ����� ������� �������� ������ ������ ����������� ��������� ����� �����
|
77
|
+
# �������� � ������� ������ nested_tags:
|
78
|
+
# class TagFilter < ClsRuby::TagNoValue
|
79
|
+
# ...
|
80
|
+
# Description = Struct.new( :name, :fields )
|
81
|
+
# ...
|
82
|
+
# def filters
|
83
|
+
# @filters.nested_tags.inject( [] ) do |r, f| r << f.value; r end
|
84
|
+
# end
|
85
|
+
# end
|
86
|
+
# ��� �� ����� ��������������� ������� TagVectorOfTags#collect_values:
|
87
|
+
# def filters
|
88
|
+
# @filters.collect_values do |t| t.value end
|
89
|
+
# end
|
90
|
+
# ��� ������� TagVectorOfTags#collect_values_by:
|
91
|
+
# def filters
|
92
|
+
# filters = @filters.collect_values_by( :value )
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
class TagVectorOfDifferentTags < Tag
|
96
|
+
include VectorOfTagsImplementation
|
97
|
+
|
98
|
+
# ������ � ������ ����������� ��������� �����.
|
99
|
+
attr_reader :nested_tags
|
100
|
+
|
101
|
+
# �����������.
|
102
|
+
#
|
103
|
+
# ������������� � ����������� ������ ���������� �����:
|
104
|
+
# [:nested_tags] ���� ��������� �����. � ���� Array, ���������� ��������
|
105
|
+
# �������� Hash � ������� :name � :type.
|
106
|
+
# ������ ���� ����������� ������ �������������� � args.
|
107
|
+
#
|
108
|
+
def initialize( args = {} )
|
109
|
+
super( args )
|
110
|
+
|
111
|
+
handle_nested_tags_descriptions
|
112
|
+
|
113
|
+
@nested_tags = []
|
114
|
+
@current = nil
|
115
|
+
end
|
116
|
+
|
117
|
+
# ��������� ���������� � ����� �� ���� ��������� �����.
|
118
|
+
def tag_compare_name( name )
|
119
|
+
@names_to_types[ name ] ? true : false
|
120
|
+
end
|
121
|
+
|
122
|
+
# ������� �������� ��� ���� ����, �������� ������������� ��������� ���.
|
123
|
+
def tag_on_start( name )
|
124
|
+
type = @names_to_types[ name ]
|
125
|
+
next_tag = type.new( :name => name )
|
126
|
+
next_tag.tag_on_start( name )
|
127
|
+
@current = next_tag
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
# ����������, ������� �����������, ���� �������������� �����-����
|
132
|
+
# �������� � ��������� ��������� �����.
|
133
|
+
#
|
134
|
+
class InvalidNestedTagsEx < Ex
|
135
|
+
end
|
136
|
+
|
137
|
+
# ��������� �������� ��������� �����.
|
138
|
+
#
|
139
|
+
# ��������� ����������, ���� ���� :nested_tags � ������ ����������
|
140
|
+
# �� ������ ��� �������� ������������ ��������.
|
141
|
+
#
|
142
|
+
def handle_nested_tags_descriptions
|
143
|
+
nested_tags = tag_params.fetch( :nested_tags, nil )
|
144
|
+
raise InvalidNestedTagsEx.new(
|
145
|
+
"key :nested_tags not found!" ) unless nested_tags
|
146
|
+
|
147
|
+
# ������ ����� ���������, ��� ������ ��������� nested_tags ��������
|
148
|
+
# Hash, � ������� ���� ����� :name � :type.
|
149
|
+
#
|
150
|
+
# ������� �������� ��� ����� ��������� ����� � ��������� ���������.
|
151
|
+
names_to_types = {}
|
152
|
+
nested_tags.each do |hash|
|
153
|
+
raise InvalidNestedTagsEx.new(
|
154
|
+
"key :name missed or has no value in #{hash}" ) \
|
155
|
+
unless hash.fetch( :name, nil )
|
156
|
+
|
157
|
+
raise InvalidNestedTagsEx.new(
|
158
|
+
"key :type missed of has no value in #{hash}" ) \
|
159
|
+
unless hash.fetch( :type, nil )
|
160
|
+
|
161
|
+
names_to_types[ hash[ :name ] ] = hash[ :type ]
|
162
|
+
end
|
163
|
+
|
164
|
+
# ���� ������ �� ��������, ������ ����������� �������� �����
|
165
|
+
# ��������� � �������� ���������.
|
166
|
+
@names_to_types = names_to_types
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
end # module ClsRuby
|
171
|
+
|
172
|
+
|