crapshoot 0.3.0 → 0.4.0

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