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.
@@ -1,633 +1,627 @@
1
- module Jkf::Parser
2
- # Intersection of KIF and KI2
3
- module Kifuable
4
- protected
5
-
6
- # initialboard : (" " nonls nl)? ("+" nonls nl)? ikkatsuline+ ("+" nonls nl)?
7
- def parse_initialboard
8
- s0 = s1 = @current_pos
9
- if match_space == :failed
10
- @current_pos = s1
11
- else
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
- @current_pos = s4 if parse_nl == :failed
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
- s2 = :failed
35
+ @scanner.pos = s0
36
+ :failed
59
37
  else
60
- s2 = []
61
- while s3 != :failed
62
- s2 << s3
63
- s3 = parse_masu
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
- if s2 == :failed
67
- @current_pos = s0
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
- elsif match_str("|") != :failed
70
- s4 = parse_nonls!
71
- if s4 == :failed
72
- @current_pos = s0
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 parse_nl != :failed
75
- @reported_pos = s0
76
- s0 = s2
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
- @current_pos = s0
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
- s0
88
- end
88
+ s0
89
+ end
89
90
 
90
- # masu : teban piece | " ・"
91
- def parse_masu
92
- s0 = @current_pos
93
- s1 = parse_teban
94
- if s1 == :failed
95
- @current_pos = s0
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
- @reported_pos = s0
104
- s0 = { "color" => s1, "kind" => s2 }
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
- end
107
- if s0 == :failed
108
- s0 = @current_pos
109
- s1 = match_str(" ・")
110
- if s1 != :failed
111
- @reported_pos = s0
112
- 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
113
116
  end
114
- s0 = s1
115
- end
116
117
 
117
- s0
118
- end
118
+ s0
119
+ end
119
120
 
120
- # teban : (" " | "+" | "^") | ("v" | "V")
121
- def parse_teban
122
- s0 = @current_pos
123
- s1 = match_space
124
- if s1 == :failed
125
- s1 = match_str("+")
126
- s1 = match_str("^") if s1 == :failed
127
- end
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 = 1
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
- # pointer : "&" nonls nl
147
- def parse_pointer
148
- s0 = @current_pos
149
- s1 = match_str("&")
150
- if s1 == :failed
151
- @current_pos = s0
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
- s0 = [s1, s2, s3]
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
- # num : [123456789]
167
- def parse_num
168
- s0 = @current_pos
169
- s1 = match_regexp(/^[123456789]/)
170
- if s1 != :failed
171
- @reported_pos = s0
172
- s1 = zen2n(s1)
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
- # numkan : [一二三四五六七八九]
178
- def parse_numkan
179
- s0 = @current_pos
180
- s1 = match_regexp(/^[一二三四五六七八九]/)
181
- if s1 != :failed
182
- @reported_pos = s0
183
- s1 = kan2n(s1)
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
- # piece : "成"? [歩香桂銀金角飛王玉と杏圭全馬竜龍]
189
- def parse_piece
190
- s0 = @current_pos
191
- s1 = match_str("")
192
- s1 = "" if s1 == :failed
193
- s2 = match_regexp(/^[歩香桂銀金角飛王玉と杏圭全馬竜龍]/)
194
- if s2 == :failed
195
- @current_pos = s0
196
- :failed
197
- else
198
- @reported_pos = s0
199
- kind2csa(s1 + s2)
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
- # result : "まで" [0-9]+ "手" (
204
- # "で" (turn "手の" (result_toryo | result_illegal)) |
205
- # result_timeup | result_chudan | result_jishogi |
206
- # result_sennichite | result_tsumi | result_fuzumi
207
- # ) nl
208
- def parse_result
209
- s0 = @current_pos
210
- if match_str("まで") == :failed
211
- @current_pos = s0
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
- elsif match_str("手") != :failed
219
- s4 = @current_pos
220
- if match_str("で") == :failed
221
- @current_pos = s4
222
- s4 = :failed
223
- elsif parse_turn != :failed
224
- if match_str("手の") == :failed
225
- @current_pos = s4
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
- s8 = parse_result_toryo
229
- s8 = parse_result_illegal if s8 == :failed
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 = parse_result_chudan
244
+ s4 = parse_result_timeup
246
245
  if s4 == :failed
