crapshoot 0.3.0 → 0.4.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/.gitignore CHANGED
@@ -2,4 +2,5 @@ Gemfile.lock
2
2
  pkg
3
3
  .yardoc
4
4
  rdoc
5
- doc
5
+ doc
6
+ coverage
@@ -12,9 +12,13 @@ You might otherwise want to roll three twenty-sided dice and drop the highest, a
12
12
 
13
13
  Crapshoot.roll '3d20^+6'
14
14
 
15
- Or you might just want nine:
15
+ Or you might just want nine divided by three:
16
16
 
17
- Crapshoot.roll '9'
17
+ Crapshoot.roll '9 / 3'
18
+
19
+ Crapshoot supports addition, subtraction, multiplication, and division with correct order of operations:
20
+
21
+ Crapshoot.roll '1 + 2 * 3' # returns seven
18
22
 
19
23
  == Rolling Dice
20
24
 
@@ -27,10 +27,10 @@ class << self
27
27
  private :_scanner_trans_keys, :_scanner_trans_keys=
28
28
  end
29
29
  self._scanner_trans_keys = [
30
- 0, 0, 48, 57, 9, 45,
30
+ 0, 0, 48, 57, 9, 47,
31
31
  9, 57, 9, 57, 48,
32
32
  57, 9, 100, 9, 118,
33
- 9, 45, 0
33
+ 9, 47, 0
34
34
  ]
35
35
 
36
36
  class << self
@@ -38,8 +38,8 @@ class << self
38
38
  private :_scanner_key_spans, :_scanner_key_spans=
39
39
  end
40
40
  self._scanner_key_spans = [
41
- 0, 10, 37, 49, 49, 10, 92, 110,
42
- 37
41
+ 0, 10, 39, 49, 49, 10, 92, 110,
42
+ 39
43
43
  ]
44
44
 
45
45
  class << self
@@ -47,8 +47,8 @@ class << self
47
47
  private :_scanner_index_offsets, :_scanner_index_offsets=
48
48
  end
49
49
  self._scanner_index_offsets = [
50
- 0, 0, 11, 49, 99, 149, 160, 253,
51
- 364
50
+ 0, 0, 11, 51, 101, 151, 162, 255,
51
+ 366
52
52
  ]
53
53
 
54
54
  class << self
