rpg_lib 1.0.0 → 1.0.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d34b6d848dfd8d8f76606d2ff2da3e4db758349f
4
- data.tar.gz: 92897b0065a31f7c747b0806a9be0ec7a0d8b99d
3
+ metadata.gz: 136dbff71bbb97184c6835b956e5cc79a3578142
4
+ data.tar.gz: 356ce85a68d6f9a03d87335452dd6293bd8453d3
5
5
  SHA512:
6
- metadata.gz: 5cc706792314e57fc3a7612194b215a4f8e9b6c02aef932c8150e26b0d836589830c28d2292ab9335877058df7da9ad7a49fd8d68576d805fa45577e6e058d14
7
- data.tar.gz: 035d42799027fdadcafdb903d7c4ab8a7355cb05bb0d0ec49e54ca62e3271bd68bbc319aad6598f080c8a4331ec653484fd093cf9350e12dddd14445b698537b
6
+ metadata.gz: 7ed15287c7b7c90cdd89cf6f50e98591be19ac72ab74fc4cec1d999e775e6258daa2b59178da775c7ace7b89a5c30382ab823900d9fe27c65925c26ee7184df1
7
+ data.tar.gz: '08bd9248297bd14ed7226d391df5cc46a8712ac3d2ad6806c615f3a43f2e8c82b0d1977c30363a960d5a227c0f8e3c87cc066451f6165eab930ffe229703b155'
data/.gitignore CHANGED
@@ -1 +1,3 @@
1
1
  /coverage
2
+ /pkg
3
+ *.swp
data/.rubocop.yml CHANGED
@@ -1,3 +1,7 @@
1
+ AllCops:
2
+ Exclude:
3
+ - 'lib/rpg_lib/parser/dice_expression_parser.rb'
4
+
1
5
  Metrics/LineLength:
2
6
  Enabled: false
3
7
  Metrics/ModuleLength:
data/Gemfile CHANGED
@@ -1,3 +1,20 @@
1
+ # Copyright 2017 Jamie Hale
2
+ #
3
+ # This file is part of the RpgLib gem.
4
+ #
5
+ # RpgLib is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # RpgLib is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with RpgLib. If not, see <http://www.gnu.org/licenses/>.
17
+
1
18
  source 'https://rubygems.org'
2
19
 
3
20
  gemspec
data/Gemfile.lock CHANGED
@@ -2,6 +2,7 @@ PATH
2
2
  remote: .
3
3
  specs:
4
4
  rpg_lib (1.0.0)
5
+ treetop (~> 1.6)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
@@ -12,6 +13,7 @@ GEM
12
13
  json (2.0.3)
13
14
  parser (2.4.0.0)
14
15
  ast (~> 2.2)
16
+ polyglot (0.3.5)
15
17
  powerpack (0.1.1)
16
18
  rainbow (2.2.1)
17
19
  rake (12.0.0)
@@ -40,6 +42,8 @@ GEM
40
42
  json (>= 1.8, < 3)
41
43
  simplecov-html (~> 0.10.0)
42
44
  simplecov-html (0.10.0)
45
+ treetop (1.6.8)
46
+ polyglot (~> 0.3)
43
47
  unicode-display_width (1.1.3)
44
48
 
45
49
  PLATFORMS
data/Rakefile CHANGED
@@ -26,3 +26,7 @@ task default: :spec
26
26
  task :rubocop do
27
27
  sh 'bundle exec rubocop'
28
28
  end
