bcdice 3.0.0.pre.alpha.2 → 3.0.0.pre.rc.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.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -0
  3. data/README.md +1 -0
  4. data/i18n/KillDeathBusiness/ja_jp.yml +4 -4
  5. data/i18n/KillDeathBusiness/ko_kr.yml +5 -4
  6. data/i18n/MagicaLogia/ko_kr.yml +564 -0
  7. data/i18n/MonotoneMuseum/ja_jp.yml +37 -1
  8. data/i18n/StratoShout/ja_jp.yml +4 -4
  9. data/i18n/StratoShout/ko_kr.yml +4 -4
  10. data/lib/bcdice.rb +2 -1
  11. data/lib/bcdice/arithmetic.rb +22 -0
  12. data/lib/bcdice/arithmetic/node.rb +112 -43
  13. data/lib/bcdice/arithmetic/parser.rb +240 -0
  14. data/lib/bcdice/arithmetic_evaluator.rb +5 -156
  15. data/lib/bcdice/base.rb +8 -1
  16. data/lib/bcdice/command/lexer.rb +57 -0
  17. data/lib/bcdice/command/parsed.rb +65 -0
  18. data/lib/bcdice/command/parser.rb +489 -0
  19. data/lib/bcdice/common_command/add_dice.rb +1 -1
  20. data/lib/bcdice/common_command/add_dice/node.rb +142 -69
  21. data/lib/bcdice/common_command/add_dice/parser.rb +100 -83
  22. data/lib/bcdice/common_command/barabara_dice/node.rb +7 -1
  23. data/lib/bcdice/common_command/barabara_dice/result.rb +22 -0
  24. data/lib/bcdice/common_command/calc/node.rb +10 -1
  25. data/lib/bcdice/common_command/calc/parser.rb +1 -1
  26. data/lib/bcdice/common_command/d66_dice.rb +3 -1
  27. data/lib/bcdice/common_command/lexer.rb +2 -1
  28. data/lib/bcdice/common_command/upper_dice/parser.rb +118 -97
  29. data/lib/bcdice/common_command/version.rb +1 -1
  30. data/lib/bcdice/deprecated/checker.rb +6 -6
  31. data/lib/bcdice/dice_table.rb +1 -0
  32. data/lib/bcdice/dice_table/d66_parity_table.rb +34 -0
  33. data/lib/bcdice/game_system.rb +3 -0
  34. data/lib/bcdice/game_system/AceKillerGene.rb +1 -1
  35. data/lib/bcdice/game_system/AlchemiaStruggle.rb +312 -0
  36. data/lib/bcdice/game_system/Alshard.rb +0 -1
  37. data/lib/bcdice/game_system/Amadeus.rb +1 -1
  38. data/lib/bcdice/game_system/AnimaAnimus.rb +1 -5
  39. data/lib/bcdice/game_system/BadLife.rb +1 -1
  40. data/lib/bcdice/game_system/BeastBindTrinity.rb +1 -10
  41. data/lib/bcdice/game_system/BeginningIdol.rb +4 -4
  42. data/lib/bcdice/game_system/BeginningIdol_Korean.rb +4 -4
  43. data/lib/bcdice/game_system/BladeOfArcana.rb +4 -4
  44. data/lib/bcdice/game_system/BlindMythos.rb +12 -9
  45. data/lib/bcdice/game_system/BloodCrusade.rb +12 -38
  46. data/lib/bcdice/game_system/BloodMoon.rb +2 -2
  47. data/lib/bcdice/game_system/CardRanker.rb +23 -63
  48. data/lib/bcdice/game_system/ChaosFlare.rb +3 -3
  49. data/lib/bcdice/game_system/CodeLayerd.rb +1 -1
  50. data/lib/bcdice/game_system/ColossalHunter.rb +2 -2
  51. data/lib/bcdice/game_system/Cthulhu7th.rb +2 -2
  52. data/lib/bcdice/game_system/CthulhuTech.rb +0 -1
  53. data/lib/bcdice/game_system/DarkBlaze.rb +4 -4
  54. data/lib/bcdice/game_system/DeadlineHeroes.rb +1 -1
  55. data/lib/bcdice/game_system/DoubleCross.rb +60 -93
  56. data/lib/bcdice/game_system/EmbryoMachine.rb +5 -5
  57. data/lib/bcdice/game_system/EtrianOdysseySRS.rb +0 -1
  58. data/lib/bcdice/game_system/FilledWith.rb +3 -3
  59. data/lib/bcdice/game_system/FullMetalPanic.rb +0 -1
  60. data/lib/bcdice/game_system/GURPS.rb +1 -1
  61. data/lib/bcdice/game_system/Garako.rb +3 -2
  62. data/lib/bcdice/game_system/GardenOrder.rb +1 -1
  63. data/lib/bcdice/game_system/GehennaAn.rb +3 -3
  64. data/lib/bcdice/game_system/Gundog.rb +1 -1
  65. data/lib/bcdice/game_system/GundogRevised.rb +3 -3
  66. data/lib/bcdice/game_system/GundogZero.rb +2 -2
  67. data/lib/bcdice/game_system/GurpsFW.rb +2 -5
  68. data/lib/bcdice/game_system/HatsuneMiku.rb +1 -1
  69. data/lib/bcdice/game_system/HuntersMoon.rb +17 -110
  70. data/lib/bcdice/game_system/JuinKansen.rb +251 -0
  71. data/lib/bcdice/game_system/KanColle.rb +17 -166
  72. data/lib/bcdice/game_system/KillDeathBusiness.rb +35 -44
  73. data/lib/bcdice/game_system/KillDeathBusiness_Korean.rb +2 -1
  74. data/lib/bcdice/game_system/LogHorizon.rb +8 -8
  75. data/lib/bcdice/game_system/LostRoyal.rb +1 -3
  76. data/lib/bcdice/game_system/MagicaLogia.rb +3 -3
  77. data/lib/bcdice/game_system/MagicaLogia_Korean.rb +66 -0
  78. data/lib/bcdice/game_system/MeikyuDays.rb +1 -1
  79. data/lib/bcdice/game_system/MeikyuKingdom.rb +1 -1
  80. data/lib/bcdice/game_system/MeikyuKingdomBasic.rb +1 -1
  81. data/lib/bcdice/game_system/MetalHeadExtream.rb +4 -4
  82. data/lib/bcdice/game_system/MetallicGuardian.rb +0 -1
  83. data/lib/bcdice/game_system/MonotoneMuseum.rb +3 -2
  84. data/lib/bcdice/game_system/MonotoneMuseum_Korean.rb +1 -1
  85. data/lib/bcdice/game_system/NSSQ.rb +2 -2
  86. data/lib/bcdice/game_system/Nechronica.rb +3 -3
  87. data/lib/bcdice/game_system/NightWizard.rb +1 -1
  88. data/lib/bcdice/game_system/NightmareHunterDeep.rb +3 -4
  89. data/lib/bcdice/game_system/NinjaSlayer.rb +26 -28
  90. data/lib/bcdice/game_system/OracleEngine.rb +13 -17
  91. data/lib/bcdice/game_system/Paradiso.rb +2 -2
  92. data/lib/bcdice/game_system/PhantasmAdventure.rb +0 -4
  93. data/lib/bcdice/game_system/Raisondetre.rb +1 -1
  94. data/lib/bcdice/game_system/RecordOfLodossWar.rb +2 -3
  95. data/lib/bcdice/game_system/RokumonSekai2.rb +2 -2
  96. data/lib/bcdice/game_system/RuinBreakers.rb +1 -1
  97. data/lib/bcdice/game_system/Ryutama.rb +1 -1
  98. data/lib/bcdice/game_system/SRS.rb +0 -5
  99. data/lib/bcdice/game_system/SamsaraBallad.rb +4 -3
  100. data/lib/bcdice/game_system/Satasupe.rb +22 -14
  101. data/lib/bcdice/game_system/ScreamHighSchool.rb +2 -2
  102. data/lib/bcdice/game_system/ShinkuuGakuen.rb +1 -1
  103. data/lib/bcdice/game_system/ShinobiGami.rb +75 -39
  104. data/lib/bcdice/game_system/StellarKnights.rb +1 -3
  105. data/lib/bcdice/game_system/SterileLife.rb +1 -1
  106. data/lib/bcdice/game_system/StrangerOfSwordCity.rb +1 -1
  107. data/lib/bcdice/game_system/StratoShout.rb +10 -36
  108. data/lib/bcdice/game_system/StratoShout_Korean.rb +2 -1
  109. data/lib/bcdice/game_system/SwordWorld.rb +5 -5
  110. data/lib/bcdice/game_system/SwordWorld2_5.rb +1 -1
  111. data/lib/bcdice/game_system/TherapieSein.rb +2 -2
  112. data/lib/bcdice/game_system/TokumeiTenkousei.rb +2 -2
  113. data/lib/bcdice/game_system/Torg.rb +1 -1
  114. data/lib/bcdice/game_system/TorgEternity.rb +4 -7
  115. data/lib/bcdice/game_system/TrinitySeven.rb +2 -2
  116. data/lib/bcdice/game_system/TunnelsAndTrolls.rb +6 -6
  117. data/lib/bcdice/game_system/TwilightGunsmoke.rb +1 -1
  118. data/lib/bcdice/game_system/Utakaze.rb +1 -1
  119. data/lib/bcdice/game_system/Warhammer.rb +6 -6
  120. data/lib/bcdice/game_system/Warhammer4.rb +9 -12
  121. data/lib/bcdice/game_system/ZettaiReido.rb +1 -1
  122. data/lib/bcdice/normalize.rb +1 -1
  123. data/lib/bcdice/preprocessor.rb +12 -8
  124. data/lib/bcdice/randomizer.rb +12 -0
  125. data/lib/bcdice/repl.rb +1 -1
  126. data/lib/bcdice/result.rb +2 -0
  127. data/lib/bcdice/user_defined_dice_table.rb +26 -15
  128. data/lib/bcdice/version.rb +1 -1
  129. metadata +14 -25
  130. data/.editorconfig +0 -21
  131. data/.github/.codecov.yaml +0 -10
  132. data/.github/workflows/coverage.yaml +0 -21
  133. data/.github/workflows/lint.yaml +0 -13
  134. data/.github/workflows/test.yml +0 -20
  135. data/.gitignore +0 -14
  136. data/.rubocop.yml +0 -108
  137. data/.rubocop_todo.yml +0 -114
  138. data/Gemfile +0 -14
  139. data/ROADMAP.md +0 -30
  140. data/Rakefile +0 -152
  141. data/bcdice.gemspec +0 -29
  142. data/bin/repl.rb +0 -21
  143. data/docs/README.txt +0 -2028
  144. data/docs/dicebot_sort_key.md +0 -72
  145. data/docs/how_to_make_dicebot.md +0 -453
  146. data/lib/bcdice/command_parser.rb +0 -242
  147. data/lib/bcdice/common_command/add_dice/parser.y +0 -153
  148. data/lib/bcdice/common_command/barabara_dice/parser.y +0 -107
  149. data/lib/bcdice/common_command/calc/parser.y +0 -79
  150. data/lib/bcdice/common_command/reroll_dice/parser.y +0 -158
  151. data/lib/bcdice/common_command/upper_dice/parser.y +0 -143
