casegen 2.0.0 → 3.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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/.rubocop.yml +109 -0
  4. data/.ruby-version +1 -1
  5. data/Gemfile +3 -1
  6. data/Gemfile.lock +51 -6
  7. data/README.md +10 -119
  8. data/Rakefile +9 -7
  9. data/bin/casegen +2 -1
  10. data/casegen.gemspec +13 -9
  11. data/doc/bounding_box.rb +37 -0
  12. data/doc/cart.rb +43 -0
  13. data/doc/expect_only.rb +28 -0
  14. data/doc/pricing.rb +50 -0
  15. data/doc/ruby_array.rb +41 -0
  16. data/lib/case_gen/combination.rb +38 -0
  17. data/lib/case_gen/combo_matcher.rb +15 -0
  18. data/lib/case_gen/exclude_rule.rb +50 -0
  19. data/lib/case_gen/expect_rule.rb +24 -0
  20. data/lib/case_gen/generator.rb +40 -0
  21. data/lib/case_gen/output/exclude.rb +6 -0
  22. data/lib/case_gen/output/exclude_as_table.rb +13 -0
  23. data/lib/case_gen/output/exclude_as_text.rb +12 -0
  24. data/lib/case_gen/output/exclude_inline.rb +13 -0
  25. data/lib/case_gen/output/exclude_inline_footnotes.rb +20 -0
  26. data/lib/case_gen/output.rb +66 -0
  27. data/lib/case_gen/rule_description.rb +11 -0
  28. data/lib/case_gen/set.rb +16 -0
  29. data/lib/casegen.rb +15 -183
  30. data/spec/cart_sample_spec.rb +46 -0
  31. data/spec/case_gen/combination_spec.rb +11 -0
  32. data/spec/case_gen/exclude_rule_spec.rb +17 -0
  33. data/spec/exclude_as_table_spec.rb +39 -0
  34. data/spec/exclude_as_text_spec.rb +58 -0
  35. data/spec/exclude_inline_footnotes_spec.rb +58 -0
  36. data/spec/exclude_inline_spec.rb +50 -0
  37. data/spec/expect_only_spec.rb +30 -0
  38. data/spec/spec_helper.rb +113 -0
  39. metadata +101 -35
  40. data/.idea/encodings.xml +0 -5
  41. data/.idea/misc.xml +0 -5
  42. data/.idea/modules.xml +0 -9
  43. data/.idea/vcs.xml +0 -7
  44. data/doc/calc.sample.txt +0 -13
  45. data/doc/cart.sample.rb +0 -3
  46. data/doc/cart.sample.txt +0 -33
  47. data/doc/ruby_array.sample.rb +0 -26
  48. data/lib/agents/sets/enum/by.rb +0 -244
  49. data/lib/agents/sets/enum/cluster.rb +0 -164
  50. data/lib/agents/sets/enum/inject.rb +0 -50
  51. data/lib/agents/sets/enum/nest.rb +0 -117
  52. data/lib/agents/sets/enum/op.rb +0 -283
  53. data/lib/agents/sets/enum/pipe.rb +0 -160
  54. data/lib/agents/sets/enum/tree.rb +0 -442
  55. data/lib/agents/sets.rb +0 -313
  56. data/test/agents/console_output_test.rb +0 -27
  57. data/test/agents/sets.test.rb +0 -227
  58. data/test/agents_test.rb +0 -41
  59. data/test/casegen.tests.rb +0 -0
  60. data/test/parser_test.rb +0 -163
  61. data/test/test_helper.rb +0 -2