29
+
30
+ task :treetop do
31
+ sh 'tt --force --output lib/rpg_lib/parser/dice_expression_parser.rb grammar/dice_expression.treetop'
32
+ end
@@ -0,0 +1,95 @@
1
+ module RpgLib
2
+ module Parser
3
+ # :nocov:
4
+ grammar DiceExpression
5
+ rule additive
6
+ head:multitive
7
+ tail:(
8
+ space operator:additive_op
9
+ space operand:multitive)* <BinaryOperation>
10
+ end
11
+
12
+ rule additive_op
13
+ '+' {
14
+ def apply(a, b)
15
+ a + b
16
+ end
17
+ }
18
+ /
19
+ '-' {
20
+ def apply(a, b)
21
+ a - b
22
+ end
23
+ }
24
+ end
25
+
26
+ rule multitive
27
+ head:primary
28
+ tail:(
29
+ space operator:multitive_op
30
+ space operand:primary)* <BinaryOperation>
31
+ end
32
+
33
+ rule multitive_op
34
+ '*' {
35
+ def apply(a, b)
36
+ a * b
37
+ end
38
+ }
39
+ /
40
+ '/' {
41
+ def apply(a, b)
42
+ a / b
43
+ end
44
+ }
45
+ end
46
+
47
+ rule primary
48
+ dice
49
+ /
50
+ number
51
+ /
52
+ '(' space additive space ')' {
53
+ def eval(roller)
54
+ additive.eval(roller)
55
+ end
56
+ }
57
+ end
58
+
59
+ rule number
60
+ ('-'? [1-9] [0-9]* / '0' ) {
61
+ def eval(_roller)
62
+ text_value.to_i
63
+ end
64
+ }
65
+ end
66
+
67
+ rule positive_integer
68
+ ([1-9] [0-9]*) {
69
+ def eval(_roller)
70
+ text_value.to_i
71
+ end
72
+ }
73
+ end
74
+
75
+ rule dice
76
+ count:positive_integer? 'd' sides:positive_integer {
77
+ def eval(roller)
78
+ die_count = count.empty? ? 1 : count.eval(nil)
79
+ die_sides = sides.eval(nil)
80
+ rolls = []
81
+ die_count.times do
82
+ rolls << roller.roll(die_sides)
83
+ end
84
+ rolls.inject(&:+)
85
+ end
86
+ }
87
+ end
88
+
89
+ rule space
90
+ ' '*
91
+ end
92
+ end
93
+ # :nocov:
94
+ end
95
+ end
data/lib/rpg_lib.rb CHANGED
@@ -17,6 +17,12 @@
17
17
 
18
18
  require 'rpg_lib/version'
19
19
  require 'rpg_lib/roll_set'
20
- require 'rpg_lib/roll_descriptor'
20
+ require 'rpg_lib/die_roller'
21
21
  require 'rpg_lib/dice_roller'
22
22
  require 'rpg_lib/string'
23
+ require 'rpg_lib/api'
24
+
25
+ require 'treetop'
26
+ require 'rpg_lib/parser/dice_expression_nodes.rb'
27
+ require 'rpg_lib/parser/dice_expression_parser.rb'
28
+ require 'rpg_lib/parser/dice_parser.rb'
data/lib/rpg_lib/api.rb CHANGED
@@ -1,11 +1,35 @@
1
+ # Copyright 2017 Jamie Hale
2
+ #
3
+ # This file is part of the RpgLib gem.
4
+ #
5
+ # RpgLib is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # RpgLib is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with RpgLib. If not, see <http://www.gnu.org/licenses/>.
17
+
1
18
  module RpgLib
19
+ ##
20
+ # Api
21
+ #
2
22
  module Api
3
23
  def roll(dice)
4
24
  DiceRoller.instance.roll(dice)
5
25
  end
6
26
 
7
27
  def roll_and_ignore(dice, *args)
8
- DiceRoller.instance.roll_and_ignore(dice, *args)
28
+ DiceRoller.instance.roll_and_ignore(dice, RollSet.new(*args))
29
+ end
30
+
31
+ def choose(options)
32
+ options[DiceRoller.instance.roll_die(options.size) - 1]
9
33
  end
10
34
  end
11
35
  end
@@ -24,59 +24,27 @@ module RpgLib
24
24
  class DiceRoller
25
25
  include Singleton
26
26
 
27
- DICE_REGEXP = /(\d*)d(\d+)((dl)(\d*)|(dh)(\d*))?/
27
+ attr_reader :parser
28
+ attr_accessor :roller
28
29
 
29
- def random_value_in_range(range)
30
- rand(range)
30
+ def initialize
31
+ @roller = DieRoller.new
32
+ @parser = Parser::DiceParser.new
31
33
  end
32
34
 
