jkf 0.4.3 → 0.5.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 +4 -4
- data/.github/workflows/ci.yml +16 -0
- data/.rubocop.yml +46 -990
- data/.rubocop_todo.yml +1 -5
- data/CHANGELOG.md +63 -0
- data/Gemfile +11 -9
- data/Guardfile +3 -3
- data/README.en.md +28 -15
- data/README.md +9 -5
- data/Rakefile +7 -2
- data/bench.rb +12 -0
- data/bin/console +4 -4
- data/jkf.gemspec +14 -12
- data/lib/jkf/converter/base.rb +12 -10
- data/lib/jkf/converter/csa.rb +141 -150
- data/lib/jkf/converter/ki2.rb +93 -91
- data/lib/jkf/converter/kif.rb +105 -99
- data/lib/jkf/converter/kifuable.rb +160 -160
- data/lib/jkf/converter.rb +6 -8
- data/lib/jkf/parser/base.rb +81 -95
- data/lib/jkf/parser/csa.rb +652 -667
- data/lib/jkf/parser/ki2.rb +332 -338
- data/lib/jkf/parser/kif.rb +468 -485
- data/lib/jkf/parser/kifuable.rb +500 -518
- data/lib/jkf/parser.rb +5 -7
- data/lib/jkf/version.rb +1 -2
- data/lib/jkf.rb +6 -6
- data/manifest.scm +143 -0
- data/po/all.pot +176 -0
- data/po/en.po +199 -0
- data/po4a.cfg +11 -0
- metadata +13 -7
- data/.codeclimate.yml +0 -28
- data/.travis.yml +0 -9
data/lib/jkf/parser/kifuable.rb
CHANGED
@@ -1,243 +1,243 @@
|
|
1
|
-
module Jkf
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
else
|
14
|
-
@current_pos = s1
|
15
|
-
end
|
16
|
-
s2 = @current_pos
|
17
|
-
if match_str("+") != :failed
|
18
|
-
parse_nonls
|
19
|
-
@current_pos = s2 if parse_nl == :failed
|
20
|
-
else
|
21
|
-
@current_pos = s2
|
22
|
-
end
|
23
|
-
s4 = parse_ikkatsuline
|
24
|
-
if s4 != :failed
|
25
|
-
s3 = []
|
26
|
-
while s4 != :failed
|
27
|
-
s3 << s4
|
28
|
-
s4 = parse_ikkatsuline
|
29
|
-
end
|
30
|
-
else
|
31
|
-
s3 = :failed
|
32
|
-
end
|
33
|
-
if s3 != :failed
|
34
|
-
s4 = @current_pos
|
35
|
-
if match_str("+") != :failed
|
1
|
+
module Jkf
|
2
|
+
module Parser
|
3
|
+
# Intersection of KIF and KI2
|
4
|
+
module Kifuable
|
5
|
+
protected
|
6
|
+
|
7
|
+
# initialboard : (" " nonls nl)? ("+" nonls nl)? ikkatsuline+ ("+" nonls nl)?
|
8
|
+
def parse_initialboard
|
9
|
+
s0 = s1 = @scanner.pos
|
10
|
+
if match_space == :failed
|
11
|
+
@scanner.pos = s1
|
12
|
+
else
|
36
13
|
parse_nonls
|
37
|
-
|
14
|
+
s2 = parse_nl
|
15
|
+
@scanner.pos = s1 if s2 == :failed
|
16
|
+
end
|
17
|
+
s2 = @scanner.pos
|
18
|
+
if match_str('+') == :failed
|
19
|
+
@scanner.pos = s2
|
38
20
|
else
|
39
|
-
|
21
|
+
parse_nonls
|
22
|
+
@scanner.pos = s2 if parse_nl == :failed
|
40
23
|
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
# ikkatsuline : "|" masu:masu+ "|" nonls! nl
|
50
|
-
def parse_ikkatsuline
|
51
|
-
s0 = @current_pos
|
52
|
-
if match_str("|") != :failed
|
53
|
-
s3 = parse_masu
|
54
|
-
if s3 != :failed
|
55
|
-
s2 = []
|
56
|
-
while s3 != :failed
|
57
|
-
s2 << s3
|
58
|
-
s3 = parse_masu
|
24
|
+
s4 = parse_ikkatsuline
|
25
|
+
if s4 == :failed
|
26
|
+
s3 = :failed
|
27
|
+
else
|
28
|
+
s3 = []
|
29
|
+
while s4 != :failed
|
30
|
+
s3 << s4
|
31
|
+
s4 = parse_ikkatsuline
|
59
32
|
end
|
33
|
+
end
|
34
|
+
if s3 == :failed
|
35
|
+
@scanner.pos = s0
|
36
|
+
:failed
|
60
37
|
else
|
61
|
-
|
38
|
+
s4 = @scanner.pos
|
39
|
+
if match_str('+') == :failed
|
40
|
+
@scanner.pos = s4
|
41
|
+
else
|
42
|
+
parse_nonls
|
43
|
+
@scanner.pos = s4 if parse_nl == :failed
|
44
|
+
end
|
45
|
+
@reported_pos = s0
|
46
|
+
transform_initialboard(s3)
|
62
47
|
end
|
63
|
-
|
64
|
-
|
48
|
+
end
|
49
|
+
|
50
|
+
# ikkatsuline : "|" masu:masu+ "|" nonls! nl
|
51
|
+
def parse_ikkatsuline
|
52
|
+
s0 = @scanner.pos
|
53
|
+
if match_str('|') == :failed
|
54
|
+
@scanner.pos = s0
|
55
|
+
s0 = :failed
|
56
|
+
else
|
57
|
+
s3 = parse_masu
|
58
|
+
if s3 == :failed
|
59
|
+
s2 = :failed
|
60
|
+
else
|
61
|
+
s2 = []
|
62
|
+
while s3 != :failed
|
63
|
+
s2 << s3
|
64
|
+
s3 = parse_masu
|
65
|
+
end
|
66
|
+
end
|
67
|
+
if s2 == :failed
|
68
|
+
@scanner.pos = s0
|
69
|
+
s0 = :failed
|
70
|
+
elsif match_str('|') != :failed
|
65
71
|
s4 = parse_nonls!
|
66
|
-
if s4
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
s0 = :failed
|
73
|
-
end
|
72
|
+
if s4 == :failed
|
73
|
+
@scanner.pos = s0
|
74
|
+
s0 = :failed
|
75
|
+
elsif parse_nl != :failed
|
76
|
+
@reported_pos = s0
|
77
|
+
s0 = s2
|
74
78
|
else
|
75
|
-
@
|
79
|
+
@scanner.pos = s0
|
76
80
|
s0 = :failed
|
77
81
|
end
|
78
82
|
else
|
79
|
-
@
|
83
|
+
@scanner.pos = s0
|
80
84
|
s0 = :failed
|
81
85
|
end
|
82
|
-
else
|
83
|
-
@current_pos = s0
|
84
|
-
s0 = :failed
|
85
86
|
end
|
86
|
-
else
|
87
|
-
@current_pos = s0
|
88
|
-
s0 = :failed
|
89
|
-
end
|
90
87
|
|
91
|
-
|
92
|
-
|
88
|
+
s0
|
89
|
+
end
|
93
90
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
if s2 != :failed
|
101
|
-
@reported_pos = s0
|
102
|
-
s0 = { "color" => s1, "kind" => s2 }
|
103
|
-
else
|
104
|
-
@current_pos = s0
|
91
|
+
# masu : teban piece | " ・"
|
92
|
+
def parse_masu
|
93
|
+
s0 = @scanner.pos
|
94
|
+
s1 = parse_teban
|
95
|
+
if s1 == :failed
|
96
|
+
@scanner.pos = s0
|
105
97
|
s0 = :failed
|
98
|
+
else
|
99
|
+
s2 = parse_piece
|
100
|
+
if s2 == :failed
|
101
|
+
@scanner.pos = s0
|
102
|
+
s0 = :failed
|
103
|
+
else
|
104
|
+
@reported_pos = s0
|
105
|
+
s0 = { 'color' => s1, 'kind' => s2 }
|
106
|
+
end
|
106
107
|
end
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
@reported_pos = s0
|
116
|
-
s1 = {}
|
108
|
+
if s0 == :failed
|
109
|
+
s0 = @scanner.pos
|
110
|
+
s1 = match_str(' ・')
|
111
|
+
if s1 != :failed
|
112
|
+
@reported_pos = s0
|
113
|
+
s1 = {}
|
114
|
+
end
|
115
|
+
s0 = s1
|
117
116
|
end
|
118
|
-
s0 = s1
|
119
|
-
end
|
120
117
|
|
121
|
-
|
122
|
-
|
118
|
+
s0
|
119
|
+
end
|
123
120
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
if s1 != :failed
|
133
|
-
@reported_pos = s0
|
134
|
-
s1 = 0
|
135
|
-
end
|
136
|
-
s0 = s1
|
137
|
-
if s0 == :failed
|
138
|
-
s0 = @current_pos
|
139
|
-
s1 = match_str("v")
|
140
|
-
s1 = match_str("V") if s1 == :failed
|
121
|
+
# teban : (" " | "+" | "^") | ("v" | "V")
|
122
|
+
def parse_teban
|
123
|
+
s0 = @scanner.pos
|
124
|
+
s1 = match_space
|
125
|
+
if s1 == :failed
|
126
|
+
s1 = match_str('+')
|
127
|
+
s1 = match_str('^') if s1 == :failed
|
128
|
+
end
|
141
129
|
if s1 != :failed
|
142
130
|
@reported_pos = s0
|
143
|
-
s1 =
|
131
|
+
s1 = 0
|
144
132
|
end
|
145
133
|
s0 = s1
|
134
|
+
if s0 == :failed
|
135
|
+
s0 = @scanner.pos
|
136
|
+
s1 = match_str('v')
|
137
|
+
s1 = match_str('V') if s1 == :failed
|
138
|
+
if s1 != :failed
|
139
|
+
@reported_pos = s0
|
140
|
+
s1 = 1
|
141
|
+
end
|
142
|
+
s0 = s1
|
143
|
+
end
|
144
|
+
s0
|
146
145
|
end
|
147
|
-
s0
|
148
|
-
end
|
149
146
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
s3 = parse_nl
|
157
|
-
if s3 != :failed
|
158
|
-
s0 = [s1, s2, s3]
|
159
|
-
else
|
160
|
-
@current_pos = s0
|
147
|
+
# pointer : "&" nonls nl
|
148
|
+
def parse_pointer
|
149
|
+
s0 = @scanner.pos
|
150
|
+
s1 = match_str('&')
|
151
|
+
if s1 == :failed
|
152
|
+
@scanner.pos = s0
|
161
153
|
s0 = :failed
|
154
|
+
else
|
155
|
+
s2 = parse_nonls
|
156
|
+
s3 = parse_nl
|
157
|
+
if s3 == :failed
|
158
|
+
@scanner.pos = s0
|
159
|
+
s0 = :failed
|
160
|
+
else
|
161
|
+
s0 = [s1, s2, s3]
|
162
|
+
end
|
162
163
|
end
|
163
|
-
|
164
|
-
@current_pos = s0
|
165
|
-
s0 = :failed
|
164
|
+
s0
|
166
165
|
end
|
167
|
-
s0
|
168
|
-
end
|
169
166
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
167
|
+
# num : [123456789]
|
168
|
+
def parse_num
|
169
|
+
s0 = @scanner.pos
|
170
|
+
s1 = match_regexp(/[123456789]/)
|
171
|
+
if s1 != :failed
|
172
|
+
@reported_pos = s0
|
173
|
+
s1 = zen2n(s1)
|
174
|
+
end
|
175
|
+
s1
|
177
176
|
end
|
178
|
-
s1
|
179
|
-
end
|
180
177
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
178
|
+
# numkan : [一二三四五六七八九]
|
179
|
+
def parse_numkan
|
180
|
+
s0 = @scanner.pos
|
181
|
+
s1 = match_regexp(/[一二三四五六七八九]/)
|
182
|
+
if s1 != :failed
|
183
|
+
@reported_pos = s0
|
184
|
+
s1 = kan2n(s1)
|
185
|
+
end
|
186
|
+
s1
|
188
187
|
end
|
189
|
-
s1
|
190
|
-
end
|
191
188
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
189
|
+
# piece : "成"? [歩香桂銀金角飛王玉と杏圭全馬竜龍]
|
190
|
+
def parse_piece
|
191
|
+
s0 = @scanner.pos
|
192
|
+
s1 = match_str('成')
|
193
|
+
s1 = '' if s1 == :failed
|
194
|
+
s2 = match_regexp(/[歩香桂銀金角飛王玉と杏圭全馬竜龍]/)
|
195
|
+
if s2 == :failed
|
196
|
+
@scanner.pos = s0
|
197
|
+
:failed
|
198
|
+
else
|
199
|
+
@reported_pos = s0
|
200
|
+
kind2csa(s1 + s2)
|
201
|
+
end
|
204
202
|
end
|
205
|
-
end
|
206
203
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
end
|
231
|
-
else
|
232
|
-
@current_pos = s4
|
233
|
-
s4 = :failed
|
234
|
-
end
|
235
|
-
else
|
236
|
-
@current_pos = s4
|
204
|
+
# result : "まで" [0-9]+ "手" (
|
205
|
+
# "で" (turn "手の" (result_toryo | result_illegal)) |
|
206
|
+
# result_timeup | result_chudan | result_jishogi |
|
207
|
+
# result_sennichite | result_tsumi | result_fuzumi
|
208
|
+
# ) nl
|
209
|
+
def parse_result
|
210
|
+
s0 = @scanner.pos
|
211
|
+
if match_str('まで') == :failed
|
212
|
+
@scanner.pos = s0
|
213
|
+
:failed
|
214
|
+
else
|
215
|
+
s2 = match_digits!
|
216
|
+
if s2 == :failed
|
217
|
+
@scanner.pos = s0
|
218
|
+
:failed
|
219
|
+
elsif match_str('手') != :failed
|
220
|
+
s4 = @scanner.pos
|
221
|
+
if match_str('で') == :failed
|
222
|
+
@scanner.pos = s4
|
223
|
+
s4 = :failed
|
224
|
+
elsif parse_turn != :failed
|
225
|
+
if match_str('手の') == :failed
|
226
|
+
@scanner.pos = s4
|
237
227
|
s4 = :failed
|
228
|
+
else
|
229
|
+
s8 = parse_result_toryo
|
230
|
+
s8 = parse_result_illegal if s8 == :failed
|
231
|
+
s4 = if s8 == :failed
|
232
|
+
@scanner.pos = s4
|
233
|
+
:failed
|
234
|
+
else
|
235
|
+
@reported_pos = s4
|
236
|
+
s8
|
237
|
+
end
|
238
238
|
end
|
239
239
|
else
|
240
|
-
@
|
240
|
+
@scanner.pos = s4
|
241
241
|
s4 = :failed
|
242
242
|
end
|
243
243
|
if s4 == :failed
|
@@ -256,390 +256,372 @@ module Jkf::Parser
|
|
256
256
|
end
|
257
257
|
end
|
258
258
|
end
|
259
|
-
if s4
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
:failed
|
266
|
-
end
|
259
|
+
if s4 == :failed
|
260
|
+
@scanner.pos = s0
|
261
|
+
:failed
|
262
|
+
elsif parse_nl != :failed || eos?
|
263
|
+
@reported_pos = s0
|
264
|
+
s4
|
267
265
|
else
|
268
|
-
@
|
266
|
+
@scanner.pos = s0
|
269
267
|
:failed
|
270
268
|
end
|
271
269
|
else
|
272
|
-
@
|
270
|
+
@scanner.pos = s0
|
273
271
|
:failed
|
274
272
|
end
|
275
|
-
else
|
276
|
-
@current_pos = s0
|
277
|
-
:failed
|
278
273
|
end
|
279
|
-
else
|
280
|
-
@current_pos = s0
|
281
|
-
:failed
|
282
274
|
end
|
283
|
-
end
|
284
275
|
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
276
|
+
# result_toryo : "勝ち"
|
277
|
+
def parse_result_toryo
|
278
|
+
s0 = @scanner.pos
|
279
|
+
s1 = match_str('勝ち')
|
280
|
+
if s1 == :failed
|
281
|
+
@scanner.pos = s0
|
282
|
+
:failed
|
283
|
+
else
|
284
|
+
@reported_pos = s0
|
285
|
+
'TORYO'
|
286
|
+
end
|
295
287
|
end
|
296
|
-
end
|
297
288
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
s11 =
|
307
|
-
end
|
308
|
-
s10 = s11
|
309
|
-
if s10 == :failed
|
310
|
-
s10 = @current_pos
|
311
|
-
s11 = match_str("負け")
|
289
|
+
# result_illegal : "反則" ("勝ち" | "負け")
|
290
|
+
def parse_result_illegal
|
291
|
+
s0 = @scanner.pos
|
292
|
+
if match_str('反則') == :failed
|
293
|
+
@scanner.pos = s0
|
294
|
+
:failed
|
295
|
+
else
|
296
|
+
s10 = @scanner.pos
|
297
|
+
s11 = match_str('勝ち')
|
312
298
|
if s11 != :failed
|
313
299
|
@reported_pos = s10
|
314
|
-
s11 =
|
300
|
+
s11 = 'ILLEGAL_ACTION'
|
315
301
|
end
|
316
302
|
s10 = s11
|
303
|
+
if s10 == :failed
|
304
|
+
s10 = @scanner.pos
|
305
|
+
s11 = match_str('負け')
|
306
|
+
if s11 != :failed
|
307
|
+
@reported_pos = s10
|
308
|
+
s11 = 'ILLEGAL_MOVE'
|
309
|
+
end
|
310
|
+
s10 = s11
|
311
|
+
end
|
312
|
+
if s10 == :failed
|
313
|
+
@scanner.pos = s0
|
314
|
+
:failed
|
315
|
+
else
|
316
|
+
@reported_pos = s0
|
317
|
+
s10
|
318
|
+
end
|
317
319
|
end
|
318
|
-
|
320
|
+
end
|
321
|
+
|
322
|
+
# result_timeup : "で時間切れにより" turn "手の勝ち"
|
323
|
+
def parse_result_timeup
|
324
|
+
s0 = @scanner.pos
|
325
|
+
if match_str('で時間切れにより') != :failed && parse_turn != :failed && match_str('手の勝ち') != :failed
|
319
326
|
@reported_pos = s0
|
320
|
-
|
327
|
+
'TIME_UP'
|
321
328
|
else
|
322
|
-
@
|
329
|
+
@scanner.pos = s0
|
323
330
|
:failed
|
324
331
|
end
|
325
|
-
else
|
326
|
-
@current_pos = s0
|
327
|
-
:failed
|
328
332
|
end
|
329
|
-
end
|
330
333
|
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
if
|
336
|
-
|
337
|
-
@reported_pos = s0
|
338
|
-
"TIME_UP"
|
339
|
-
else
|
340
|
-
@current_pos = s0
|
341
|
-
:failed
|
342
|
-
end
|
343
|
-
else
|
344
|
-
@current_pos = s0
|
334
|
+
# result_chudan : "で中断"
|
335
|
+
def parse_result_chudan
|
336
|
+
s0 = @scanner.pos
|
337
|
+
s1 = match_str('で中断')
|
338
|
+
if s1 == :failed
|
339
|
+
@scanner.pos = s0
|
345
340
|
:failed
|
341
|
+
else
|
342
|
+
@reported_pos = s0
|
343
|
+
'CHUDAN'
|
346
344
|
end
|
347
|
-
else
|
348
|
-
@current_pos = s0
|
349
|
-
:failed
|
350
345
|
end
|
351
|
-
end
|
352
346
|
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
347
|
+
# result_jishogi : "で持将棋"
|
348
|
+
def parse_result_jishogi
|
349
|
+
s0 = @scanner.pos
|
350
|
+
s1 = match_str('で持将棋')
|
351
|
+
if s1 == :failed
|
352
|
+
@scanner.pos = s0
|
353
|
+
:failed
|
354
|
+
else
|
355
|
+
@reported_pos = s0
|
356
|
+
'JISHOGI'
|
357
|
+
end
|
363
358
|
end
|
364
|
-
end
|
365
359
|
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
360
|
+
# result_sennichite : "で千日手"
|
361
|
+
def parse_result_sennichite
|
362
|
+
s0 = @scanner.pos
|
363
|
+
s1 = match_str('で千日手')
|
364
|
+
if s1 == :failed
|
365
|
+
@scanner.pos = s0
|
366
|
+
:failed
|
367
|
+
else
|
368
|
+
@reported_pos = s0
|
369
|
+
'SENNICHITE'
|
370
|
+
end
|
376
371
|
end
|
377
|
-
end
|
378
372
|
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
373
|
+
# result_tsumi : "で"? "詰" "み"?
|
374
|
+
def parse_result_tsumi
|
375
|
+
s0 = @scanner.pos
|
376
|
+
match_str('で')
|
377
|
+
if match_str('詰') == :failed
|
378
|
+
@scanner.pos = s0
|
379
|
+
:failed
|
380
|
+
else
|
381
|
+
match_str('み')
|
382
|
+
@reported_pos = s0
|
383
|
+
'TSUMI'
|
384
|
+
end
|
389
385
|
end
|
390
|
-
end
|
391
386
|
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
387
|
+
# result_fuzumi : "で不詰"
|
388
|
+
def parse_result_fuzumi
|
389
|
+
s0 = @scanner.pos
|
390
|
+
s1 = match_str('で不詰')
|
391
|
+
if s1 == :failed
|
392
|
+
@scanner.pos = s0
|
393
|
+
:failed
|
394
|
+
else
|
395
|
+
@reported_pos = s0
|
396
|
+
'FUZUMI'
|
397
|
+
end
|
403
398
|
end
|
404
|
-
end
|
405
399
|
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
400
|
+
# skipline : "#" nonls newline
|
401
|
+
def parse_skipline
|
402
|
+
s0 = @scanner.pos
|
403
|
+
s1 = match_str('#')
|
404
|
+
if s1 == :failed
|
405
|
+
@scanner.pos = s0
|
406
|
+
s0 = :failed
|
407
|
+
else
|
408
|
+
s2 = parse_nonls
|
409
|
+
s3 = parse_newline
|
410
|
+
s0 = if s3 == :failed
|
411
|
+
@scanner.pos = s0
|
412
|
+
:failed
|
413
|
+
else
|
414
|
+
[s1, s2, s3]
|
415
|
+
end
|
416
|
+
end
|
417
|
+
s0
|
416
418
|
end
|
417
|
-
end
|
418
|
-
|
419
|
-
# skipline : "#" nonls newline
|
420
|
-
def parse_skipline
|
421
|
-
s0 = @current_pos
|
422
|
-
s1 = match_str("#")
|
423
|
-
if s1 != :failed
|
424
|
-
s2 = parse_nonls
|
425
|
-
s3 = parse_newline
|
426
|
-
s0 = if s3 != :failed
|
427
|
-
[s1, s2, s3]
|
428
|
-
else
|
429
|
-
@current_pos = s0
|
430
|
-
:failed
|
431
|
-
end
|
432
|
-
else
|
433
|
-
@current_pos = s0
|
434
|
-
s0 = :failed
|
435
|
-
end
|
436
|
-
s0
|
437
|
-
end
|
438
419
|
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
end
|
443
|
-
|
444
|
-
# newline : whitespace* ("\n" | "\r" "\n"?)
|
445
|
-
def parse_newline
|
446
|
-
s0 = @current_pos
|
447
|
-
s1 = []
|
448
|
-
s2 = parse_whitespace
|
449
|
-
while s2 != :failed
|
450
|
-
s1 << s2
|
451
|
-
s2 = parse_whitespace
|
420
|
+
# whitespace : " " | "\t"
|
421
|
+
def parse_whitespace
|
422
|
+
match_regexp(/[ \t]/)
|
452
423
|
end
|
453
|
-
s2 = match_str("\n")
|
454
|
-
if s2 == :failed
|
455
|
-
s2 = @current_pos
|
456
|
-
s3 = match_str("\r")
|
457
|
-
s2 = if s3 != :failed
|
458
|
-
s4 = match_str("\n")
|
459
|
-
s4 = nil if s4 == :failed
|
460
|
-
[s3, s4]
|
461
|
-
else
|
462
|
-
@current_pos = s2
|
463
|
-
:failed
|
464
|
-
end
|
465
|
-
end
|
466
|
-
if s2 != :failed
|
467
|
-
[s1, s2]
|
468
|
-
else
|
469
|
-
@current_pos = s0
|
470
|
-
:failed
|
471
|
-
end
|
472
|
-
end
|
473
424
|
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
s2 = parse_newline
|
478
|
-
if s2 != :failed
|
425
|
+
# newline : whitespace* ("\n" | "\r" "\n"?)
|
426
|
+
def parse_newline
|
427
|
+
s0 = @scanner.pos
|
479
428
|
s1 = []
|
429
|
+
s2 = parse_whitespace
|
480
430
|
while s2 != :failed
|
481
431
|
s1 << s2
|
482
|
-
s2 =
|
432
|
+
s2 = parse_whitespace
|
433
|
+
end
|
434
|
+
s2 = match_str("\n")
|
435
|
+
if s2 == :failed
|
436
|
+
s2 = @scanner.pos
|
437
|
+
s3 = match_str("\r")
|
438
|
+
s2 = if s3 == :failed
|
439
|
+
@scanner.pos = s2
|
440
|
+
:failed
|
441
|
+
else
|
442
|
+
s4 = match_str("\n")
|
443
|
+
s4 = nil if s4 == :failed
|
444
|
+
[s3, s4]
|
445
|
+
end
|
446
|
+
end
|
447
|
+
if s2 == :failed
|
448
|
+
@scanner.pos = s0
|
449
|
+
:failed
|
450
|
+
else
|
451
|
+
[s1, s2]
|
483
452
|
end
|
484
|
-
else
|
485
|
-
s1 = :failed
|
486
453
|
end
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
454
|
+
|
455
|
+
# nl : newline+ skipline*
|
456
|
+
def parse_nl
|
457
|
+
s0 = @scanner.pos
|
458
|
+
s2 = parse_newline
|
459
|
+
if s2 == :failed
|
460
|
+
s1 = :failed
|
461
|
+
else
|
462
|
+
s1 = []
|
463
|
+
while s2 != :failed
|
464
|
+
s1 << s2
|
465
|
+
s2 = parse_newline
|
466
|
+
end
|
467
|
+
end
|
468
|
+
if s1 == :failed
|
469
|
+
@scanner.pos = s0
|
470
|
+
:failed
|
471
|
+
else
|
472
|
+
s2 = []
|
492
473
|
s3 = parse_skipline
|
474
|
+
while s3 != :failed
|
475
|
+
s2 << s3
|
476
|
+
s3 = parse_skipline
|
477
|
+
end
|
478
|
+
[s1, s2]
|
493
479
|
end
|
494
|
-
[s1, s2]
|
495
|
-
else
|
496
|
-
@current_pos = s0
|
497
|
-
:failed
|
498
480
|
end
|
499
|
-
end
|
500
481
|
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
482
|
+
# nonl :
|
483
|
+
def parse_nonl
|
484
|
+
match_regexp(/[^\r\n]/)
|
485
|
+
end
|
505
486
|
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
matched = parse_nonl
|
510
|
-
while matched != :failed
|
511
|
-
stack << matched
|
487
|
+
# nonls : nonl*
|
488
|
+
def parse_nonls
|
489
|
+
stack = []
|
512
490
|
matched = parse_nonl
|
491
|
+
while matched != :failed
|
492
|
+
stack << matched
|
493
|
+
matched = parse_nonl
|
494
|
+
end
|
495
|
+
stack
|
513
496
|
end
|
514
|
-
stack
|
515
|
-
end
|
516
497
|
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
498
|
+
# nonls! : nonl+
|
499
|
+
def parse_nonls!
|
500
|
+
matched = parse_nonls
|
501
|
+
if matched.empty?
|
502
|
+
:failed
|
503
|
+
else
|
504
|
+
matched
|
505
|
+
end
|
524
506
|
end
|
525
|
-
end
|
526
507
|
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
508
|
+
# transform header-data to jkf
|
509
|
+
def transform_root_header_data(ret)
|
510
|
+
if ret['header']['手番']
|
511
|
+
ret['initial']['data']['color'] = '下先'.include?(ret['header']['手番']) ? 0 : 1
|
512
|
+
ret['header'].delete('手番')
|
513
|
+
else
|
514
|
+
ret['initial']['data']['color'] = 0
|
515
|
+
end
|
516
|
+
ret['initial']['data']['hands'] = [
|
517
|
+
make_hand(ret['header']['先手の持駒'] || ret['header']['下手の持駒']),
|
518
|
+
make_hand(ret['header']['後手の持駒'] || ret['header']['上手の持駒'])
|
519
|
+
]
|
520
|
+
%w(先手の持駒 下手の持駒 後手の持駒 上手の持駒).each do |key|
|
521
|
+
ret['header'].delete(key)
|
522
|
+
end
|
541
523
|
end
|
542
|
-
end
|
543
524
|
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
525
|
+
# transfrom forks to jkf
|
526
|
+
def transform_root_forks(forks, moves)
|
527
|
+
fork_stack = [{ 'te' => 0, 'moves' => moves }]
|
528
|
+
forks.each do |f|
|
529
|
+
now_fork = f
|
530
|
+
fork = fork_stack.pop
|
531
|
+
fork = fork_stack.pop while fork['te'] > now_fork['te']
|
532
|
+
move = fork['moves'][now_fork['te'] - fork['te']]
|
533
|
+
move['forks'] ||= []
|
534
|
+
move['forks'] << now_fork['moves']
|
535
|
+
fork_stack << fork
|
536
|
+
fork_stack << now_fork
|
537
|
+
end
|
556
538
|
end
|
557
|
-
end
|
558
539
|
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
540
|
+
# transform initialboard to jkf
|
541
|
+
def transform_initialboard(lines)
|
542
|
+
board = []
|
543
|
+
9.times do |i|
|
544
|
+
line = []
|
545
|
+
9.times do |j|
|
546
|
+
line << lines[j][8 - i]
|
547
|
+
end
|
548
|
+
board << line
|
566
549
|
end
|
567
|
-
board
|
550
|
+
{ 'preset' => 'OTHER', 'data' => { 'board' => board } }
|
568
551
|
end
|
569
|
-
{ "preset" => "OTHER", "data" => { "board" => board } }
|
570
|
-
end
|
571
552
|
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
553
|
+
# zenkaku number to number
|
554
|
+
def zen2n(s)
|
555
|
+
'0123456789'.index(s)
|
556
|
+
end
|
576
557
|
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
558
|
+
# kanji number to number (1)
|
559
|
+
def kan2n(s)
|
560
|
+
'〇一二三四五六七八九'.index(s)
|
561
|
+
end
|
581
562
|
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
563
|
+
# kanji number to number (2)
|
564
|
+
def kan2n2(s)
|
565
|
+
case s.length
|
566
|
+
when 1
|
567
|
+
'〇一二三四五六七八九十'.index(s)
|
568
|
+
when 2
|
569
|
+
'〇一二三四五六七八九十'.index(s[1]) + 10
|
570
|
+
else
|
571
|
+
raise '21以上の数値に対応していません'
|
572
|
+
end
|
591
573
|
end
|
592
|
-
end
|
593
574
|
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
575
|
+
# kanji piece-type to csa
|
576
|
+
def kind2csa(kind)
|
577
|
+
if kind[0] == '成'
|
578
|
+
{
|
579
|
+
'香' => 'NY',
|
580
|
+
'桂' => 'NK',
|
581
|
+
'銀' => 'NG'
|
582
|
+
}[kind[1]]
|
583
|
+
else
|
584
|
+
{
|
585
|
+
'歩' => 'FU',
|
586
|
+
'香' => 'KY',
|
587
|
+
'桂' => 'KE',
|
588
|
+
'銀' => 'GI',
|
589
|
+
'金' => 'KI',
|
590
|
+
'角' => 'KA',
|
591
|
+
'飛' => 'HI',
|
592
|
+
'玉' => 'OU',
|
593
|
+
'王' => 'OU',
|
594
|
+
'と' => 'TO',
|
595
|
+
'杏' => 'NY',
|
596
|
+
'圭' => 'NK',
|
597
|
+
'全' => 'NG',
|
598
|
+
'馬' => 'UM',
|
599
|
+
'竜' => 'RY',
|
600
|
+
'龍' => 'RY'
|
601
|
+
}[kind]
|
602
|
+
end
|
621
603
|
end
|
622
|
-
end
|
623
604
|
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
605
|
+
# preset string to jkf
|
606
|
+
def preset2str(preset)
|
607
|
+
{
|
608
|
+
'平手' => 'HIRATE',
|
609
|
+
'香落ち' => 'KY',
|
610
|
+
'右香落ち' => 'KY_R',
|
611
|
+
'角落ち' => 'KA',
|
612
|
+
'飛車落ち' => 'HI',
|
613
|
+
'飛香落ち' => 'HIKY',
|
614
|
+
'二枚落ち' => '2',
|
615
|
+
'三枚落ち' => '3',
|
616
|
+
'四枚落ち' => '4',
|
617
|
+
'五枚落ち' => '5',
|
618
|
+
'左五枚落ち' => '5_L',
|
619
|
+
'六枚落ち' => '6',
|
620
|
+
'八枚落ち' => '8',
|
621
|
+
'十枚落ち' => '10',
|
622
|
+
'その他' => 'OTHER'
|
623
|
+
}[preset.gsub(/\s/, '')]
|
624
|
+
end
|
643
625
|
end
|
644
626
|
end
|
645
627
|
end
|