@@ -1,242 +0,0 @@
1
- require "bcdice/arithmetic_evaluator"
2
- require "bcdice/normalize"
3
- require "bcdice/format"
4
-
5
- module BCDice
6
- # よくある形式のコマンドのパースを補助するクラス
7
- #
8
- # @example Literal by String
9
- # parser = CommandParser.new("MC")
10
- # parsed = parser.parse("MC+2*3@30<=10/2-3") #=> <CommandParser::Parsed>
11
- #
12
- # parsed.command #=> "MC"
13
- # parsed.modify_number #=> 6
14
- # parsed.critical #=> 30
15
- # parsed.cmp_op #=> #>=
16
- # parsed.target_number #=> 2
17
- #
18
- # @example Literal by Regexp
19
- # parser = CommandParser.new(/^RE\d+$/)
20
- # parsed = parser.parse("RE44+20") #=> <CommandParser::Parsed>
21
- #
22
- # parsed.command #=> "RE44"
23
- # parsed.modify_number #=> 20
24
- class CommandParser < ArithmeticEvaluator
25
- # @param literals [Array<String, Regexp>]
26
- def initialize(*literals)
27
- @literals = literals
28
- @round_type = RoundType::FLOOR
29
- @allowed_cmp_op = nil
30
-
31
- @enabled_question_target = false
32
- end
33
-
34
- # パース結果
35
- class Parsed
36
- # @return [String]
37
- attr_accessor :command
38
-
39
- # @return [Integer, nil]
40
- attr_accessor :critical
41
-
42
- # @return [Integer, nil]
43
- attr_accessor :fumble
44
-
45
- # @return [Integer, nil]
46
- attr_accessor :dollar
47
-
48
- # @return [Integer]
49
- attr_accessor :modify_number
50
-
51
- # @return [Symbol, nil]
52
- attr_accessor :cmp_op
53
-
54
- # @return [Integer, nil]
55
- attr_accessor :target_number
56
-
57
- # @param value [Boolean]
58
- # @return [Boolean]
59
- attr_writer :question_target
60
-
61
- def initialize
62
- @critical = nil
63
- @fumble = nil
64
- @dollar = nil
65
- @cmp_op = nil
66
- @target_number = nil
67
- @question_target = false
68
- end
69
-
70
- # @return [Boolean]
71
- def question_target?
72
- @question_target
73
- end
74
-
75
- # @param suffix_position [Symbol] クリティカルなどの表示位置
76
- # @return [String]
77
- def to_s(suffix_position = :after_command)
78
- c = @critical ? "@#{@critical}" : nil
79
- f = @fumble ? "##{@fumble}" : nil
80
- d = @dollar ? "$#{@dollar}" : nil
81
- m = Format.modifier(@modify_number)
82
- target = @question_target ? "?" : @target_number
83
-
84
- case suffix_position
85
- when :after_command
86
- [@command, c, f, d, m, @cmp_op, target].join()
87
- when :after_modify_number
88
- [@command, m, c, f, d, @cmp_op, target].join()
89
- when :after_target_number
90
- [@command, m, @cmp_op, target, c, f, d].join()
91
- end
92
- end
93
- end
94
-
95
- # 特定の比較演算子のみ許可するようにする。
96
- # 比較演算子なしを許可する場合には nil を指定してください。
97
- #
98
- # @param cmp_op [Array<Symbol, nil>] 許可する比較演算子の一覧
99
- # @return [self]
100
- def allow_cmp_op(*cmp_op)
101
- @allowed_cmp_op = cmp_op
102
- self
103
- end
104
-
105
- # 目標値 "?" を許容する
106
- #
107
- # @return [self]
108
- def enable_question_target
109
- @enabled_question_target = true
110
- self
111
- end
112
-
113
- # 式をパースする
114
- #
115
- # @param expr [String]
116
- # @param round_type [Symbol]
117
- # @return [CommandParser::Parsed, nil]
118
- def parse(expr, round_type = RoundType::FLOOR)
119
- @tokens = tokenize(expr)
120
- @idx = 0
121
- @error = false
122
- @round_type = round_type
123
-
124
- @parsed = Parsed.new()
125
-
126
- lhs()
127
- if @error
128
- return nil
129
- end
130
-
131
- @parsed.cmp_op = take_cmp_op()
132
- rhs() if @parsed.cmp_op
133
-
134
- if @idx < @tokens.size || @error
135
- return nil
136
- end
137
-
138
- return @parsed
139
- end
140
-
141
- private
142
-
143
- # @return [Array<String>]
144
- def tokenize(expr)
145
- expr.gsub(%r{[\(\)\+\-*/@#\$]|[<>!=]+}) { |e| " #{e} " }.split(" ")
146
- end
147
-
148
- def lhs
149
- command = take()
150
- unless literal?(command)
151
- @error = true
152
- return
153
- end
154
-
155
- command_suffix()
156
-
157
- ret = 0
158
- loop do
159
- if consume("+")
160
- ret += mul()
161
- elsif consume("-")
162
- ret -= mul()
163
- else
164
- break
165
- end
166
- end
167
-
168
- command_suffix()
169
-
170
- @parsed.command = command
171
- @parsed.modify_number = ret
172
- end
173
-
174
- def command_suffix
175
- loop do
176
- if consume("@")
177
- if @parsed.critical
178
- @error = true
179
- end
180
- @parsed.critical = unary()
181
- elsif consume("#")
182
- if @parsed.fumble
183
- @error = true
184
- end
185
- @parsed.fumble = unary()
186
- elsif consume("$")
187
- if @parsed.dollar
188
- @error = true
189
- end
190
- @parsed.dollar = unary()
191
- else
192
- break
193
- end
194
- end
195
- end
196
-
197
- def rhs
198
- if @enabled_question_target && consume("?")
199
- @parsed.question_target = true
200
- @parsed.target_number = 0
201
- else
202
- @parsed.question_target = false
203
- @parsed.target_number = expr()
204
- end
205
- end
206
-
207
- def literal?(command)
208
- @literals.each do |lit|
209
- case lit
210
- when String
211
- return true if command == lit
212
- when Regexp
213
- return true if command =~ lit
214
- end
215
- end
216
-
217
- return false
218
- end
219
-
220
- def take
221
- ret = @tokens[@idx]
222
- @idx += 1
223
-
224
- return ret
225
- end
226
-
227
- def take_cmp_op
228
- cmp_op = Normalize.comparison_operator(take())
229
- @error ||= denied_cmp_op?(cmp_op)
230
-
231
- return cmp_op
232
- end
233
-
234
- def denied_cmp_op?(cmp_op)
235
- if @allowed_cmp_op.nil?
236
- false
237
- else
238
- !@allowed_cmp_op.include?(cmp_op)
239
- end
240
- end
241
- end
242
- end
@@ -1,153 +0,0 @@
1
- class BCDice::CommonCommand::AddDice::Parser
2
- token NUMBER CMP_OP S D K H L U R PLUS MINUS ASTERISK SLASH PARENL PARENR QUESTION
3
-
4
- rule
5
- command: secret add
6
- {
7
- secret, lhs = val
8
- raise ParseError unless lhs.include_dice?
9
-
10
- result = Node::Command.new(secret, lhs)
11
- }
12
- | secret add CMP_OP target
13
- {
14
- secret, lhs, cmp_op, rhs = val
15
- raise ParseError if !lhs.include_dice? || rhs.include_dice? || cmp_op.nil?
16
-
17
- result = Node::Command.new(secret, lhs, cmp_op, rhs)
18
- }
19
-
20
- secret: /* none */
21
- { result = false }
22
- | S
23
- { result = true }
24
-
25
- target: add
26
- | QUESTION
27
- { result = Node::UndecidedTarget.instance }
28
-
29
- add: add PLUS mul
30
- {
31
- lhs = val[0]
32
- op, rhs = expand_negate(:+, val[2])
33
- result = Node::BinaryOp.new(lhs, op, rhs)
34
- }
35
- | add MINUS mul
36
- {
37
- lhs = val[0]
38
- op, rhs = expand_negate(:-, val[2])
39
- result = Node::BinaryOp.new(lhs, op, rhs)
40
- }
41
- | mul
42
-
43
- mul: mul ASTERISK unary
44
- {
45
- lhs = val[0]
46
- rhs = val[2]
47
- result = Node::BinaryOp.new(lhs, :*, rhs)
48
- }
49
- | mul SLASH unary round_type
50
- {
51
- lhs = val[0]
52
- rhs = val[2]
53
- divied_class = val[3]
54
- result = divied_class.new(lhs, rhs)
55
- }
56
- | unary
57
-
58
- round_type: /* none */
59
- { result = Node::DivideWithRoundingDown }
60
- | U
61
- { result = Node::DivideWithRoundingUp }
62
- | R
63
- { result = Node::DivideWithRoundingOff }
64
-
65
- unary: PLUS unary
66
- { result = val[1] }
67
- | MINUS unary
68
- {
69
- body = val[1]
70
- result = body.is_a?(Node::Negate) ? body.body : Node::Negate.new(body)
71
- }
72
- | dice
73
-
74
- dice: term D term
75
- {
76
- times = val[0]
77
- sides = val[2]
78
- raise ParseError if times.include_dice? || sides.include_dice?
79
-
80
- result = Node::DiceRoll.new(times, sides)
81
- }
82
- | term D
83
- {
84
- times = val[0]
85
- sides = Node::Number.new(6)
86
- raise ParseError if times.include_dice?
87
-
88
- result = Node::DiceRoll.new(times, sides)
89
- }
90
- | term D term filter_type term
91
- {
92
- times = val[0]
93
- sides = val[2]
94
- filter = val[3]
95
- n_filtering = val[4]
96
- raise ParseError if times.include_dice? || sides.include_dice? || n_filtering.include_dice?
97
-
98
- result = Node::DiceRollWithFilter.new(times, sides, n_filtering, filter)
99
- }
100
- | term
101
-
102
- filter_type: K H
103
- { result = Node::DiceRollWithFilter::KEEP_HIGHEST }
104
- | K L
105
- { result = Node::DiceRollWithFilter::KEEP_LOWEST }
106
- | D H
107
- { result = Node::DiceRollWithFilter::DROP_HIGHEST }
108
- | D L
109
- { result = Node::DiceRollWithFilter::DROP_LOWEST }
110
-
111
- term: PARENL add PARENR
112
- { result = Node::Parenthesis.new(val[1]) }
113
- | NUMBER
114
- { result = Node::Number.new(val[0]) }
115
- end
116
-
117
- ---- header
118
-
119
- require "bcdice/common_command/lexer"
120
- require "bcdice/common_command/add_dice/node"
121
-
122
- ---- inner
123
-
124
- def self.parse(source)
125
- new.parse(source)
126
- end
127
-
128
- def parse(source)
129
- @lexer = Lexer.new(source)
130
- do_parse()
131
- rescue ParseError
132
- nil
133
- end
134
-
135
- private
136
-
137
- def next_token
138
- @lexer.next_token
139
- end
140
-
141
- # 加減算の右辺が負数である場合に加減算を逆転させる
142
- def expand_negate(op, rhs)
143
- if rhs.is_a?(Node::Negate)
144
- if op == :+
145
- return [:-, rhs.body]
146
- elsif op == :-
147
- return [:+, rhs.body]
148
- end
149
- end
150
-
151
- [op, rhs]
152
- end
153
-
@@ -1,107 +0,0 @@
1
- class BCDice::CommonCommand::BarabaraDice::Parser
2
- token NUMBER B R U C F S PLUS MINUS ASTERISK SLASH PARENL PARENR BRACKETL BRACKETR LESS GREATER EQUAL NOT AT CMP_OP
3
-
4
- rule
5
- expr: secret notations target
6
- {
7
- result = Node::Command.new(
8
- secret: val[0],
9
- notations: val[1],
10
- cmp_op: val[2][:cmp_op],
11
- target_number: val[2][:target]
12
- )
13
- }
14
-
15
- secret: /* none */
16
- { result = false }
17
- | S
18
- { result = true }
19
-
20
- target: /* none */
21
- { result = {} }
22
- | CMP_OP add
23
- {
24
- cmp_op, target = val
25
- raise ParseError unless cmp_op
26
-
27
- result = {cmp_op: cmp_op, target: target}
28
- }
29
-
30
- notations: notations PLUS dice
31
- {
32
- notations = val[0]
33
- notations.push(val[2])
34
- result = notations
35
- }
36
- | dice
37
- { result = [val[0]] }
38
-
39
- dice: term B term
40
- {
41
- times = val[0]
42
- sides = val[2]
43
- result = Node::Notation.new(times, sides)
44
- }
45
-
46
- add: add PLUS mul
47
- { result = Arithmetic::Node::BinaryOp.new(val[0], :+, val[2]) }
48
- | add MINUS mul
49
- { result = Arithmetic::Node::BinaryOp.new(val[0], :-, val[2]) }
50
- | mul
51
-
52
- mul: mul ASTERISK unary
53
- { result = Arithmetic::Node::BinaryOp.new(val[0], :*, val[2]) }
54
- | mul SLASH unary round_type
55
- {
56
- divied_class = val[3]
57
- result = divied_class.new(val[0], val[2])
58
- }
59
- | unary
60
-
61
- round_type: /* none */
62
- { result = Arithmetic::Node::DivideWithGameSystemDefault }
63
- | U
64
- { result = Arithmetic::Node::DivideWithCeil }
65
- | C
66
- { result = Arithmetic::Node::DivideWithCeil }
67
- | R
68
- { result = Arithmetic::Node::DivideWithRound }
69
- | F
70
- { result = Arithmetic::Node::DivideWithFloor }
71
-
72
- unary: PLUS unary
73
- { result = val[1] }
74
- | MINUS unary
75
- { result = Arithmetic::Node::Negative.new(val[1]) }
76
- | term
77
-
78
- term: PARENL add PARENR
79
- { result = val[1] }
80
- | NUMBER
81
- { result = Arithmetic::Node::Number.new(val[0]) }
82
- end
83
-
84
- ---- header
85
-
86
- require "bcdice/common_command/lexer"
87
- require "bcdice/common_command/reroll_dice/node"
88
- require "bcdice/arithmetic/node"
89
-
90
- ---- inner
91
-
92
- def self.parse(source)
93
- new.parse(source)
94
- end
95
-
96
- def parse(source)
97
- @lexer = Lexer.new(source)
98
- do_parse()
99
- rescue ParseError
100
- nil
101
- end
102
-
103
- private
104
-
105
- def next_token
106
- @lexer.next_token
107
- end