@@ -61,52 +61,52 @@ self._scanner_indicies = [
61
61
  1, 1, 1, 1, 1, 1, 1, 1,
62
62
  1, 1, 1, 1, 1, 1, 1, 1,
63
63
  1, 1, 2, 1, 1, 1, 1, 1,
64
- 1, 1, 1, 1, 1, 3, 1, 3,
65
- 1, 4, 4, 4, 4, 4, 1, 1,
64
+ 1, 1, 1, 1, 3, 3, 1, 3,
65
+ 1, 3, 1, 4, 4, 4, 4, 4,
66
66
  1, 1, 1, 1, 1, 1, 1, 1,
67
67
  1, 1, 1, 1, 1, 1, 1, 1,
68
- 4, 1, 1, 1, 1, 1, 1, 1,
68
+ 1, 1, 4, 1, 1, 1, 1, 1,
69
69
  1, 1, 1, 1, 1, 1, 1, 1,
70
- 5, 5, 5, 5, 5, 5, 5, 5,
71
- 5, 5, 1, 6, 6, 6, 6, 6,
70
+ 1, 1, 5, 5, 5, 5, 5, 5,
71
+ 5, 5, 5, 5, 1, 6, 6, 6,
72
+ 6, 6, 1, 1, 1, 1, 1, 1,
72
73
  1, 1, 1, 1, 1, 1, 1, 1,
74
+ 1, 1, 1, 1, 6, 1, 1, 1,
73
75
  1, 1, 1, 1, 1, 1, 1, 1,
74
- 1, 1, 6, 1, 1, 1, 1, 1,
76
+ 1, 1, 1, 1, 0, 0, 0, 0,
77
+ 0, 0, 0, 0, 0, 0, 1, 7,
78
+ 7, 7, 7, 7, 7, 7, 7, 7,
79
+ 7, 1, 8, 8, 8, 8, 8, 1,
75
80
  1, 1, 1, 1, 1, 1, 1, 1,
76
- 1, 1, 0, 0, 0, 0, 0, 0,
77
- 0, 0, 0, 0, 1, 7, 7, 7,
78
- 7, 7, 7, 7, 7, 7, 7, 1,
79
- 8, 8, 8, 8, 8, 1, 1, 1,
80
81
  1, 1, 1, 1, 1, 1, 1, 1,
81
- 1, 1, 1, 1, 1, 1, 1, 8,
82
+ 1, 8, 1, 1, 1, 1, 1, 1,
83
+ 1, 1, 1, 9, 9, 1, 9, 1,
84
+ 9, 10, 10, 10, 10, 10, 10, 10,
85
+ 10, 10, 10, 1, 1, 1, 1, 1,
82
86
  1, 1, 1, 1, 1, 1, 1, 1,
83
- 1, 1, 9, 1, 9, 1, 1, 10,
84
- 10, 10, 10, 10, 10, 10, 10, 10,
85
- 10, 1, 1, 1, 1, 1, 1, 1,
86
87
  1, 1, 1, 1, 1, 1, 1, 1,
87
88
  1, 1, 1, 1, 1, 1, 1, 1,
88
89
  1, 1, 1, 1, 1, 1, 1, 1,
90
+ 1, 1, 1, 1, 1, 11, 1, 12,
91
+ 12, 12, 12, 12, 1, 1, 1, 1,
89
92
  1, 1, 1, 1, 1, 1, 1, 1,
90
- 1, 1, 1, 11, 1, 12, 12, 12,
91
- 12, 12, 1, 1, 1, 1, 1, 1,
93
+ 1, 1, 1, 1, 1, 1, 12, 1,
92
94
  1, 1, 1, 1, 1, 1, 1, 1,
93
- 1, 1, 1, 1, 12, 1, 1, 1,
94
- 1, 1, 1, 1, 1, 1, 1, 13,
95
- 1, 13, 1, 1, 14, 14, 14, 14,
96
- 14, 14, 14, 14, 14, 14, 1, 1,
95
+ 13, 13, 1, 13, 1, 13, 14, 14,
96
+ 14, 14, 14, 14, 14, 14, 14, 14,
97
97
  1, 1, 1, 1, 1, 1, 1, 1,
98
98
  1, 1, 1, 1, 1, 1, 1, 1,
99
99
  1, 1, 1, 1, 1, 1, 1, 1,
100
100
  1, 1, 1, 1, 1, 1, 1, 1,
101
- 1, 1, 15, 1, 1, 1, 1, 1,
101
+ 1, 1, 1, 1, 15, 1, 1, 1,
102
102
  1, 1, 1, 1, 1, 1, 1, 1,
103
103
  1, 1, 1, 1, 1, 1, 1, 1,
104
- 1, 1, 15, 1, 16, 16, 16, 16,
105
- 16, 1, 1, 1, 1, 1, 1, 1,
104
+ 1, 1, 1, 1, 15, 1, 16, 16,
105
+ 16, 16, 16, 1, 1, 1, 1, 1,
106
106
  1, 1, 1, 1, 1, 1, 1, 1,
107
- 1, 1, 1, 16, 1, 1, 1, 1,
108
- 1, 1, 1, 1, 1, 1, 17, 1,
109
- 17, 1, 0
107
+ 1, 1, 1, 1, 1, 16, 1, 1,
108
+ 1, 1, 1, 1, 1, 1, 1, 17,
109
+ 17, 1, 17, 1, 17, 1, 0
110
110
  ]
111
111
 
112
112
  class << self
@@ -208,25 +208,31 @@ begin
208
208
  # line 4 "lib/crapshoot/parser/scan.rl"
209
209
  begin
210
210
  @mark_num = p end
211
+ # line 4 "lib/crapshoot/parser/scan.rl"
211
212
  when 5 then
212
213
  # line 5 "lib/crapshoot/parser/scan.rl"
213
214
  begin
214
215
  @num_stack.push atos(data[@mark_num..p-1]) end
216
+ # line 5 "lib/crapshoot/parser/scan.rl"
215
217
  when 2 then
216
218
  # line 15 "lib/crapshoot/parser/scan.rl"
217
219
  begin
218
220
  @tokens << Tokens::Arithmetic.new(data[p-1].chr) end
221
+ # line 15 "lib/crapshoot/parser/scan.rl"
219
222
  when 4 then
220
223
  # line 5 "lib/crapshoot/parser/scan.rl"
221
224
  begin
222
225
  @num_stack.push atos(data[@mark_num..p-1]) end
226
+ # line 5 "lib/crapshoot/parser/scan.rl"
223
227
  # line 7 "lib/crapshoot/parser/scan.rl"
224
228
  begin
225
229
  @tokens << Tokens::Constant.new(@num_stack.pop) end