247
- s4 = parse_result_jishogi
246
+ s4 = parse_result_chudan
248
247
  if s4 == :failed
249
- s4 = parse_result_sennichite
248
+ s4 = parse_result_jishogi
250
249
  if s4 == :failed
251
- s4 = parse_result_tsumi
252
- s4 = parse_result_fuzumi if s4 == :failed
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
- end
258
- if s4 == :failed
259
- @current_pos = s0
260
- :failed
261
- elsif parse_nl != :failed || eos?
262
- @reported_pos = s0
263
- s4
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
- @current_pos = s0
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
- # result_toryo : "勝ち"
276
- def parse_result_toryo
277
- s0 = @current_pos
278
- s1 = match_str("勝ち")
279
- if s1 == :failed
280
- @current_pos = s0
281
- :failed
282
- else
283
- @reported_pos = s0
284
- "TORYO"
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
- # result_illegal : "反則" ("勝ち" | "負け")
289
- def parse_result_illegal
290
- s0 = @current_pos
291
- if match_str("反則") == :failed
292
- @current_pos = s0
293
- :failed
294
- else
295
- s10 = @current_pos
296
- s11 = match_str("勝ち")
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 = "ILLEGAL_MOVE"
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
- if s10 == :failed
312
- @current_pos = s0
313
- :failed
314
- else
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
- s10
327
+ 'TIME_UP'
328
+ else
329
+ @scanner.pos = s0
330
+ :failed
317
331
  end
318
332
  end
319
- end
320
333
 
321
- # result_timeup : "で時間切れにより" turn "手の勝ち"
322
- def parse_result_timeup
323
- s0 = @current_pos
324
- if match_str("で時間切れにより") == :failed
325
- @current_pos = s0
326
- :failed
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
- "TIME_UP"
343
+ 'CHUDAN'
334
344
  end
335
- else
336
- @current_pos = s0
337
- :failed
338
345
  end
339
- end
340
346
 
341
- # result_chudan : "で中断"
342
- def parse_result_chudan
343
- s0 = @current_pos
344
- s1 = match_str("で中断")
345
- if s1 == :failed
346
- @current_pos = s0
347
- :failed
348
- else
349
- @reported_pos = s0
350
- "CHUDAN"
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
- # result_jishogi : "で持将棋"
355
- def parse_result_jishogi
356
- s0 = @current_pos
357
- s1 = match_str("で持将棋")
358
- if s1 == :failed
359
- @current_pos = s0
360
- :failed
361
- else
362
- @reported_pos = s0
363
- "JISHOGI"
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
- # result_sennichite : "で千日手"
368
- def parse_result_sennichite
369
- s0 = @current_pos
370
- s1 = match_str("で千日手")
371
- if s1 == :failed
372
- @current_pos = s0
373
- :failed
374
- else
375
- @reported_pos = s0
376
- "SENNICHITE"
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
- # result_tsumi : ""? "詰" "み"?
381
- def parse_result_tsumi
382
- s0 = @current_pos
383
- match_str("で")
384
- if match_str("詰") == :failed
385
- @current_pos = s0
386
- :failed
387
- else
388
- match_str("み")
389
- @reported_pos = s0
390
- "TSUMI"
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
- # result_fuzumi : "で不詰"
395
- def parse_result_fuzumi
396
- s0 = @current_pos
397
- s1 = match_str("で不詰")
398
- if s1 == :failed
399
- @current_pos = s0
400
- :failed
401
- else
402
- @reported_pos = s0
403
- "FUZUMI"
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
- # whitespace : " " | "\t"
428
- def parse_whitespace
429
- match_regexp(/^[ \t]/)
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
- # nl : newline+ skipline*
463
- def parse_nl
464
- s0 = @current_pos
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 = parse_newline
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
- if s1 == :failed
476
- @current_pos = s0
477
- :failed
478
- else
479
- s2 = []
480
- s3 = parse_skipline
481
- while s3 != :failed
482
- s2 << s3
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
- # nonl :
490
- def parse_nonl
491
- match_regexp(/^[^\r\n]/)
492
- end
482
+ # nonl :
483
+ def parse_nonl
484
+ match_regexp(/[^\r\n]/)
485
+ end
493
486
 
