casegen 2.0.0 → 3.0.0

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