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 +2 -1
- data/README.rdoc +6 -2
- data/lib/crapshoot/parser/scan.rb +51 -34
- data/lib/crapshoot/parser/scan.rl +1 -1
- data/lib/crapshoot/postfixer.rb +28 -4
- data/lib/crapshoot/tokens/arithmetic.rb +9 -0
- data/lib/crapshoot/tokens/base.rb +3 -0
- data/lib/crapshoot/version.rb +1 -1
- data/test/crapshoot_test.rb +7 -0
- data/test/postfixer_test.rb +5 -1
- metadata +3 -3
data/.gitignore
CHANGED
data/README.rdoc
CHANGED
@@ -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,
|
30
|
+
0, 0, 48, 57, 9, 47,
|
31
31
|
9, 57, 9, 57, 48,
|
32
32
|
57, 9, 100, 9, 118,
|
33
|
-
9,
|
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,
|
42
|
-
|
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,
|
51
|
-
|
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,
|
65
|
-
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
|
-
|
68
|
+
1, 1, 4, 1, 1, 1, 1, 1,
|
69
69
|
1, 1, 1, 1, 1, 1, 1, 1,
|
70
|
-
|
71
|
-
5, 5,
|
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,
|
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,
|
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,
|
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
|
-
|
94
|
-
|
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,
|
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,
|
105
|
-
16,
|
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,
|
108
|
-
1, 1, 1, 1, 1, 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
|
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
|
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)+;
|
data/lib/crapshoot/postfixer.rb
CHANGED
@@ -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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
data/lib/crapshoot/version.rb
CHANGED
data/test/crapshoot_test.rb
CHANGED
@@ -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\)/
|
data/test/postfixer_test.rb
CHANGED
@@ -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
|
-
|
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
|
-
-
|
7
|
+
- 4
|
8
8
|
- 0
|
9
|
-
version: 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
|
17
|
+
date: 2011-01-12 00:00:00 +00:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|