jkf 0.5.0 → 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/.rubocop.yml +57 -0
- data/.rubocop_todo.yml +1 -454
- data/CHANGELOG.md +17 -0
- data/Gemfile +11 -11
- data/Guardfile +3 -3
- data/README.en.md +3 -4
- data/README.md +4 -2
- data/Rakefile +4 -4
- data/bench.rb +12 -0
- data/bin/console +4 -4
- data/jkf.gemspec +12 -13
- 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 +651 -654
- data/lib/jkf/parser/ki2.rb +331 -333
- data/lib/jkf/parser/kif.rb +467 -468
- data/lib/jkf/parser/kifuable.rb +511 -517
- data/lib/jkf/parser.rb +5 -7
- data/lib/jkf/version.rb +1 -2
- data/lib/jkf.rb +6 -6
- data/manifest.scm +1 -0
- data/po/all.pot +31 -25
- data/po/en.po +36 -37
- metadata +4 -3
data/lib/jkf/parser/kifuable.rb
CHANGED
@@ -1,633 +1,627 @@
|
|
1
|
-
module Jkf
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
parse_nonls
|
13
|
-
s2 = parse_nl
|
14
|
-
@current_pos = s1 if s2 == :failed
|
15
|
-
end
|
16
|
-
s2 = @current_pos
|
17
|
-
if match_str("+") == :failed
|
18
|
-
@current_pos = s2
|
19
|
-
else
|
20
|
-
parse_nonls
|
21
|
-
@current_pos = s2 if parse_nl == :failed
|
22
|
-
end
|
23
|
-
s4 = parse_ikkatsuline
|
24
|
-
if s4 == :failed
|
25
|
-
s3 = :failed
|
26
|
-
else
|
27
|
-
s3 = []
|
28
|
-
while s4 != :failed
|
29
|
-
s3 << s4
|
30
|
-
s4 = parse_ikkatsuline
|
31
|
-
end
|
32
|
-
end
|
33
|
-
if s3 == :failed
|
34
|
-
@current_pos = s0
|
35
|
-
:failed
|
36
|
-
else
|
37
|
-
s4 = @current_pos
|
38
|
-
if match_str("+") == :failed
|
39
|
-
@current_pos = s4
|
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
|
40
12
|
else
|
41
13
|
parse_nonls
|
42
|
-
|
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
|
20
|
+
else
|
21
|
+
parse_nonls
|
22
|
+
@scanner.pos = s2 if parse_nl == :failed
|
23
|
+
end
|
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
|
32
|
+
end
|
43
33
|
end
|
44
|
-
@reported_pos = s0
|
45
|
-
transform_initialboard(s3)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# ikkatsuline : "|" masu:masu+ "|" nonls! nl
|
50
|
-
def parse_ikkatsuline
|
51
|
-
s0 = @current_pos
|
52
|
-
if match_str("|") == :failed
|
53
|
-
@current_pos = s0
|
54
|
-
s0 = :failed
|
55
|
-
else
|
56
|
-
s3 = parse_masu
|
57
34
|
if s3 == :failed
|
58
|
-
|
35
|
+
@scanner.pos = s0
|
36
|
+
:failed
|
59
37
|
else
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
64
44
|
end
|
45
|
+
@reported_pos = s0
|
46
|
+
transform_initialboard(s3)
|
65
47
|
end
|
66
|
-
|
67
|
-
|
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
|
68
55
|
s0 = :failed
|
69
|
-
|
70
|
-
|
71
|
-
if
|
72
|
-
|
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
|
73
69
|
s0 = :failed
|
74
|
-
elsif
|
75
|
-
|
76
|
-
|
70
|
+
elsif match_str('|') != :failed
|
71
|
+
s4 = parse_nonls!
|
72
|
+
if s4 == :failed
|
73
|
+
@scanner.pos = s0
|
74
|
+
s0 = :failed
|
75
|
+
elsif parse_nl != :failed
|
76
|
+
@reported_pos = s0
|
77
|
+
s0 = s2
|
78
|
+
else
|
79
|
+
@scanner.pos = s0
|
80
|
+
s0 = :failed
|
81
|
+
end
|
77
82
|
else
|
78
|
-
@
|
83
|
+
@scanner.pos = s0
|
79
84
|
s0 = :failed
|
80
85
|
end
|
81
|
-
else
|
82
|
-
@current_pos = s0
|
83
|
-
s0 = :failed
|
84
86
|
end
|
85
|
-
end
|
86
87
|
|
87
|
-
|
88
|
-
|
88
|
+
s0
|
89
|
+
end
|
89
90
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
s0 = :failed
|
97
|
-
else
|
98
|
-
s2 = parse_piece
|
99
|
-
if s2 == :failed
|
100
|
-
@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
|
101
97
|
s0 = :failed
|
102
98
|
else
|
103
|
-
|
104
|
-
|
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
|
105
107
|
end
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
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
|
113
116
|
end
|
114
|
-
s0 = s1
|
115
|
-
end
|
116
117
|
|
117
|
-
|
118
|
-
|
118
|
+
s0
|
119
|
+
end
|
119
120
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
if s1 != :failed
|
129
|
-
@reported_pos = s0
|
130
|
-
s1 = 0
|
131
|
-
end
|
132
|
-
s0 = s1
|
133
|
-
if s0 == :failed
|
134
|
-
s0 = @current_pos
|
135
|
-
s1 = match_str("v")
|
136
|
-
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
|
137
129
|
if s1 != :failed
|
138
130
|
@reported_pos = s0
|
139
|
-
s1 =
|
131
|
+
s1 = 0
|
140
132
|
end
|
141
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
|
142
145
|
end
|
143
|
-
s0
|
144
|
-
end
|
145
146
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
s0 = :failed
|
153
|
-
else
|
154
|
-
s2 = parse_nonls
|
155
|
-
s3 = parse_nl
|
156
|
-
if s3 == :failed
|
157
|
-
@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
|
158
153
|
s0 = :failed
|
159
154
|
else
|
160
|
-
|
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
|
161
163
|
end
|
164
|
+
s0
|
162
165
|
end
|
163
|
-
s0
|
164
|
-
end
|
165
166
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
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
|
173
176
|
end
|
174
|
-
s1
|
175
|
-
end
|
176
177
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
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
|
184
187
|
end
|
185
|
-
s1
|
186
|
-
end
|
187
188
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
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
|
200
202
|
end
|
201
|
-
end
|
202
203
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
:failed
|
213
|
-
else
|
214
|
-
s2 = match_digits!
|
215
|
-
if s2 == :failed
|
216
|
-
@current_pos = s0
|
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
|
217
213
|
:failed
|
218
|
-
|
219
|
-
|
220
|
-
if
|
221
|
-
@
|
222
|
-
|
223
|
-
elsif
|
224
|
-
|
225
|
-
|
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
|
226
223
|
s4 = :failed
|
224
|
+
elsif parse_turn != :failed
|
225
|
+
if match_str('手の') == :failed
|
226
|
+
@scanner.pos = s4
|
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
|
+
end
|
227
239
|
else
|
228
|
-
|
229
|
-
|
230
|
-
s4 = if s8 == :failed
|
231
|
-
@current_pos = s4
|
232
|
-
:failed
|
233
|
-
else
|
234
|
-
@reported_pos = s4
|
235
|
-
s8
|
236
|
-
end
|
240
|
+
@scanner.pos = s4
|
241
|
+
s4 = :failed
|
237
242
|
end
|
238
|
-
else
|
239
|
-
@current_pos = s4
|
240
|
-
s4 = :failed
|
241
|
-
end
|
242
|
-
if s4 == :failed
|
243
|
-
s4 = parse_result_timeup
|
244
243
|
if s4 == :failed
|
245
|
-
s4 =
|
244
|
+
s4 = parse_result_timeup
|
246
245
|
if s4 == :failed
|
247
|
-
s4 =
|
246
|
+
s4 = parse_result_chudan
|
248
247
|
if s4 == :failed
|
249
|
-
s4 =
|
248
|
+
s4 = parse_result_jishogi
|
250
249
|
if s4 == :failed
|
251
|
-
s4 =
|
252
|
-
|
250
|
+
s4 = parse_result_sennichite
|
251
|
+
if s4 == :failed
|
252
|
+
s4 = parse_result_tsumi
|
253
|
+
s4 = parse_result_fuzumi if s4 == :failed
|
254
|
+
end
|
253
255
|
end
|
254
256
|
end
|
255
257
|
end
|
256
258
|
end
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
:failed
|
261
|
-
|
262
|
-
|
263
|
-
|
259
|
+
if s4 == :failed
|
260
|
+
@scanner.pos = s0
|
261
|
+
:failed
|
262
|
+
elsif parse_nl != :failed || eos?
|
263
|
+
@reported_pos = s0
|
264
|
+
s4
|
265
|
+
else
|
266
|
+
@scanner.pos = s0
|
267
|
+
:failed
|
268
|
+
end
|
264
269
|
else
|
265
|
-
@
|
270
|
+
@scanner.pos = s0
|
266
271
|
:failed
|
267
272
|
end
|
268
|
-
else
|
269
|
-
@current_pos = s0
|
270
|
-
:failed
|
271
273
|
end
|
272
274
|
end
|
273
|
-
end
|
274
275
|
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
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
|
285
287
|
end
|
286
|
-
end
|
287
288
|
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
if s11 != :failed
|
298
|
-
@reported_pos = s10
|
299
|
-
s11 = "ILLEGAL_ACTION"
|
300
|
-
end
|
301
|
-
s10 = s11
|
302
|
-
if s10 == :failed
|
303
|
-
s10 = @current_pos
|
304
|
-
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('勝ち')
|
305
298
|
if s11 != :failed
|
306
299
|
@reported_pos = s10
|
307
|
-
s11 =
|
300
|
+
s11 = 'ILLEGAL_ACTION'
|
308
301
|
end
|
309
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
|
310
319
|
end
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
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
|
315
326
|
@reported_pos = s0
|
316
|
-
|
327
|
+
'TIME_UP'
|
328
|
+
else
|
329
|
+
@scanner.pos = s0
|
330
|
+
:failed
|
317
331
|
end
|
318
332
|
end
|
319
|
-
end
|
320
333
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
elsif parse_turn != :failed
|
328
|
-
if match_str("手の勝ち") == :failed
|
329
|
-
@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
|
330
340
|
:failed
|
331
341
|
else
|
332
342
|
@reported_pos = s0
|
333
|
-
|
343
|
+
'CHUDAN'
|
334
344
|
end
|
335
|
-
else
|
336
|
-
@current_pos = s0
|
337
|
-
:failed
|
338
345
|
end
|
339
|
-
end
|
340
346
|
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
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
|
351
358
|
end
|
352
|
-
end
|
353
359
|
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
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
|
364
371
|
end
|
365
|
-
end
|
366
372
|
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
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
|
377
385
|
end
|
378
|
-
end
|
379
386
|
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
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
|
391
398
|
end
|
392
|
-
end
|
393
399
|
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
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
|
404
418
|
end
|
405
|
-
end
|
406
|
-
|
407
|
-
# skipline : "#" nonls newline
|
408
|
-
def parse_skipline
|
409
|
-
s0 = @current_pos
|
410
|
-
s1 = match_str("#")
|
411
|
-
if s1 == :failed
|
412
|
-
@current_pos = s0
|
413
|
-
s0 = :failed
|
414
|
-
else
|
415
|
-
s2 = parse_nonls
|
416
|
-
s3 = parse_newline
|
417
|
-
s0 = if s3 == :failed
|
418
|
-
@current_pos = s0
|
419
|
-
:failed
|
420
|
-
else
|
421
|
-
[s1, s2, s3]
|
422
|
-
end
|
423
|
-
end
|
424
|
-
s0
|
425
|
-
end
|
426
419
|
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
end
|
431
|
-
|
432
|
-
# newline : whitespace* ("\n" | "\r" "\n"?)
|
433
|
-
def parse_newline
|
434
|
-
s0 = @current_pos
|
435
|
-
s1 = []
|
436
|
-
s2 = parse_whitespace
|
437
|
-
while s2 != :failed
|
438
|
-
s1 << s2
|
439
|
-
s2 = parse_whitespace
|
420
|
+
# whitespace : " " | "\t"
|
421
|
+
def parse_whitespace
|
422
|
+
match_regexp(/[ \t]/)
|
440
423
|
end
|
441
|
-
s2 = match_str("\n")
|
442
|
-
if s2 == :failed
|
443
|
-
s2 = @current_pos
|
444
|
-
s3 = match_str("\r")
|
445
|
-
s2 = if s3 == :failed
|
446
|
-
@current_pos = s2
|
447
|
-
:failed
|
448
|
-
else
|
449
|
-
s4 = match_str("\n")
|
450
|
-
s4 = nil if s4 == :failed
|
451
|
-
[s3, s4]
|
452
|
-
end
|
453
|
-
end
|
454
|
-
if s2 == :failed
|
455
|
-
@current_pos = s0
|
456
|
-
:failed
|
457
|
-
else
|
458
|
-
[s1, s2]
|
459
|
-
end
|
460
|
-
end
|
461
424
|
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
s2 = parse_newline
|
466
|
-
if s2 == :failed
|
467
|
-
s1 = :failed
|
468
|
-
else
|
425
|
+
# newline : whitespace* ("\n" | "\r" "\n"?)
|
426
|
+
def parse_newline
|
427
|
+
s0 = @scanner.pos
|
469
428
|
s1 = []
|
429
|
+
s2 = parse_whitespace
|
470
430
|
while s2 != :failed
|
471
431
|
s1 << s2
|
472
|
-
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]
|
473
452
|
end
|
474
453
|
end
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
s2 =
|
480
|
-
|
481
|
-
|
482
|
-
|
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 = []
|
483
473
|
s3 = parse_skipline
|
474
|
+
while s3 != :failed
|
475
|
+
s2 << s3
|
476
|
+
s3 = parse_skipline
|
477
|
+
end
|
478
|
+
[s1, s2]
|
484
479
|
end
|
485
|
-
[s1, s2]
|
486
480
|
end
|
487
|
-
end
|
488
481
|
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
482
|
+
# nonl :
|
483
|
+
def parse_nonl
|
484
|
+
match_regexp(/[^\r\n]/)
|
485
|
+
end
|
493
486
|
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
matched = parse_nonl
|
498
|
-
while matched != :failed
|
499
|
-
stack << matched
|
487
|
+
# nonls : nonl*
|
488
|
+
def parse_nonls
|
489
|
+
stack = []
|
500
490
|
matched = parse_nonl
|
491
|
+
while matched != :failed
|
492
|
+
stack << matched
|
493
|
+
matched = parse_nonl
|
494
|
+
end
|
495
|
+
stack
|
501
496
|
end
|
502
|
-
stack
|
503
|
-
end
|
504
497
|
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
498
|
+
# nonls! : nonl+
|
499
|
+
def parse_nonls!
|
500
|
+
matched = parse_nonls
|
501
|
+
if matched.empty?
|
502
|
+
:failed
|
503
|
+
else
|
504
|
+
matched
|
505
|
+
end
|
512
506
|
end
|
513
|
-
end
|
514
507
|
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
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
|
529
523
|
end
|
530
|
-
end
|
531
524
|
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
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
|
544
538
|
end
|
545
|
-
end
|
546
539
|
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
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
|
554
549
|
end
|
555
|
-
board
|
550
|
+
{ 'preset' => 'OTHER', 'data' => { 'board' => board } }
|
556
551
|
end
|
557
|
-
{ "preset" => "OTHER", "data" => { "board" => board } }
|
558
|
-
end
|
559
552
|
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
553
|
+
# zenkaku number to number
|
554
|
+
def zen2n(s)
|
555
|
+
'0123456789'.index(s)
|
556
|
+
end
|
564
557
|
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
558
|
+
# kanji number to number (1)
|
559
|
+
def kan2n(s)
|
560
|
+
'〇一二三四五六七八九'.index(s)
|
561
|
+
end
|
569
562
|
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
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
|
579
573
|
end
|
580
|
-
end
|
581
574
|
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
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
|
609
603
|
end
|
610
|
-
end
|
611
604
|
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
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
|
631
625
|
end
|
632
626
|
end
|
633
627
|
end
|