230
+ # line 7 "lib/crapshoot/parser/scan.rl"
226
231
  when 6 then
227
232
  # line 5 "lib/crapshoot/parser/scan.rl"
228
233
  begin
229
234
  @num_stack.push atos(data[@mark_num..p-1]) end
235
+ # line 5 "lib/crapshoot/parser/scan.rl"
230
236
  # line 8 "lib/crapshoot/parser/scan.rl"
231
237
  begin
232
238
 
@@ -236,17 +242,21 @@ begin
236
242
  count = @num_stack.pop
237
243
  @tokens << Tokens::Series.new(count, sides, drop)
238
244
  end
245
+ # line 8 "lib/crapshoot/parser/scan.rl"
239
246
  when 3 then
240
247
  # line 15 "lib/crapshoot/parser/scan.rl"
241
248
  begin
242
249
  @tokens << Tokens::Arithmetic.new(data[p-1].chr) end
250
+ # line 15 "lib/crapshoot/parser/scan.rl"
243
251
  # line 4 "lib/crapshoot/parser/scan.rl"
244
252
  begin
245
253
  @mark_num = p end
254
+ # line 4 "lib/crapshoot/parser/scan.rl"
246
255
  when 7 then
247
256
  # line 17 "lib/crapshoot/parser/scan.rl"
248
257
  begin
249
258
  @drop_current = data[p-1].chr end
259
+ # line 17 "lib/crapshoot/parser/scan.rl"
250
260
  # line 8 "lib/crapshoot/parser/scan.rl"
251
261
  begin
252
262
 
@@ -256,7 +266,8 @@ begin
256
266
  count = @num_stack.pop
257
267
  @tokens << Tokens::Series.new(count, sides, drop)
258
268
  end
259
- # line 260 "lib/crapshoot/parser/scan.rb"
269
+ # line 8 "lib/crapshoot/parser/scan.rl"
270
+ # line 271 "lib/crapshoot/parser/scan.rb"
260
271
  end
261
272
  end
262
273
  end
@@ -278,13 +289,16 @@ begin
278
289
  # line 5 "lib/crapshoot/parser/scan.rl"
279
290
  begin
280
291
  @num_stack.push atos(data[@mark_num..p-1]) end
292
+ # line 5 "lib/crapshoot/parser/scan.rl"
281
293
  # line 7 "lib/crapshoot/parser/scan.rl"
282
294
  begin
283
295
  @tokens << Tokens::Constant.new(@num_stack.pop) end
296
+ # line 7 "lib/crapshoot/parser/scan.rl"
284
297
  when 6 then
285
298
  # line 5 "lib/crapshoot/parser/scan.rl"
286
299
  begin
287
300
  @num_stack.push atos(data[@mark_num..p-1]) end
301
+ # line 5 "lib/crapshoot/parser/scan.rl"
288
302
  # line 8 "lib/crapshoot/parser/scan.rl"
289
303
  begin
290
304
 
@@ -294,10 +308,12 @@ begin
294
308
  count = @num_stack.pop
295
309
  @tokens << Tokens::Series.new(count, sides, drop)
296
310
  end
311
+ # line 8 "lib/crapshoot/parser/scan.rl"
297
312
  when 7 then
298
313
  # line 17 "lib/crapshoot/parser/scan.rl"
299
314
  begin
300
315
  @drop_current = data[p-1].chr end
316
+ # line 17 "lib/crapshoot/parser/scan.rl"
301
317
  # line 8 "lib/crapshoot/parser/scan.rl"
302
318
  begin
303
319
 
@@ -307,7 +323,8 @@ begin
307
323
  count = @num_stack.pop
308
324
  @tokens << Tokens::Series.new(count, sides, drop)
309
325
  end
310
- # line 311 "lib/crapshoot/parser/scan.rb"
326
+ # line 8 "lib/crapshoot/parser/scan.rl"
327
+ # line 328 "lib/crapshoot/parser/scan.rb"
311
328
  end
312
329
  end
313
330
 
@@ -23,7 +23,7 @@
23
23
  Drop = ('^' | 'v') %drop;
24
24
  Series = Number 'd' Number Drop? %series;
25
25
 
26
- Arithmetic = ('+' | '-') %arithmetic;
26
+ Arithmetic = ('+' | '-' | '*' | '/') %arithmetic;
27
27
 
28
28
  UnaryExpression = Series | Constant;
29
29
  BinaryExpression = UnaryExpression (space* Arithmetic space* UnaryExpression)+;