33
- def roll_dice(roll_descriptor)
34
- rolled_values = roll_all_dice_from_descriptor(roll_descriptor)
35
- drop_lowest(rolled_values, roll_descriptor)
36
- drop_highest(rolled_values, roll_descriptor)
37
- total(rolled_values)
35
+ def roll_die(n)
36
+ @roller.roll(n)
38
37
  end
39
38
 
40
39
  def roll(dice)
41
- local_dice = dice.dup
42
- loop do
43
- m = local_dice.downcase.match(DICE_REGEXP)
44
- break if m.nil?
45
- rolled_value = roll_dice(RollDescriptor.new(m))
46
- local_dice[m.begin(0)...m.end(0)] = rolled_value.to_s
47
- end
48
- eval(local_dice)
40
+ @parser.parse(dice).eval(@roller)
49
41
  end
50
42
 
51
43
  def roll_and_ignore(dice, ignored_values)
52
- rolled_value = nil
53
44
  loop do
54
45
  rolled_value = roll(dice)
55
- break unless ignored_values.include?(rolled_value)
56
- end
57
- rolled_value
58
- end
59
-
60
- private
61
-
62
- def roll_all_dice_from_descriptor(roll_descriptor)
63
- rolled_values = []
64
- 1.upto roll_descriptor.count do
65
- rolled_values << random_value_in_range(1..roll_descriptor.die)
46
+ return rolled_value unless ignored_values.include?(rolled_value)
66
47
  end
67
- rolled_values.sort
68
- end
69
-
70
- def drop_lowest(rolled_values, roll_descriptor)
71
- rolled_values.slice!(0, roll_descriptor.drop_lowest)
72
- end
73
-
74
- def drop_highest(rolled_values, roll_descriptor)
75
- rolled_values.slice!(rolled_values.size - roll_descriptor.drop_highest, roll_descriptor.drop_highest)
76
- end
77
-
78
- def total(rolled_values)
79
- rolled_values.inject(:+)
80
48
  end
81
49
  end
82
50
  end
@@ -0,0 +1,14 @@
1
+ module RpgLib
2
+ ##
3
+ # DieRoller
4
+ #
5
+ class DieRoller
6
+ def initialize(generator = nil)
7
+ @generator = generator || Random.new
8
+ end
9
+
10
+ def roll(sides)
11
+ @generator.rand(1..sides)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ module RpgLib
2
+ module Parser
3
+ module DiceExpression
4
+ ##
5
+ # BinaryOperation
6
+ #
7
+ class BinaryOperation < Treetop::Runtime::SyntaxNode
8
+ def eval(roller)
9
+ tail.elements.inject(head.eval(roller)) do |value, element|
10
+ element.operator.apply(value, element.operand.eval(roller))
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,677 @@
1
+ # Autogenerated from a Treetop grammar. Edits may be lost.
2
+
3
+
4
+ module RpgLib
5
+ module Parser
6
+ # :nocov:
7
+ module DiceExpression
8
+ include Treetop::Runtime
9
+
10
+ def root
11
+ @root ||= :additive
12
+ end
13
+
14
+ module Additive0
15
+ def space1
16
+ elements[0]
17
+ end
18
+
19
+ def operator
20
+ elements[1]
21
+ end
22
+
23
+ def space2
24
+ elements[2]
25
+ end
26
+
27
+ def operand
28
+ elements[3]
29
+ end
30
+ end
31
+
32
+ module Additive1
33
+ def head
34
+ elements[0]
35
+ end
36
+
37
+ def tail
38
+ elements[1]
39
+ end
40
+ end
41
+
42
+ def _nt_additive
43
+ start_index = index
44
+ if node_cache[:additive].has_key?(index)
45
+ cached = node_cache[:additive][index]
46
+ if cached
47
+ node_cache[:additive][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
48
+ @index = cached.interval.end
49
+ end
50
+ return cached
51
+ end
52
+
53
+ i0, s0 = index, []
54
+ r1 = _nt_multitive
55
+ s0 << r1
56
+ if r1
57
+ s2, i2 = [], index
58
+ loop do
59
+ i3, s3 = index, []
60
+ r4 = _nt_space
61
+ s3 << r4
62
+ if r4
63
+ r5 = _nt_additive_op
64
+ s3 << r5
65
+ if r5
66
+ r6 = _nt_space
67
+ s3 << r6
68
+ if r6
69
+ r7 = _nt_multitive
70
+ s3 << r7
71
+ end
72
+ end
73
+ end
74
+ if s3.last
75
+ r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
76
+ r3.extend(Additive0)
77
+ else
78
+ @index = i3
79
+ r3 = nil
80
+ end
81
+ if r3
82
+ s2 << r3
83
+ else
84
+ break
85
+ end
86
+ end
87
+ r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
88
+ s0 << r2
89
+ end
90
+ if s0.last
91
+ r0 = instantiate_node(BinaryOperation,input, i0...index, s0)
92
+ r0.extend(Additive1)
93
+ else
94
+ @index = i0
95
+ r0 = nil
96
+ end
97
+
98
+ node_cache[:additive][start_index] = r0
99
+
100
+ r0
101
+ end
102
+
103
+ module AdditiveOp0
104
+ def apply(a, b)
105
+ a + b
106
+ end
107
+ end
108
+
109
+ module AdditiveOp1
110
+ def apply(a, b)
111
+ a - b
112
+ end
113
+ end
114
+
115
+ def _nt_additive_op
116
+ start_index = index
117
+ if node_cache[:additive_op].has_key?(index)
118
+ cached = node_cache[:additive_op][index]
119
+ if cached
120
+ node_cache[:additive_op][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
121
+ @index = cached.interval.end
122
+ end
123
+ return cached
124
+ end
125
+
126
+ i0 = index
127
+ if (match_len = has_terminal?('+', false, index))
128
+ r1 = instantiate_node(SyntaxNode,input, index...(index + match_len))
129
+ r1.extend(AdditiveOp0)
130
+ @index += match_len
131
+ else
132
+ terminal_parse_failure('\'+\'')
133
+ r1 = nil
134
+ end
135
+ if r1
136
+ r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
137
+ r0 = r1
138
+ else
139
+ if (match_len = has_terminal?('-', false, index))
140
+ r2 = instantiate_node(SyntaxNode,input, index...(index + match_len))
141
+ r2.extend(AdditiveOp1)
142
+ @index += match_len
143
+ else
144
+ terminal_parse_failure('\'-\'')
145
+ r2 = nil
146
+ end
147
+ if r2
148
+ r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
149
+ r0 = r2
150
+ else
151
+ @index = i0
152
+ r0 = nil
153
+ end
154
+ end
155
+
156
+ node_cache[:additive_op][start_index] = r0
157
+
158
+ r0
159
+ end
160
+
161
+ module Multitive0
162
+ def space1
163
+ elements[0]
164
+ end
165
+
166
+ def operator
167
+ elements[1]
168
+ end
169
+
170
+ def space2
171
+ elements[2]
172
+ end
173
+
174
+ def operand
175
+ elements[3]
176
+ end
177
+ end
178
+
179
+ module Multitive1
180
+ def head
181
+ elements[0]
182
+ end
183
+
184
+ def tail
185
+ elements[1]
186
+ end
187
+ end
188
+
189
+ def _nt_multitive
190
+ start_index = index
191
+ if node_cache[:multitive].has_key?(index)
192
+ cached = node_cache[:multitive][index]
193
+ if cached
194
+ node_cache[:multitive][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
195
+ @index = cached.interval.end
196
+ end
197
+ return cached
198
+ end
199
+
200
+ i0, s0 = index, []
201
+ r1 = _nt_primary
202
+ s0 << r1
203
+ if r1
204
+ s2, i2 = [], index
205
+ loop do
206
+ i3, s3 = index, []
207
+ r4 = _nt_space
208
+ s3 << r4
209
+ if r4
210
+ r5 = _nt_multitive_op
211
+ s3 << r5
212
+ if r5
213
+ r6 = _nt_space
214
+ s3 << r6
215
+ if r6
216
+ r7 = _nt_primary
217
+ s3 << r7
218
+ end
219
+ end
220
+ end
221
+ if s3.last
222
+ r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
223
+ r3.extend(Multitive0)
224
+ else
225
+ @index = i3
226
+ r3 = nil
227
+ end
228
+ if r3
229
+ s2 << r3
230
+ else
231
+ break
232
+ end
233
+ end
234
+ r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
235
+ s0 << r2
236
+ end
237
+ if s0.last
238
+ r0 = instantiate_node(BinaryOperation,input, i0...index, s0)
239
+ r0.extend(Multitive1)
240
+ else
241
+ @index = i0
242
+ r0 = nil
243
+ end
244
+
245
+ node_cache[:multitive][start_index] = r0
246
+
247
+ r0
248
+ end
249
+
250
+ module MultitiveOp0
251
+ def apply(a, b)
252
+ a * b
253
+ end
254
+ end
255
+
256
+ module MultitiveOp1
257
+ def apply(a, b)
258
+ a / b
259
+ end
260
+ end
261
+
262
+ def _nt_multitive_op
263
+ start_index = index
264
+ if node_cache[:multitive_op].has_key?(index)
265
+ cached = node_cache[:multitive_op][index]
266
+ if cached
267
+ node_cache[:multitive_op][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
268
+ @index = cached.interval.end
269
+ end
270
+ return cached
271
+ end
272
+
273
+ i0 = index
274
+ if (match_len = has_terminal?('*', false, index))
275
+ r1 = instantiate_node(SyntaxNode,input, index...(index + match_len))
276
+ r1.extend(MultitiveOp0)
277
+ @index += match_len
278
+ else
279
+ terminal_parse_failure('\'*\'')
280
+ r1 = nil
281
+ end
282
+ if r1
283
+ r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
284
+ r0 = r1
285
+ else
286
+ if (match_len = has_terminal?('/', false, index))
287
+ r2 = instantiate_node(SyntaxNode,input, index...(index + match_len))
288
+ r2.extend(MultitiveOp1)
289
+ @index += match_len
290
+ else
291
+ terminal_parse_failure('\'/\'')
292
+ r2 = nil
293
+ end
294
+ if r2
295
+ r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
296
+ r0 = r2
297
+ else
298
+ @index = i0
299
+ r0 = nil
300
+ end
301
+ end
302
+
303
+ node_cache[:multitive_op][start_index] = r0
304
+
305
+ r0
306
+ end
307
+
308
+ module Primary0
309
+ def space1
310
+ elements[1]
311
+ end
312
+
313
+ def additive
314
+ elements[2]
315
+ end
316
+
317
+ def space2
318
+ elements[3]
319
+ end
320
+
321
+ end
322
+
323
+ module Primary1
324
+ def eval(roller)
325
+ additive.eval(roller)
326
+ end
327
+ end
328
+
329
+ def _nt_primary
330
+ start_index = index
331
+ if node_cache[:primary].has_key?(index)
332
+ cached = node_cache[:primary][index]
333
+ if cached
334
+ node_cache[:primary][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
335
+ @index = cached.interval.end
336
+ end
337
+ return cached
338
+ end
339
+
340
+ i0 = index
341
+ r1 = _nt_dice
342
+ if r1
343
+ r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
344
+ r0 = r1
345
+ else
346
+ r2 = _nt_number
347
+ if r2
348
+ r2 = SyntaxNode.new(input, (index-1)...index) if r2 == true
349
+ r0 = r2
350
+ else
351
+ i3, s3 = index, []
352
+ if (match_len = has_terminal?('(', false, index))
353
+ r4 = true
354
+ @index += match_len
355
+ else
356
+ terminal_parse_failure('\'(\'')
357
+ r4 = nil
358
+ end
359
+ s3 << r4
360
+ if r4
361
+ r5 = _nt_space
362
+ s3 << r5
363
+ if r5
364
+ r6 = _nt_additive
365
+ s3 << r6
366
+ if r6
367
+ r7 = _nt_space
368
+ s3 << r7
369
+ if r7
370
+ if (match_len = has_terminal?(')', false, index))
371
+ r8 = true
372
+ @index += match_len
373
+ else
374
+ terminal_parse_failure('\')\'')
375
+ r8 = nil
376
+ end
377
+ s3 << r8
378
+ end
379
+ end
380
+ end
381
+ end
382
+ if s3.last
383
+ r3 = instantiate_node(SyntaxNode,input, i3...index, s3)
384
+ r3.extend(Primary0)
385
+ r3.extend(Primary1)
386
+ else
387
+ @index = i3
388
+ r3 = nil
389
+ end
390
+ if r3
391
+ r3 = SyntaxNode.new(input, (index-1)...index) if r3 == true
392
+ r0 = r3
393
+ else
394
+ @index = i0
395
+ r0 = nil
396
+ end
397
+ end
398
+ end
399
+
400
+ node_cache[:primary][start_index] = r0
401
+
402
+ r0
403
+ end
404
+
405
+ module Number0
406
+ end
407
+
408
+ module Number1
409
+ def eval(_roller)
410
+ text_value.to_i
411
+ end
412
+ end
413
+
414
+ def _nt_number
415
+ start_index = index
416
+ if node_cache[:number].has_key?(index)
417
+ cached = node_cache[:number][index]
418
+ if cached
419
+ node_cache[:number][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
420
+ @index = cached.interval.end
421
+ end
422
+ return cached
423
+ end
424
+
425
+ i0 = index
426
+ i1, s1 = index, []
427
+ if (match_len = has_terminal?('-', false, index))
428
+ r3 = true
429
+ @index += match_len
430
+ else
431
+ terminal_parse_failure('\'-\'')
432
+ r3 = nil
433
+ end
434
+ if r3
435
+ r2 = r3
436
+ else
437
+ r2 = instantiate_node(SyntaxNode,input, index...index)
438
+ end
439
+ s1 << r2
440
+ if r2
441
+ if has_terminal?(@regexps[gr = '\A[1-9]'] ||= Regexp.new(gr), :regexp, index)
442
+ r4 = true
443
+ @index += 1
444
+ else
445
+ terminal_parse_failure('[1-9]')
446
+ r4 = nil
447
+ end
448
+ s1 << r4
449
+ if r4
450
+ s5, i5 = [], index
451
+ loop do
452
+ if has_terminal?(@regexps[gr = '\A[0-9]'] ||= Regexp.new(gr), :regexp, index)
453
+ r6 = true
454
+ @index += 1
455
+ else
456
+ terminal_parse_failure('[0-9]')
457
+ r6 = nil
458
+ end
459
+ if r6
460
+ s5 << r6
461
+ else
462
+ break
463
+ end
464
+ end
465
+ r5 = instantiate_node(SyntaxNode,input, i5...index, s5)
466
+ s1 << r5
467
+ end
468
+ end
469
+ if s1.last
470
+ r1 = instantiate_node(SyntaxNode,input, i1...index, s1)
471
+ r1.extend(Number0)
472
+ else
473
+ @index = i1
474
+ r1 = nil
475
+ end
476
+ if r1
477
+ r1 = SyntaxNode.new(input, (index-1)...index) if r1 == true
478
+ r0 = r1
479
+ r0.extend(Number1)
480
+ r0.extend(Number1)
481
+ else
482
+ if (match_len = has_terminal?('0', false, index))
483
+ r7 = true
484
+ @index += match_len
485
+ else
486
+ terminal_parse_failure('\'0\'')
487
+ r7 = nil
488
+ end
489
+ if r7
490
+ r7 = SyntaxNode.new(input, (index-1)...index) if r7 == true
491
+ r0 = r7
492
+ r0.extend(Number1)
493
+ r0.extend(Number1)
494
+ else
495
+ @index = i0
496
+ r0 = nil
497
+ end
498
+ end
499
+
500
+ node_cache[:number][start_index] = r0
501
+
502
+ r0
503
+ end
504
+
505
+ module PositiveInteger0
506
+ end
507
+
508
+ module PositiveInteger1
509
+ def eval(_roller)
510
+ text_value.to_i
511
+ end
512
+ end
513
+
514
+ def _nt_positive_integer
515
+ start_index = index
516
+ if node_cache[:positive_integer].has_key?(index)
517
+ cached = node_cache[:positive_integer][index]
518
+ if cached
519
+ node_cache[:positive_integer][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
520
+ @index = cached.interval.end
521
+ end
522
+ return cached
523
+ end
524
+
525
+ i0, s0 = index, []
526
+ if has_terminal?(@regexps[gr = '\A[1-9]'] ||= Regexp.new(gr), :regexp, index)
527
+ r1 = true
528
+ @index += 1
529
+ else
530
+ terminal_parse_failure('[1-9]')
531
+ r1 = nil
532
+ end
533
+ s0 << r1
534
+ if r1
535
+ s2, i2 = [], index
536
+ loop do
537
+ if has_terminal?(@regexps[gr = '\A[0-9]'] ||= Regexp.new(gr), :regexp, index)
538
+ r3 = true
539
+ @index += 1
540
+ else
541
+ terminal_parse_failure('[0-9]')
542
+ r3 = nil
543
+ end
544
+ if r3
545
+ s2 << r3
546
+ else
547
+ break
548
+ end
549
+ end
550
+ r2 = instantiate_node(SyntaxNode,input, i2...index, s2)
551
+ s0 << r2
552
+ end
553
+ if s0.last
554
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
555
+ r0.extend(PositiveInteger0)
556
+ r0.extend(PositiveInteger1)
557
+ else
558
+ @index = i0
559
+ r0 = nil
560
+ end
561
+
562
+ node_cache[:positive_integer][start_index] = r0
563
+
564
+ r0
565
+ end
566
+
567
+ module Dice0
568
+ def count
569
+ elements[0]
570
+ end
571
+
572
+ def sides
573
+ elements[2]
574
+ end
575
+ end
576
+
577
+ module Dice1
578
+ def eval(roller)
579
+ die_count = count.empty? ? 1 : count.eval(nil)
580
+ die_sides = sides.eval(nil)
581
+ rolls = []
582
+ die_count.times do
583
+ rolls << roller.roll(die_sides)
584
+ end
585
+ rolls.inject(&:+)
586
+ end
587
+ end
588
+
589
+ def _nt_dice
590
+ start_index = index
591
+ if node_cache[:dice].has_key?(index)
592
+ cached = node_cache[:dice][index]
593
+ if cached
594
+ node_cache[:dice][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
595
+ @index = cached.interval.end
596
+ end
597
+ return cached
598
+ end
599
+
600
+ i0, s0 = index, []
601
+ r2 = _nt_positive_integer
602
+ if r2
603
+ r1 = r2
604
+ else
605
+ r1 = instantiate_node(SyntaxNode,input, index...index)
606
+ end
607
+ s0 << r1
608
+ if r1
609
+ if (match_len = has_terminal?('d', false, index))
610
+ r3 = true
611
+ @index += match_len
612
+ else
613
+ terminal_parse_failure('\'d\'')
614
+ r3 = nil
615
+ end
616
+ s0 << r3
617
+ if r3
618
+ r4 = _nt_positive_integer
619
+ s0 << r4
620
+ end
621
+ end
622
+ if s0.last
623
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
624
+ r0.extend(Dice0)
625
+ r0.extend(Dice1)
626
+ else
627
+ @index = i0
628
+ r0 = nil
629
+ end
630
+
631
+ node_cache[:dice][start_index] = r0
632
+
633
+ r0
634
+ end
635
+
636
+ def _nt_space
637
+ start_index = index
638
+ if node_cache[:space].has_key?(index)
639
+ cached = node_cache[:space][index]
640
+ if cached
641
+ node_cache[:space][index] = cached = SyntaxNode.new(input, index...(index + 1)) if cached == true
642
+ @index = cached.interval.end
643
+ end
644
+ return cached
645
+ end
646
+
647
+ s0, i0 = [], index
648
+ loop do
649
+ if (match_len = has_terminal?(' ', false, index))
650
+ r1 = true
651
+ @index += match_len
652
+ else
653
+ terminal_parse_failure('\' \'')
654
+ r1 = nil
655
+ end
656
+ if r1
657
+ s0 << r1
658
+ else
659
+ break
660
+ end
661
+ end
662
+ r0 = instantiate_node(SyntaxNode,input, i0...index, s0)
663
+
664
+ node_cache[:space][start_index] = r0
665
+
666
+ r0
667
+ end
668
+
669
+ end
670
+
671
+ class DiceExpressionParser < Treetop::Runtime::CompiledParser
672
+ include DiceExpression
673
+ end
674
+
675
+ # :nocov:
676
+ end
677
+ end