494
- # nonls : nonl*
495
- def parse_nonls
496
- stack = []
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
- # nonls! : nonl+
506
- def parse_nonls!
507
- matched = parse_nonls
508
- if matched.empty?
509
- :failed
510
- else
511
- matched
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
- # transform header-data to jkf
516
- def transform_root_header_data(ret)
517
- if ret["header"]["手番"]
518
- ret["initial"]["data"]["color"] = "下先".include?(ret["header"]["手番"]) ? 0 : 1
519
- ret["header"].delete("手番")
520
- else
521
- ret["initial"]["data"]["color"] = 0
522
- end
523
- ret["initial"]["data"]["hands"] = [
524
- make_hand(ret["header"]["先手の持駒"] || ret["header"]["下手の持駒"]),
525
- make_hand(ret["header"]["後手の持駒"] || ret["header"]["上手の持駒"])
526
- ]
527
- %w(先手の持駒 下手の持駒 後手の持駒 上手の持駒).each do |key|
528
- ret["header"].delete(key)
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
- # transfrom forks to jkf
533
- def transform_root_forks(forks, moves)
534
- fork_stack = [{ "te" => 0, "moves" => moves }]
535
- forks.each do |f|
536
- now_fork = f
537
- _fork = fork_stack.pop
538
- _fork = fork_stack.pop while _fork["te"] > now_fork["te"]
539
- move = _fork["moves"][now_fork["te"] - _fork["te"]]
540
- move["forks"] ||= []
541
- move["forks"] << now_fork["moves"]
542
- fork_stack << _fork
543
- fork_stack << now_fork
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
- # transform initialboard to jkf
548
- def transform_initialboard(lines)
549
- board = []
550
- 9.times do |i|
551
- line = []
552
- 9.times do |j|
553
- line << lines[j][8 - i]
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 << line
550
+ { 'preset' => 'OTHER', 'data' => { 'board' => board } }
556
551
  end
557
- { "preset" => "OTHER", "data" => { "board" => board } }
558
- end
559
552
 
560
- # zenkaku number to number
561
- def zen2n(s)
562
- "0123456789".index(s)
563
- end
553
+ # zenkaku number to number
554
+ def zen2n(s)
555
+ '0123456789'.index(s)
556
+ end
564
557
 
565
- # kanji number to number (1)
566
- def kan2n(s)
567
- "〇一二三四五六七八九".index(s)
568
- end
558
+ # kanji number to number (1)
559
+ def kan2n(s)
560
+ '〇一二三四五六七八九'.index(s)
561
+ end
569
562
 
570
- # kanji number to number (2)
571
- def kan2n2(s)
572
- case s.length
573
- when 1
574
- "〇一二三四五六七八九十".index(s)
575
- when 2
576
- "〇一二三四五六七八九十".index(s[1]) + 10
577
- else
578
- raise "21以上の数値に対応していません"
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
- # kanji piece-type to csa
583
- def kind2csa(kind)
584
- if kind[0] == ""
585
- {
586
- "" => "NY",
587
- "" => "NK",
588
- "" => "NG"
589
- }[kind[1]]
590
- else
591
- {
592
- "" => "FU",
593
- "" => "KY",
594
- "" => "KE",
595
- "" => "GI",
596
- "" => "KI",
597
- "" => "KA",
598
- "" => "HI",
599
- "" => "OU",
600
- "" => "OU",
601
- "" => "TO",
602
- "" => "NY",
603
- "" => "NK",
604
- "" => "NG",
605
- "" => "UM",
606
- "" => "RY",
607
- "" => "RY"
608
- }[kind]
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
- # preset string to jkf
613
- def preset2str(preset)
614
- {
615
- "平手" => "HIRATE",
616
- "香落ち" => "KY",
617
- "右香落ち" => "KY_R",
618
- "角落ち" => "KA",
619
- "飛車落ち" => "HI",
620
- "飛香落ち" => "HIKY",
621
- "二枚落ち" => "2",
622
- "三枚落ち" => "3",
623
- "四枚落ち" => "4",
624
- "五枚落ち" => "5",
625
- "左五枚落ち" => "5_L",
626
- "六枚落ち" => "6",
627
- "八枚落ち" => "8",
628
- "十枚落ち" => "10",
629
- "その他" => "OTHER"
630
- }[preset.gsub(/\s/, "")]
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