@@ -1,24 +1,48 @@
1
1
  module Crapshoot
2
2
  # Translate the infix-notation tokens into postfix notation to make evaluating them easier.
3
3
  class Postfixer
4
+
5
+ # Postfixify turns the infix list of tokens from Scanner into a postfix list
6
+ # by repeatedly calling "step"
4
7
  def postfixify(infix_tokens)
5
8
  @infix_orig = infix_tokens
6
9
  @infix = @infix_orig.dup
7
10
  @postfix = []
11
+ @operator_stack = []
8
12
  until @infix.empty?
9
13
  step
10
14
  end
11
15
 
16
+ until @operator_stack.empty?
17
+ @postfix.push @operator_stack.pop
18
+ end
19
+
12
20
  return @postfix
13
21
  end
14
22
 
23
+ # step shifts an independent (Constant or Series) token to the
24
+ # postfix list, or loads a dependent (Arithmetic) token into the
25
+ # operator_stack for future postfixing.
15
26
  def step
16
27
  candidate = @infix.shift
17
- unless candidate.independent
18
- dependency = @infix.shift
19
- @postfix.push dependency
20
- end
28
+ process_independent candidate
29
+ process_operator candidate
30
+ end
31
+
32
+ def process_independent(candidate)
33
+ return unless candidate.independent
21
34
  @postfix.push candidate
22
35
  end
36
+
37
+ def process_operator(candidate)
38
+ return if candidate.independent
39
+
40
+ if @operator_stack.empty? || candidate.precedent(@operator_stack.last)
41
+ @operator_stack.push candidate
42
+ else
43
+ @postfix.push @operator_stack.pop
44
+ @operator_stack.push candidate
45
+ end
46
+ end
23
47
  end
24
48
  end
@@ -9,6 +9,15 @@ module Crapshoot
9
9
  false
10
10
  end
11
11
 
12
+ def precedent(stack_top)
13
+ return true if high_priority? && !stack_top.high_priority?
14
+ return false
15
+ end
16
+
17
+ def high_priority?
18
+ @operation == '*' || @operation == '/'
19
+ end
20
+
12
21
  def eval(stack)
13
22
  r = stack.pop
14
23
  l = stack.pop
@@ -4,6 +4,9 @@ module Crapshoot
4
4
  def independent
5
5
  true
6
6
  end
7
+ def precedent(stack_top)
8
+ true
9
+ end
7
10
  end
8
11
  end
9
12
  end
@@ -1,3 +1,3 @@
1
1
  module Crapshoot
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -27,6 +27,13 @@ class TestCrapshoot < Test::Unit::TestCase
27
27
  should_roll '10-5', '=='=>5
28
28
  should_roll '5-10', '=='=>-5
29
29
 
30
+ should_roll '2*5', '=='=>10
31
+ should_roll '10/2', '=='=>5
32
+ should_roll '1 + 2 * 3', '=='=>7
33
+ should_roll '4 * 5 + 6', '=='=>26
34
+ should_roll '4 * 5 / 10', '=='=>2
35
+ should_roll '2 * 3 + 4 * 5 + 10 + 10 * 8 / 2', '=='=>76
36
+
30
37
  should_describe '1 + 2', '1+2'
31
38
  should_describe '10 - 5', '10-5'
32
39
  should_describe '2d6', /\(\d\+\d\)/
@@ -14,9 +14,11 @@ class TestPostfixer < Test::Unit::TestCase
14
14
  end
15
15
 
16
16
  five = Constant.new '5'
17
+ six = Constant.new '6'
18
+ seven = Constant.new '7'
17
19
  plus = Arithmetic.new '+'
18
20
  minus = Arithmetic.new '-'
19
- six = Constant.new '6'
21
+ times = Arithmetic.new '*'
20
22
  series1 = Series.new '5', '6', nil
21
23
  series2 = Series.new '4', '20', 'v'
22
24
 
@@ -24,5 +26,7 @@ class TestPostfixer < Test::Unit::TestCase
24
26
  [five, six, plus])
25
27
  should_postfixify([series1, plus, six, minus, series2],
26
28
  [series1, six, plus, series2, minus])
29
+ should_postfixify([five, plus, six, times, seven],
30
+ [five, six, seven, times, plus])
27
31
  end
28
32
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 3
7
+ - 4
8
8
  - 0
9
- version: 0.3.0
9
+ version: 0.4.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Bryce Kerley
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-01-12 00:00:00 -05:00
17
+ date: 2011-01-12 00:00:00 +00:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency