forked from bcdice/BCDice
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_add_dice_parser.rb
450 lines (378 loc) · 11.4 KB
/
test_add_dice_parser.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
# frozen_string_literal: true
require "test/unit"
require "bcdice"
require "bcdice/common_command/add_dice/parser"
class AddDiceParserTest < Test::Unit::TestCase
# ダイスロールのみ
def test_parse_dice_roll
test_parse("2D6", "(Command (DiceRoll 2 6))")
end
# ダイスロール + 修正値
def test_parse_modifier
test_parse("2D6+1", "(Command (+ (DiceRoll 2 6) 1))")
end
# 定数畳み込みはしない
def test_parse_long_modifier
test_parse("2D6+1-1-2-3-4", "(Command (- (- (- (- (+ (DiceRoll 2 6) 1) 1) 2) 3) 4))")
end
# 複数のダイスロール
def test_parse_multiple_dice_rolls
test_parse(
"2D6*3-1D6+1",
"(Command (+ (- (* (DiceRoll 2 6) 3) (DiceRoll 1 6)) 1))"
)
end
# 面数の省略
def test_parse_implicit_d
test_parse("2D", "(Command (ImplicitSidesDiceRoll 2))")
test_parse("2D+3", "(Command (+ (ImplicitSidesDiceRoll 2) 3))")
end
# ダイス数の省略
def test_parse_implicit_times
test_parse("D20", "(Command (DiceRoll 1 20))")
test_parse("D20+3", "(Command (+ (DiceRoll 1 20) 3))")
end
def test_parse_d66
assert_not_parse("D66", "D66は処理しない")
assert_not_parse("1+D66", "D66は処理しない")
end
# 1D66は66面ダイス扱い
def test_parse_1d66
test_parse("1D66", "(Command (DiceRoll 1 66))")
end
# 最初の空白までがパース対象となる
def test_parse_only_first_word
test_parse("2D6 +1", "(Command (DiceRoll 2 6))")
test_parse("2D6\n+1", "(Command (DiceRoll 2 6))")
end
# 除法
def test_parse_division
test_parse("5D6/10", "(Command (/ (DiceRoll 5 6) 10))")
test_parse("5D6+300/10", "(Command (+ (DiceRoll 5 6) (/ 300 10)))")
end
# 除法(切り上げ)
def test_parse_division_with_rounding_up
test_parse("3D6/2U", "(Command (/U (DiceRoll 3 6) 2))")
test_parse("3D6-40/2U", "(Command (- (DiceRoll 3 6) (/U 40 2)))")
end
# 除法(四捨五入)
def test_parse_division_with_rounding_off
test_parse("1D100/10R", "(Command (/R (DiceRoll 1 100) 10))")
test_parse("1D100*12/10R", "(Command (/R (* (DiceRoll 1 100) 12) 10))")
end
# 符号反転(負の整数で割る)
def test_parse_negation_1
test_parse("1D6/-3", "(Command (/ (DiceRoll 1 6) (- 3)))")
end
# 符号反転(ダイスロールの符号反転)
def test_parse_negation_2
test_parse("-1D6+1", "(Command (+ (- (DiceRoll 1 6)) 1))")
end
# 二重符号反転(--1)
def test_parse_double_negation_1
test_parse("2D6--1", "(Command (+ (DiceRoll 2 6) 1))")
end
# 二重符号反転(---1)
def test_parse_double_negation_2
test_parse("2D6---1", "(Command (- (DiceRoll 2 6) 1))")
end
# カッコ
def test_parse_parenthesis
test_parse("(1D6+2D4)*2", "(Command (* (Parenthesis (+ (DiceRoll 1 6) (DiceRoll 2 4))) 2))")
end
def test_parse_nested_dice
assert_not_parse("(1D6)D6", "ダイス数にダイスロールをネストできない")
assert_not_parse("1D(1D6)", "面数数にダイスロールをネストできない")
end
def test_parse_without_dice
assert_not_parse("1+2", "ダイスロールがない場合にはエラーになる")
end
# 目標値あり(=)
def test_parse_target_value_eq_1
test_parse("2D6=7", "(Command (== (DiceRoll 2 6) 7))")
end
# 目標値あり(===)
def test_parse_target_value_eq_2
test_parse("2D6===7", "(Command (== (DiceRoll 2 6) 7))")
end
# 目標値あり(<>)
def test_parse_target_value_not_eq_1
test_parse("2D6<>7", "(Command (!= (DiceRoll 2 6) 7))")
end
# 目標値あり(!=)
def test_parse_target_value_not_eq_2
test_parse("2D6!=7", "(Command (!= (DiceRoll 2 6) 7))")
end
# 目標値あり(>=)
def test_parse_target_value_geq_1
test_parse("2D6>=7", "(Command (>= (DiceRoll 2 6) 7))")
end
# 目標値あり(=>)
def test_parse_target_value_geq_2
test_parse("2D6=>7", "(Command (>= (DiceRoll 2 6) 7))")
end
# 目標値あり(<=)
def test_parse_target_value_leq
test_parse("2D6<=7", "(Command (<= (DiceRoll 2 6) 7))")
end
# 目標値あり(>)
def test_parse_target_value_less
test_parse("2D6>7", "(Command (> (DiceRoll 2 6) 7))")
end
# 目標値あり(<)
def test_parse_target_value_greater
test_parse("2D6<7", "(Command (< (DiceRoll 2 6) 7))")
end
# 目標値に式を書ける
def test_parse_target_value_expr
test_parse("2D6>=(5+1)*2", "(Command (>= (DiceRoll 2 6) (* (Parenthesis (+ 5 1)) 2)))")
end
def test_parse_question_target
test_parse("2D6<=?", "(Command (<= (DiceRoll 2 6) ?))")
end
def test_parse_empty_target
assert_not_parse("2D6<", "目標値無しはパースエラーになる")
end
def test_parse_invalid_cmp_op
assert_not_parse("2D6!!10", "不正な比較演算子はパースエラーになる")
end
def test_parse_invalid_question_target
assert_not_parse("2D6<=?a")
end
def test_parse_invalid_target
assert_not_parse("2D6<=12ab")
end
def test_parse_dice_target
assert_not_parse("2D6<=1D6", "目標値にダイスロールを設定できない")
end
# 目標値あり、目標値の定数畳み込み
def test_parse_target_value_constant_fonding
test_parse(
"1D6+1-2>=1+2",
"(Command (>= (- (+ (DiceRoll 1 6) 1) 2) (+ 1 2)))"
)
end
# 大きな出目から複数個取る
def test_parse_keep_high
test_parse(
"5D10KH3",
"(Command (DiceRollWithFilter 5 10 :KH 3))"
)
end
# 括弧で指定
def test_parse_keep_high_with_parentheses
test_parse(
"(3+2)D(5+5)KH(5-2)",
"(Command (DiceRollWithFilter (Parenthesis (+ 3 2)) (Parenthesis (+ 5 5)) :KH (Parenthesis (- 5 2))))"
)
end
# 大きな出目から1個取る
def test_parse_keep_highest
test_parse(
"5D10KH",
"(Command (DiceRollWithFilter 5 10 :KH 1))"
)
end
# 大きな出目から複数個取る(面数省略)
def test_parse_keep_high_implicit_sides
test_parse(
"5DKH3",
"(Command (DiceRollWithFilter 5 :implicit :KH 3))"
)
end
# 大きな出目から1個取る(面数省略)
def test_parse_keep_highest_implicit_sides
test_parse(
"5DKH",
"(Command (DiceRollWithFilter 5 :implicit :KH 1))"
)
end
# 小さな出目から複数個取る
def test_parse_keep_low
test_parse(
"5D10KL3",
"(Command (DiceRollWithFilter 5 10 :KL 3))"
)
end
# 小さな出目から1個取る
def test_parse_keep_lowest
test_parse(
"5D10KL",
"(Command (DiceRollWithFilter 5 10 :KL 1))"
)
end
# 小さな出目から複数個取る(面数省略)
def test_parse_keep_low_implicit_sides
test_parse(
"5DKL3",
"(Command (DiceRollWithFilter 5 :implicit :KL 3))"
)
end
# 小さな出目から1個取る(面数省略)
def test_parse_keep_lowest_implicit_sides
test_parse(
"5DKL",
"(Command (DiceRollWithFilter 5 :implicit :KL 1))"
)
end
# 大きな出目から複数個除く
def test_parse_drop_high
test_parse(
"5D10DH3",
"(Command (DiceRollWithFilter 5 10 :DH 3))"
)
end
# 大きな出目から1個除く
def test_parse_drop_highest
test_parse(
"5D10DH",
"(Command (DiceRollWithFilter 5 10 :DH 1))"
)
end
# 大きな出目から複数個除く(面数省略)
def test_parse_drop_high_implicit_sides
test_parse(
"5DDH3",
"(Command (DiceRollWithFilter 5 :implicit :DH 3))"
)
end
# 大きな出目から1個除く(面数省略)
def test_parse_drop_highest_implicit_sides
test_parse(
"5DDH",
"(Command (DiceRollWithFilter 5 :implicit :DH 1))"
)
end
# 小さな出目から複数個除く
def test_parse_drop_low
test_parse(
"5D10DL3",
"(Command (DiceRollWithFilter 5 10 :DL 3))"
)
end
# 小さな出目から1個除く
def test_parse_drop_lowest
test_parse(
"5D10DL",
"(Command (DiceRollWithFilter 5 10 :DL 1))"
)
end
# 小さな出目から複数個除く(面数省略)
def test_parse_drop_low_implicit_sides
test_parse(
"5DDL3",
"(Command (DiceRollWithFilter 5 :implicit :DL 3))"
)
end
# 小さな出目から1個除く(面数省略)
def test_parse_drop_lowest_implicit_sides
test_parse(
"5DDL",
"(Command (DiceRollWithFilter 5 :implicit :DL 1))"
)
end
# 大きな値キープ機能、修正値付き
def test_parse_keep_high_with_modifier
test_parse(
"5D10KH3+1",
"(Command (+ (DiceRollWithFilter 5 10 :KH 3) 1))"
)
end
# 小さな値キープ機能、修正値付き
def test_parse_keep_low_with_modifier
test_parse(
"5D10KL3+1",
"(Command (+ (DiceRollWithFilter 5 10 :KL 3) 1))"
)
end
# 大きな値ドロップ機能、修正値付き
def test_parse_drop_high_with_modifier
test_parse(
"5D10DH3+1",
"(Command (+ (DiceRollWithFilter 5 10 :DH 3) 1))"
)
end
# 小さな値ドロップ機能、修正値付き
def test_parse_drop_low_with_modifier
test_parse(
"5D10DL3+1",
"(Command (+ (DiceRollWithFilter 5 10 :DL 3) 1))"
)
end
# 最大値抽出( KH1 の簡易記法)
def test_parse_max
test_parse(
"3D6MAX",
"(Command (DiceRollWithFilter 3 6 :KH 1))"
)
end
# 最大値抽出、面数省略
def test_parse_max_implicit_sides
test_parse(
"3DMAX",
"(Command (DiceRollWithFilter 3 :implicit :KH 1))"
)
end
# 最大値抽出、修正値つき
def test_parse_max_with_modifier
test_parse(
"3D6MAX+2",
"(Command (+ (DiceRollWithFilter 3 6 :KH 1) 2))"
)
end
# 最大値抽出、パース不可
def test_not_parse_max
# 個数を指定できない
assert_not_parse("3D6MAX1")
assert_not_parse("3DMAX1")
end
# 最小値抽出( KL1 の簡易記法)
def test_parse_min
test_parse(
"5D10MIN",
"(Command (DiceRollWithFilter 5 10 :KL 1))"
)
end
# 最小値抽出、面数省略
def test_parse_min_implicit_sides
test_parse(
"5DMIN",
"(Command (DiceRollWithFilter 5 :implicit :KL 1))"
)
end
# 最小値抽出、修正値つき
def test_parse_min_with_modifier
test_parse(
"5D10MIN-3",
"(Command (- (DiceRollWithFilter 5 10 :KL 1) 3))"
)
end
# 最小値抽出、パース不可
def test_not_parse_min
# 個数を指定できない
assert_not_parse("3D6MIN1")
assert_not_parse("3DMIN1")
end
def test_parse_filter_nested_dice
assert_not_parse("(1D6)D6HK3", "ダイス数にダイスロールをネストできない")
assert_not_parse("1D(1D6)HK3", "面数数にダイスロールをネストできない")
assert_not_parse("1D6HK(1D6)", "ダイス保持数にダイスロールをネストできない")
end
private
# 構文解析をテストする
# @param [String] command テストするコマンド
# @param [String] expected_s_exp 期待されるS式
# @return [void]
def test_parse(command, expected_s_exp)
node = BCDice::CommonCommand::AddDice::Parser.parse(command)
assert_equal(expected_s_exp, node.s_exp, "結果の抽象構文木が正しい")
end
# @param command [String]
def assert_not_parse(command, message = nil)
message = build_message(message, "? are parsed", command)
assert_block(message) do
node = BCDice::CommonCommand::AddDice::Parser.parse(command)
node.nil?
end
end
end