@@ -1,117 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- module Enumerable
4
-
5
- def nest(&compare)
6
- ary = to_a
7
- s = ary.size
8
- i = 0
9
-
10
- # wrap into Array::Iterator?
11
- items_left = proc { i < s }
12
- get_cur = proc { ary[i] }
13
- go_next = proc { i += 1 }
14
-
15
- result = nil
16
- while items_left[]
17
- level_ary = Enumerable.nest items_left, get_cur, go_next, compare
18
- result = result ? level_ary.unshift(result) : level_ary
19
- end
20
- result || []
21
- end
22
-
23
- # Handles a single level, recursing when the depth increases and
24
- # backing out when the depth decreases.
25
- def Enumerable.nest items_left, get_cur, go_next, compare
26
- # should handle compare.arity == 2 like a <=> proc
27
- result = []; item = depth = nil
28
- while items_left[]
29
- item = get_cur[]
30
- depth = compare[item]
31
- base_depth ||= depth
32
-
33
- if depth < base_depth
34
- break
35
- elsif depth > base_depth
36
- result << nest(items_left, get_cur, go_next, compare)
37
- else
38
- result << item; go_next[]
39
- end
40
- end
41
- return result
42
- end
43
-
44
- def group(&test)
45
- nest { |x| test[x] ? 1 : 0 }
46
- end
47
- end
48
-
49
- =begin
50
-
51
- =module Enumerable
52
- ==instance methods
53
- ---Enumerable#nest &compare
54
-
55
- (({nest})) is an inverse for (({Array#flatten})). (Well, actually only a right
56
- inverse since (({flatten})) is not injective.) You give it a proc that
57
- calculates the depth of each item, and it returns a nesting of arrays in which
58
- each item has the desired depth. It can be used to parse strings with
59
- Python-like indentation syntax, but it isn't limited to strings.
60
-
61
- The main improvement in this version is that the compare block can return
62
- a lower value for an element after the first, with the expected effect. See the first example at the end of the source file.
63
-
64
- ===version
65
-
66
- Enumerable tools 1.6
67
-
68
- The current version of this software can be found at
69
- ((<"http://redshift.sourceforge.net/enum
70
- "|URL:http://redshift.sourceforge.net/enum>)).
71
-
72
- ===license
73
- This software is distributed under the Ruby license.
74
- See ((<"http://www.ruby-lang.org"|URL:http://www.ruby-lang.org>)).
75
-
76
- ===author
77
- Joel VanderWerf,
78
- ((<vjoel@users.sourceforge.net|URL:mailto:vjoel@users.sourceforge.net>))
79
-
80
- =end
81
-
82
- if __FILE__ == $0
83
-
84
- str = <<END
85
- a
86
- aa
87
- ab
88
- aba
89
- abb
90
- abba
91
- abbaa
92
- abbb
93
- ac
94
- ad
95
- ada
96
- adaa
97
- adb
98
- b
99
- ba
100
- bb
101
- c
102
- ca
103
- X
104
- Y
105
- Z
106
- END
107
-
108
- lines = str.split "\n"
109
- nested = lines.nest { |line| /\S/ =~ line }
110
- p nested
111
- flat = nested.flatten
112
- p flat
113
- p flat == lines
114
-
115
- p [1, 2, "three", "four", 5, "six"].group { |x| x.is_a? String }
116
-
117
- end
@@ -1,283 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'enum/inject'
4
-
5
- module EnumerableOperator
6
-
7
- class Product
8
- include Enumerable
9
-
10
- attr_reader :factors, :dim
11
-
12
- def initialize(*factors)
13
- @factors = factors
14
- @dim = @factors.length
15
- end
16
-
17
- def each tuple = [nil]*@dim, i = 0, &block
18
- if i == @dim - 1 then
19
- @factors[i].each { |x| tuple[i] = x; yield tuple.dup }
20
- elsif i > 0
21
- @factors[i].each { |x| tuple[i] = x; each tuple, i + 1, &block }
22
- else
23
- @factors[i].each { |x| tuple[i] = x; each tuple, i + 1, &block }
24
- self
25
- end
26
- end
27
-
28
- def size
29
- @factors.product { |enum| enum.size }
30
- end
31
-
32
- end
33
-
34
- class Sum
35
- include Enumerable
36
-
37
- attr_reader :summands
38
-
39
- def initialize(*summands)
40
- @summands = summands
41
- end
42
-
43
- def each(&block)
44
- @summands.each { |enum| enum.each(&block) }
45
- self
46
- end
47
-
48
- def size
49
- @summands.sum { |enum| enum.size }
50
- end
51
-
52
- end
53
-
54
- class Diagonal
55
- include Enumerable
56
-
57
- attr_reader :factors, :dim
58
-
59
- def initialize(*factors)
60
- @factors = factors
61
- @dim = @factors.length
62
- end
63
-
64
- def each
65
- factors = @factors.map { |factor|
66
- if factor.kind_of? Array then factor else factor.entries end
67
- }
68
- minlength = factors.min { |f, g| f.length <=> g.length }.length
69
- for i in 0..(minlength-1)
70
- yield factors.map { |factor| factor[i] }
71
- end
72
- self
73
- end
74
- end
75
-
76
-
77
- def product(*factors, &block)
78
- if block
79
- Product.new(*factors).each(&block)
80
- else
81
- Product.new(*factors)
82
- end
83
- end
84
- alias :tuples :product
85
-
86
- def sum(*summands, &block)
87
- if block
88
- Sum.new(*summands).each(&block)
89
- else
90
- Sum.new(*summands)
91
- end
92
- end
93
- alias :concatenation :sum
94
- alias :cat :sum
95
-
96
- def diagonal(*factors, &block)
97
- if block
98
- Diagonal.new(*factors).each(&block)
99
- else
100
- Diagonal.new(*factors)
101
- end
102
- end
103
-
104
- module_function :product, :sum, :diagonal
105
- end
106
-
107
- =begin
108
-
109
- ==module EnumerableOperator
110
- ===instance methods and module methods
111
- ---EnumerableOperator#product *factors, &block
112
- ---EnumerableOperator#sum *summands, &block
113
-
114
- The (({product})) operator iterates over the Cartesian product of the factors,
115
- each of which must be (({Enumerable})).
116
-
117
- The (({sum})) operator iterates over the concatenation of the summands, each of
118
- which must be (({Enumerable})).
119
-
120
- Both operators have aliases: (({tuples})) for (({product}));
121
- (({concatenation})) and (({cat})) for (({sum})).
122
-
123
- Called with a block, the operators yield one element of the sequence at a time
124
- to the block.
125
-
126
- With or without a block, the operators return an (({Enumerable})) which
127
- delegates to the original (({Enumerables})), but does not explicitly construct
128
- the entire collection. Calling another (({Enumerable})) method, such as
129
- (({select})) or (({collect})), on this return value is an efficient way of
130
- chaining these operators with other methods. Simply call (({entries})) to get
131
- the whole collection. Also, because the operators return an (({Enumerable})),
132
- they can be used with the (({for})) syntax; see the examples.
133
-
134
- ---EnumerableOperator#diagonal *factors, &block
135
-
136
- The (({diagonal})) operator iterates over the diagonal of the Cartesian product
137
- of the factors, each of which must be (({Enumerable})). In other words, the
138
- n-th entry of the diagonal is an array of the n-th entries of each factor. The
139
- resulting sequence terminates when any one factor terminates. Hence the
140
- sequence has the same length as the shortest factor.
141
-
142
- Called with a block, (({diagonal})) yields one element of the sequence at a
143
- time to the block.
144
-
145
- With or without a block, (({diagonal})) returns an (({Enumerable})) object
146
- which is ((*independent*)) of the original (({Enumerables})). As with
147
- (({product})) and (({sum})), this allows chaining with other iterators and
148
- using the (({for})) syntax. Unlike (({product})) and (({sum})), however, the
149
- entire collection is generated and stored in the object returned by
150
- (({diagonal})).
151
-
152
- Internally, (({diagonal})) does not enumerate the sequences in parallel, but in
153
- the order in which they are given. If the sequences have side-effects of
154
- enumeration, this may result in different behavior than if the sequences were
155
- truly enumerated in parallel (e.g., see matz's approach using threads in the
156
- Ruby FAQ: ((<"http://www.rubycentral.com/faq/rubyfaq-5.html#ss5.5
157
- "|URL:http://www.rubycentral.com/faq/rubyfaq-5.html#ss5.5>))).
158
-
159
- ===usage
160
-
161
- include EnumerableOperator
162
- diagonal enum0, enum1, ...
163
- or
164
- EnumerableOperator.diagonal enum0, enum1, ...
165
- and similarly for product and sum.
166
-
167
- ===examples
168
-
169
- require 'enum/op'
170
- include EnumerableOperator
171
-
172
- # using the 'for ... in ... end' construct:
173
- for i, j in product 1..4, "bar".."baz"
174
- printf "%6s", i.to_s + j; puts if j == "baz"
175
- end
176
- puts
177
-
178
- # prints:
179
- # 1bar 1bas 1bat 1bau 1bav 1baw 1bax 1bay 1baz
180
- # 2bar 2bas 2bat 2bau 2bav 2baw 2bax 2bay 2baz
181
- # 3bar 3bas 3bat 3bau 3bav 3baw 3bax 3bay 3baz
182
-
183
- # directly passing a block:
184
- sum 1..5, 'a'..'c', 90..92 do |i|
185
- printf "%4s", i.to_s
186
- end
187
- puts "\n\n"
188
-
189
- # prints:
190
- # 1 2 3 4 5 a b c 90 91 92
191
-
192
- for i, j, k in diagonal 1..4, 'a'..'d', ?a..?d
193
- printf "%4d. %s is 0x%x\n", i, j, k
194
- end
195
- puts
196
-
197
- # prints:
198
- # 1. a is 0x61
199
- # 2. b is 0x62
200
- # 3. c is 0x63
201
- # 4. d is 0x64
202
-
203
- # chaining with other iterators:
204
- names = %w{ Ludwig Rudolf Bertrand Willard }
205
- more_names = %w{ Jean-Paul Albert Martin Soren }
206
- puts sum(names, more_names).sort.join ', '
207
- puts
208
-
209
- # prints:
210
- # Albert, Bertrand, Jean-Paul, Ludwig, Martin, Rudolf, Soren, Willard
211
-
212
- # note that chaining avoids constructing the intermediate collection:
213
- big_product = product 1..10, 1..10, 1..10
214
- big_product.select { |x, y, z|
215
- x <= y and x**2 + y**2 == z**2
216
- }.each { |x, y, z|
217
- printf "#{x}**2 + #{y}**2 == #{z}**2\n"
218
- }
219
-
220
- # prints:
221
- # 3**2 + 4**2 == 5**2
222
- # 6**2 + 8**2 == 10**2
223
-
224
- ==version
225
-
226
- Enumerable tools 1.6
227
-
228
- The current version of this software can be found at
229
- ((<"http://redshift.sourceforge.net/enum
230
- "|URL:http://redshift.sourceforge.net/enum>)).
231
-
232
- ==license
233
- This software is distributed under the Ruby license.
234
- See ((<"http://www.ruby-lang.org"|URL:http://www.ruby-lang.org>)).
235
-
236
- ==author
237
- Joel VanderWerf,
238
- ((<vjoel@users.sourceforge.net|URL:mailto:vjoel@users.sourceforge.net>))
239
-
240
- =end
241
-
242
-
243
- if __FILE__ == $0
244
-
245
- include EnumerableOperator
246
-
247
- # using the 'for ... in ... end' construct:
248
- for i, j in product 1..4, "bar".."baz"
249
- printf "%6s", i.to_s + j; puts if j == "baz"
250
- end
251
- puts
252
-
253
- # directly passing a block:
254
- sum 1..5, 'a'..'c', 90..92 do |i|
255
- printf "%4s", i.to_s
256
- end
257
- puts "\n\n"
258
-
259
- for i, j, k in diagonal 1..4, 'a'..'d', ?a..?d
260
- printf "%4d. %s is 0x%x\n", i, j, k
261
- end
262
- puts
263
-
264
- # chaining with other iterators:
265
- names = %w{ Ludwig Rudolf Bertrand Willard }
266
- more_names = %w{ Jean-Paul Albert Martin Soren }
267
- puts sum(names, more_names).sort.join(', ')
268
- puts
269
-
270
- # note that chaining avoids constructing the intermediate collection:
271
- big_product = product 1..10, 1..10, 1..10
272
- big_product.select { |x, y, z|
273
- x <= y and x**2 + y**2 == z**2
274
- }.each { |x, y, z|
275
- printf "#{x}**2 + #{y}**2 == #{z}**2\n"
276
- }
277
- puts
278
-
279
- # size
280
- puts "sum(1..10,11..20).size = #{sum(1..10,11..20).size}"
281
- puts "product(1..10,11..20).size = #{product(1..10,11..20).size}"
282
- puts "product([1,2,3],[]).size = #{product([1,2,3],[]).size}"
283
- end
@@ -1,160 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- module Enumerable
4
-
5
- class Pipe
6
- include Enumerable
7
-
8
- attr_reader :enum, :filter_name, :filter_map, :args
9
-
10
- def initialize enum, filter_spec = nil, *args, &filter_proc
11
- @enum = enum
12
- @args = args
13
-
14
- case filter_spec
15
- when Symbol
16
- @filter_name = filter_spec
17
- when String
18
- @filter_name = filter_spec.intern
19
- when nil
20
- @filter_map = filter_proc
21
- else
22
- unless filter_spec.respond_to? :[]
23
- raise ArgumentError,
24
- "filter_spec must be a method name or respond to []."
25
- end
26
- @filter_map = filter_spec
27
- end
28
-
29
- unless @filter_name or @filter_map
30
- raise ArgumentError,
31
- "no filter specified."
32
- end
33
- end
34
-
35
- def each
36
- if @filter_name
37
- filter_name = @filter_name
38
- message = filter_name, *@args
39
- @enum.each { |entry|
40
- yield entry.send *message
41
- }
42
- elsif @filter_map
43
- filter_map = @filter_map
44
- args = *@args
45
- @enum.each { |entry|
46
- yield filter_map[entry, *args]
47
- }
48
- end
49
- end
50
-
51
- self
52
- end
53
-
54
- def pipe filter_spec = nil, *args, &filter_proc
55
- Pipe.new self, filter_spec, *args, &filter_proc
56
- end
57
-
58
- end
59
-
60
-
61
- =begin
62
-
63
- ==class Enumerable
64
- ===instance method
65
- ---Enumerable#pipe filter_spec = nil, *args, &filter_proc
66
-
67
- Can be used to "pipe" an (({Enumerable})) sequence through a filter.
68
-
69
- (({Enumerable#pipe})) returns an (({Enumerable})) object whose (({each}))
70
- method iterates over (({self})) and applies a filter to each enumerated
71
- object, as specified by the arguments. Only the current element of the
72
- sequence is kept in memory.
73
-
74
- If (({filter_spec})) is a string or symbol, (({filter_proc})) is ignored
75
- and (({filter_spec})) is treated as a method name. This method name is
76
- sent, along with arguments (({args})), to each element of the sequence
77
- being enumerated.
78
-
79
- If (({filter_spec})) is anything else, except (({nil})), (({filter_proc}))
80
- is ignored and (({filter_spec})) is required to be an object that responds
81
- to (({[]})), such as a proc or a hash. The (({[]})) method of
82
- (({filter_spec})) is called with each element of the sequence in turn as
83
- an argument, along with (({args})).
84
-
85
- If (({next_spec})) is not given, or is (({nil})), a block is required. In
86
- this case, iteration proceeds as in the preceding paragraph.
87
-
88
- Using (({#pipe})) has potential performance advantages. The iteration
89
-
90
- e.collect { |x| x.m }.each { |y| ... }
91
-
92
- can be rewritten as
93
-
94
- e.pipe(:m).each { |y| ... }
95
-
96
- which doesn't generate an intermediate array, and uses a send instead of a
97
- proc call. Of course, it could also be written as
98
-
99
- e.each { |x| y = x.m ... }
100
-
101
- but that may be undesirable for readability or because the block is to be
102
- taken from a proc contained in a variable:
103
-
104
- pr = proc { ... }
105
- e.pipe(:m).each &pr
106
-
107
- Also, chains of (({collect})) and (({select})), such as
108
-
109
- (1..100).collect { |x| x**2 }.select { |y| y > 1000 && y < 2000 }
110
-
111
- can't be easily rewritten as a single (({select})).
112
-
113
- ===examples
114
-
115
- require 'enum/pipe'
116
-
117
- [0,1,2,3,4].pipe { |x| x + 1 }.each { |x|
118
- print x, " "
119
- }
120
-
121
- # prints: 1 2 3 4 5
122
-
123
- stooges = ['lARRY', 'cURLY', 'mOE']
124
- p stooges.pipe(:swapcase).reject { |x| x =~ /url/ }
125
- p stooges.pipe(:tr, 'RlcOEL', 'gBboog').pipe(:capitalize).entries
126
-
127
- # prints: ["Larry", "Moe"]
128
- # ["Baggy", "Buggy", "Moo"]
129
-
130
- ==version
131
-
132
- Enumerable tools 1.6
133
-
134
- The current version of this software can be found at
135
- ((<"http://redshift.sourceforge.net/enum
136
- "|URL:http://redshift.sourceforge.net/enum>)).
137
-
138
- ==license
139
- This software is distributed under the Ruby license.
140
- See ((<"http://www.ruby-lang.org"|URL:http://www.ruby-lang.org>)).
141
-
142
- ==author
143
- Joel VanderWerf,
144
- ((<vjoel@users.sourceforge.net|URL:mailto:vjoel@users.sourceforge.net>))
145
-
146
- =end
147
-
148
-
149
- if __FILE__ == $0
150
-
151
- [0,1,2,3,4].pipe { |x| x + 1 }.each { |x|
152
- print x, " "
153
- }
154
- puts
155
-
156
- stooges = ['lARRY', 'cURLY', 'mOE']
157
- p stooges.pipe(:swapcase).reject { |x| x =~ /url/ }
158
- p stooges.pipe(:tr, 'RlcOEL', 'gBboog').pipe(:capitalize).entries
159
-
160
- end