jkf 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,8 +2,11 @@
2
2
 
3
3
  module Jkf::Parser
4
4
  class Kif < Base
5
+ include Kifuable
6
+
5
7
  def parse_root
6
- @input += "\n" if @input[-1] != "\n"
8
+ @input += "\n" unless @input.end_with?("\n")
9
+
7
10
  s0 = @current_pos
8
11
  s1 = []
9
12
  s2 = parse_skipline
@@ -11,108 +14,33 @@ module Jkf::Parser
11
14
  s1 << s2
12
15
  s2 = parse_skipline
13
16
  end
14
- if s1 != :failed
15
- s2 = []
17
+
18
+ s2 = []
19
+ s3 = parse_header
20
+ while s3 != :failed
21
+ s2 << s3
16
22
  s3 = parse_header
17
- while s3 != :failed
18
- s2 << s3
19
- s3 = parse_header
20
- end
21
- if s2 != :failed
22
- s3 = parse_initial_board
23
- s3 = nil if s3 == :failed
24
- if s3 != :failed
25
- s4 = []
26
- s5 = parse_header
27
- while s5 != :failed
28
- s4 << s5
29
- s5 = parse_header
30
- end
31
- if s4 != :failed
32
- s5 = parse_split
33
- s5 = nil if s5 == :failed
34
- if s5 != :failed
35
- s6 = parse_moves
36
- if s6 != :failed
37
- s7 = []
38
- s8 = parse_fork
39
- while s8 != :failed
40
- s7 << s8
41
- s8 = parse_fork
42
- end
43
- if s7 != :failed
44
- s8 = parse_nl
45
- s8 = nil if s8 == :failed
46
- if s8 != :failed
47
- @reported_pos = s0
48
- s1 = -> (headers, ini, headers2, moves, forks) {
49
- ret = { "header" => {}, "moves" => moves }
50
- headers.compact.each { |h| ret["header"][h["k"]] = h["v"] }
51
- headers2.compact.each { |h| ret["header"][h["k"]] = h["v"] }
52
- if ini
53
- ret["initial"] = ini
54
- elsif ret["header"]["手合割"]
55
- preset = preset2str(ret["header"]["手合割"])
56
- ret["initial"] = { "preset" => preset } if preset && preset != "OTHER"
57
- end
58
- if ret["initial"] && ret["initial"]["data"]
59
- if ret["header"]["手番"]
60
- ret["initial"]["data"]["color"] = ("下先".include?(ret["header"]["手番"]) ? 0 : 1)
61
- ret["header"].delete("手番")
62
- else
63
- ret["initial"]["data"]["color"] = 0
64
- end
65
- ret["initial"]["data"]["hands"] = [
66
- make_hand(ret["header"]["先手の持駒"] || ret["header"]["下手の持駒"]),
67
- make_hand(ret["header"]["後手の持駒"] || ret["header"]["上手の持駒"])
68
- ]
69
- %w(先手の持駒 下手の持駒 後手の持駒 上手の持駒).each do |key|
70
- ret["header"].delete(key)
71
- end
72
- end
73
- fork_stack = [{ "te" => 0, "moves" => moves }]
74
- forks.each do |f|
75
- now_fork = f
76
- _fork = fork_stack.pop
77
- _fork = fork_stack.pop while _fork["te"] > now_fork["te"]
78
- move = _fork["moves"][now_fork["te"] - _fork["te"]]
79
- move["forks"] ||= []
80
- move["forks"] << now_fork["moves"]
81
- fork_stack << _fork
82
- fork_stack << now_fork
83
- end
84
- reverse_color(ret['moves']) if ret["initial"] && ret["initial"]["data"] && ret["initial"]["data"]["color"] == 1
85
- ret
86
- }.call(s2, s3, s4, s6, s7)
87
- s0 = s1
88
- else
89
- @current_pos = s0
90
- s0 = :failed
91
- end
92
- else
93
- @current_pos = s0
94
- s0 = :failed
95
- end
96
- else
97
- @current_pos = s0
98
- s0 = :failed
99
- end
100
- else
101
- @current_pos = s0
102
- s0 = :failed
103
- end
104
- else
105
- @current_pos = s0
106
- s0 = :failed
107
- end
108
- else
109
- @current_pos = s0
110
- s0 = :failed
111
- end
112
- else
113
- @current_pos = s0
114
- s0 = :failed
115
- end
23
+ end
24
+ s3 = parse_initialboard
25
+ s3 = nil if s3 == :failed
26
+ s4 = []
27
+ s5 = parse_header
28
+ while s5 != :failed
29
+ s4 << s5
30
+ s5 = parse_header
31
+ end
32
+ parse_split
33
+ s6 = parse_moves
34
+ if s6 != :failed
35
+ s7 = []
36
+ s8 = parse_fork
37
+ while s8 != :failed
38
+ s7 << s8
39
+ s8 = parse_fork
40
+ end
41
+ parse_nl
42
+ @reported_pos = s0
43
+ s0 = transform_root(s2, s3, s4, s6, s7)
116
44
  else
117
45
  @current_pos = s0
118
46
  s0 = :failed
@@ -123,9 +51,9 @@ module Jkf::Parser
123
51
 
124
52
  def parse_header
125
53
  s0 = @current_pos
126
- s1 = []
127
54
  s2 = match_regexp(/^[^:\r\n]/)
128
55
  if s2 != :failed
56
+ s1 = []
129
57
  while s2 != :failed
130
58
  s1 << s2
131
59
  s2 = match_regexp(/^[^:\r\n]/)
@@ -134,24 +62,12 @@ module Jkf::Parser
134
62
  s1 = :failed
135
63
  end
136
64
  if s1 != :failed
137
- s2 = match_str(":")
138
- if s2 != :failed
139
- s3 = []
140
- s4 = parse_nonl
141
- while s4 != :failed
142
- s3 << s4
143
- s4 = parse_nonl
144
- end
145
- if s3 != :failed
146
- s4 = parse_nl
147
- if s4 != :failed
148
- @reported_pos = s0
149
- s1 = { "k" => s1.join, "v" => s3.join }
150
- s0 = s1
151
- else
152
- @current_pos = s0
153
- s0 = :failed
154
- end
65
+ if match_str(":") != :failed
66
+ s3 = parse_nonls
67
+ if parse_nl != :failed
68
+ @reported_pos = s0
69
+ s1 = { "k" => s1.join, "v" => s3.join }
70
+ s0 = s1
155
71
  else
156
72
  @current_pos = s0
157
73
  s0 = :failed
@@ -168,12 +84,10 @@ module Jkf::Parser
168
84
  s0 = @current_pos
169
85
  s1 = parse_turn
170
86
  if s1 != :failed
171
- s2 = match_str("手番")
172
- if s2 != :failed
173
- s3 = parse_nl
174
- if s3 != :failed
87
+ if match_str("手番") != :failed
88
+ if parse_nl != :failed
175
89
  @reported_pos = s0
176
- s0 = s1 = { "k" => "手番", "v" => s1 }
90
+ s0 = { "k" => "手番", "v" => s1 }
177
91
  else
178
92
  @current_pos = s0
179
93
  s0 = :failed
@@ -188,12 +102,10 @@ module Jkf::Parser
188
102
  end
189
103
  if s0 == :failed
190
104
  s0 = @current_pos
191
- s1 = match_str("盤面回転")
192
- if s1 != :failed
193
- s2 = parse_nl
194
- if s2 != :failed
105
+ if match_str("盤面回転") != :failed
106
+ if parse_nl != :failed
195
107
  @reported_pos = s0
196
- s0 = s1 = nil
108
+ s0 = nil
197
109
  else
198
110
  @current_pos = s0
199
111
  s0 = :failed
@@ -212,258 +124,15 @@ module Jkf::Parser
212
124
  match_regexp(/[先後上下]/)
213
125
  end
214
126
 
215
- def parse_initial_board
216
- s0 = s1 = @current_pos
217
- s2 = match_str(" ")
218
- if s2 != :failed
219
- s3 = []
220
- s4 = parse_nonl
221
- while s4 != :failed
222
- s3 << s4
223
- s4 = parse_nonl
224
- end
225
- if s3 != :failed
226
- s4 = parse_nl
227
- if s4 != :failed
228
- s1 = s2 = [s2, s3, s4]
229
- else
230
- @current_pos = s1
231
- s1 = :failed
232
- end
233
- else
234
- @current_pos = s1
235
- s1 = :failed
236
- end
237
- else
238
- @current_pos = s1
239
- s1 = :failed
240
- end
241
- if s1 == :failed
242
- s1 = nil
243
- end
244
- if s1 != :failed
245
- s2 = @current_pos
246
- s3 = match_str("+")
247
- if s3 != :failed
248
- s4 = []
249
- s5 = parse_nonl
250
- while s5 != :failed
251
- s4 << s5
252
- s5 = parse_nonl
253
- end
254
- if s4 != :failed
255
- s5 = parse_nl
256
- if s5 != :failed
257
- s2 = s3 = [s3, s4, s5]
258
- else
259
- @current_pos = s2
260
- s2 = :failed
261
- end
262
- else
263
- @current_pos = s2
264
- s2 = :failed
265
- end
266
- else
267
- @current_pos = s2
268
- s2 = :failed
269
- end
270
- s2 = nil if s2 == :failed
271
- if s2 != :failed
272
- s3 = []
273
- s4 = parse_ikkatsu_line
274
- if s4 != :failed
275
- while s4 != :failed
276
- s3 << s4
277
- s4 = parse_ikkatsu_line
278
- end
279
- else
280
- s3 = :failed
281
- end
282
- if s3 != :failed
283
- s4 = @current_pos
284
- s5 = match_str("+")
285
- if s5 != :failed
286
- s6 = []
287
- s7 = parse_nonl
288
- while s7 != :failed
289
- s6 << s7
290
- s7 = parse_nonl
291
- end
292
- if s6 != :failed
293
- s7 = parse_nl
294
- if s7 != :failed
295
- s4 = s5 = [s5, s6, s7]
296
- else
297
- @current_pos = s4
298
- s4 = :failed
299
- end
300
- else
301
- @current_pos = s4
302
- s4 = :failed
303
- end
304
- else
305
- @current_pos = s4
306
- s4 = :failed
307
- end
308
- s4 = nil if s4 == :failed
309
- if s4 != :failed
310
- @reported_pos = s0
311
- s1 = -> (lines) {
312
- ret = [];
313
- 9.times { |i|
314
- line = [];
315
- 9.times { |j|
316
- line << lines[j][8-i]
317
- }
318
- ret << line
319
- }
320
- { "preset" => "OTHER", "data" => { "board" => ret } }
321
- }.call(s3)
322
- s0 = s1
323
- else
324
- @current_pos = s0
325
- s0 = :failed
326
- end
327
- else
328
- @current_pos = s0
329
- s0 = :failed
330
- end
331
- else
332
- @current_pos = s0
333
- s0 = :failed
334
- end
335
- else
336
- @current_pos = s0
337
- s0 = :failed
338
- end
339
-
340
- s0
341
- end
342
-
343
- def parse_ikkatsu_line
344
- s0 = @current_pos
345
- s1 = match_str("|")
346
- if s1 != :failed
347
- s2 = []
348
- s3 = parse_masu
349
- if s3 != :failed
350
- while s3 != :failed
351
- s2 << s3
352
- s3 = parse_masu
353
- end
354
- else
355
- s2 = :failed
356
- end
357
- if s2 != :failed
358
- s3 = match_str("|")
359
- if s3 != :failed
360
- s4 = []
361
- s5 = parse_nonl
362
- if s5 != :failed
363
- while s5 != :failed
364
- s4 << s5
365
- s5 = parse_nonl
366
- end
367
- else
368
- s4 = :failed
369
- end
370
- if s4 != :failed
371
- s5 = parse_nl
372
- if s5 != :failed
373
- @reported_pos = s0
374
- s0 = s1 = s2
375
- else
376
- @current_pos = s0
377
- s0 = :failed
378
- end
379
- else
380
- @current_pos = s0
381
- s0 = :failed
382
- end
383
- else
384
- @current_pos = s0
385
- s0 = :failed
386
- end
387
- else
388
- @current_pos = s0
389
- s0 = :failed
390
- end
391
- else
392
- @current_pos = s0
393
- s0 = :failed
394
- end
395
-
396
- s0
397
- end
398
-
399
- def parse_masu
400
- s0 = @current_pos
401
- s1 = parse_teban
402
- if s1 != :failed
403
- s2 = parse_piece
404
- if s2 != :failed
405
- @reported_pos = s0
406
- s0 = s1 = { "color" => s1, "kind" => s2 }
407
- else
408
- @current_pos = s0
409
- s0 = :failed
410
- end
411
- else
412
- @current_pos = s0
413
- s0 = :failed
414
- end
415
- if s0 == :failed
416
- s0 = @current_pos
417
- s1 = match_str(" ・")
418
- if s1 != :failed
419
- @reported_pos = s0
420
- s1 = {}
421
- end
422
- s0 = s1
423
- end
424
-
425
- s0
426
- end
427
-
428
- def parse_teban
429
- s0 = @current_pos
430
- s1 = match_str(" ")
431
- if s1 == :failed
432
- s1 = match_str("+")
433
- s1 = match_str("^") if s1 == :failed
434
- end
435
- if s1 != :failed
436
- @reported_pos = s0
437
- s1 = 0
438
- end
439
- s0 = s1
440
- if s0 == :failed
441
- s0 = @current_pos
442
- s1 = match_str("v")
443
- s1 = match_str("V") if s1 == :failed
444
- if s1 != :failed
445
- @reported_pos = s0
446
- s1 = 1
447
- end
448
- s0 = s1
449
- end
450
- s0
451
- end
452
-
453
127
  def parse_split
454
128
  s0 = @current_pos
455
129
  s1 = match_str("手数----指手--")
456
130
  if s1 != :failed
457
131
  s2 = match_str("-------消費時間--")
458
132
  s2 = nil if s2 == :failed
459
- if s2 != :failed
460
- s3 = parse_nl
461
- if s3 != :failed
462
- s0 = s1 = [s1, s2, s3]
463
- else
464
- @current_pos = s0
465
- s0 = :failed
466
- end
133
+ s3 = parse_nl
134
+ if s3 != :failed
135
+ s0 = [s1, s2, s3]
467
136
  else
468
137
  @current_pos = s0
469
138
  s0 = :failed
@@ -479,33 +148,16 @@ module Jkf::Parser
479
148
  s0 = @current_pos
480
149
  s1 = parse_firstboard
481
150
  if s1 != :failed
482
- s2 = parse_split
483
- s2 = nil if s2 == :failed
484
- if s2 != :failed
485
- s3 = []
486
- s4 = parse_move
487
- while s4 != :failed
488
- s3 << s4
489
- s4 = parse_move
490
- end
491
- if s3 != :failed
492
- s4 = parse_result
493
- s4 = nil if s4 == :failed
494
- if s4 != :failed
495
- @reported_pos = s0
496
- s0 = s1 = s3.unshift(s1)
497
- else
498
- @current_pos = s0
499
- s0 = :failed
500
- end
501
- else
502
- @current_pos = s0
503
- s0 = :failed
504
- end
505
- else
506
- @current_pos = s0
507
- s0 = :failed
151
+ parse_split
152
+ s2 = []
153
+ s3 = parse_move
154
+ while s3 != :failed
155
+ s2 << s3
156
+ s3 = parse_move
508
157
  end
158
+ parse_result
159
+ @reported_pos = s0
160
+ s0 = s2.unshift(s1)
509
161
  else
510
162
  @current_pos = s0
511
163
  s0 = :failed
@@ -521,22 +173,9 @@ module Jkf::Parser
521
173
  s1 << s2
522
174
  s2 = parse_comment
523
175
  end
524
- if s1 != :failed
525
- s2 = parse_pointer
526
- if s2 == :failed
527
- s2 = nil
528
- end
529
- if s2 != :failed
530
- @reported_pos = s0
531
- s0 = s1 = s1.length == 0 ? {} : { "comments" => s1 }
532
- else
533
- @current_pos = s0
534
- s0 = :failed
535
- end
536
- else
537
- @current_pos = s0
538
- s0 = :failed
539
- end
176
+ parse_pointer
177
+ @reported_pos = s0
178
+ s0 = s1.empty? ? {} : { "comments" => s1 }
540
179
  s0
541
180
  end
542
181
 
@@ -550,160 +189,56 @@ module Jkf::Parser
550
189
  s2 << s3
551
190
  s3 = parse_comment
552
191
  end
553
- if s2 != :failed
554
- s3 = parse_pointer
555
- s3 = nil if s3 == :failed
556
- if s3 != :failed
557
- @reported_pos = s0
558
- s1 = -> (line, c) {
559
- ret = {}
560
- ret["comments"] = c if c.length > 0
561
- if line["move"].is_a? Hash
562
- ret["move"] = line["move"]
563
- else
564
- ret["special"] = special2csa(line["move"])
565
- end
566
- ret["time"] = line["time"] if line["time"]
567
- ret
568
- }.call(s1, s2)
569
- s0 = s1
570
- else
571
- @current_pos = s0
572
- s0 = :failed
573
- end
574
- else
575
- @current_pos = s0
576
- s0 = :failed
577
- end
578
- else
579
- @current_pos = s0
580
- s0 = :failed
581
- end
582
- s0
583
- end
584
-
585
- def parse_pointer
586
- s0 = @current_pos
587
- s1 = match_str("&")
588
- if s1 != :failed
589
- s2 = []
590
- s3 = parse_nonl
591
- while s3 != :failed
592
- s2 << s3
593
- s3 = parse_nonl
594
- end
595
- if s2 != :failed
596
- s3 = parse_nl
597
- if s3 != :failed
598
- s0 = s1 = [s1, s2, s3]
599
- else
600
- @current_pos = s0
601
- s0 = :failed
602
- end
603
- else
604
- @current_pos = s0
605
- s0 = :failed
606
- end
192
+ parse_pointer
193
+ @reported_pos = s0
194
+ s0 = transform_move(s1, s2)
607
195
  else
608
- @current_pos = s0
609
- s0 = :failed
610
- end
611
- s0
612
- end
613
-
614
- def parse_line
615
- s0 = @current_pos
616
- s1 = []
617
- s2 = match_str(" ")
618
- while s2 != :failed
619
- s1 << s2
620
- s2 = match_str(" ")
621
- end
622
- if s1 != :failed
623
- s2 = parse_te
624
- if s2 != :failed
625
- s3 = []
626
- s4 = match_str(" ")
627
- while s4 != :failed
628
- s3 << s4
629
- s4 = match_str(" ")
630
- end
631
- if s3 != :failed
632
- s4 = @current_pos
633
- s5 = parse_fugou
634
- if s5 != :failed
635
- s6 = parse_from
636
- if s6 != :failed
637
- @reported_pos = s4
638
- s5 = -> (teban, fugou, from) {
639
- ret = { "color" => teban2color(teban.join), "piece" => fugou["piece"] }
640
- if fugou["to"]
641
- ret["to"] = fugou["to"]
642
- else
643
- ret["same"] = true
644
- end
645
- ret["promote"] = true if fugou["promote"]
646
- ret["from"] = from if from
647
- ret
648
- }.call(s2, s5, s6)
649
- s4 = s5
650
- else
651
- @current_pos = s4
652
- s4 = :failed
653
- end
654
- else
655
- @current_pos = s4
656
- s4 = :failed
657
- end
658
- if s4 == :failed
659
- s4 = @current_pos
660
- s5 = []
661
- s6 = match_regexp(/^[^\r\n ]/)
662
- while s6 != :failed
663
- s5 << s6
664
- s6 = match_regexp(/^[^\r\n ]/)
665
- end
666
- @reported_pos = s4
667
- s4 = s5 = s5.join
668
- end
669
- if s4 != :failed
670
- s5 = []
671
- s6 = match_str(" ")
672
- while s6 != :failed
673
- s5 << s6
674
- s6 = match_str(" ")
675
- end
676
- if s5 != :failed
677
- s6 = parse_time
678
- s6 = nil if s6 == :failed
679
- if s6 != :failed
680
- s7 = match_str("+")
681
- s7 = nil if s7 == :failed
682
- if s7 != :failed
683
- s8 = parse_nl
684
- if s8 != :failed
685
- @reported_pos = s0
686
- s0 = s1 = { "move" => s4, "time" => s6 }
687
- else
688
- @current_pos = s0
689
- s0 = :failed
690
- end
691
- else
692
- @current_pos = s0
693
- s0 = :failed
694
- end
695
- else
696
- @current_pos = s0
697
- s0 = :failed
698
- end
699
- else
700
- @current_pos = s0
701
- s0 = :failed
702
- end
703
- else
704
- @current_pos = s0
705
- s0 = :failed
706
- end
196
+ @current_pos = s0
197
+ s0 = :failed
198
+ end
199
+ s0
200
+ end
201
+
202
+ def parse_line
203
+ s0 = @current_pos
204
+ match_spaces
205
+ s2 = parse_te
206
+ if s2 != :failed
207
+ match_spaces
208
+ s4 = @current_pos
209
+ s5 = parse_fugou
210
+ if s5 != :failed
211
+ s6 = parse_from
212
+ if s6 != :failed
213
+ @reported_pos = s4
214
+ s4 = transform_teban_fugou_from(s2, s5, s6)
215
+ else
216
+ @current_pos = s4
217
+ s4 = :failed
218
+ end
219
+ else
220
+ @current_pos = s4
221
+ s4 = :failed
222
+ end
223
+ if s4 == :failed
224
+ s4 = @current_pos
225
+ s5 = []
226
+ s6 = match_regexp(/^[^\r\n ]/)
227
+ while s6 != :failed
228
+ s5 << s6
229
+ s6 = match_regexp(/^[^\r\n ]/)
230
+ end
231
+ @reported_pos = s4
232
+ s4 = s5.join
233
+ end
234
+ if s4 != :failed
235
+ match_spaces
236
+ s6 = parse_time
237
+ s6 = nil if s6 == :failed
238
+ match_str("+")
239
+ if parse_nl != :failed
240
+ @reported_pos = s0
241
+ s0 = { "move" => s4, "time" => s6 }
707
242
  else
708
243
  @current_pos = s0
709
244
  s0 = :failed
@@ -720,17 +255,7 @@ module Jkf::Parser
720
255
  end
721
256
 
722
257
  def parse_te
723
- s0 = []
724
- s1 = match_regexp(/^[0-9]/)
725
- if s1 != :failed
726
- while s1 != :failed
727
- s0 << s1
728
- s1 = match_regexp(/^[0-9]/)
729
- end
730
- else
731
- s0 = :failed
732
- end
733
- s0
258
+ match_digits!
734
259
  end
735
260
 
736
261
  def parse_fugou
@@ -741,13 +266,8 @@ module Jkf::Parser
741
266
  if s2 != :failed
742
267
  s3 = match_str("成")
743
268
  s3 = nil if s3 == :failed
744
- if s3 != :failed
745
- @reported_pos = s0
746
- s0 = s1 = { "to" => s1, "piece" => s2, "promote" => !!s3 }
747
- else
748
- @current_pos = s0
749
- s0 = :failed
750
- end
269
+ @reported_pos = s0
270
+ s0 = { "to" => s1, "piece" => s2, "promote" => !!s3 }
751
271
  else
752
272
  @current_pos = s0
753
273
  s0 = :failed
@@ -766,7 +286,7 @@ module Jkf::Parser
766
286
  s2 = parse_numkan
767
287
  if s2 != :failed
768
288
  @reported_pos = s0
769
- s0 = s1 = { "x" => s1, "y" => s2 }
289
+ s0 = { "x" => s1, "y" => s2 }
770
290
  else
771
291
  @current_pos = s0
772
292
  s0 = :failed
@@ -787,46 +307,6 @@ module Jkf::Parser
787
307
  s0
788
308
  end
789
309
 
790
- def parse_num
791
- s0 = @current_pos
792
- s1 = match_regexp(/^[123456789]/)
793
- if s1 != :failed
794
- @reported_pos = s0
795
- s1 = zen2n(s1)
796
- end
797
- s1
798
- end
799
-
800
- def parse_numkan
801
- s0 = @current_pos
802
- s1 = match_regexp(/^[一二三四五六七八九]/)
803
- if s1 != :failed
804
- @reported_pos = s0
805
- s1 = kan2n(s1)
806
- end
807
- s1
808
- end
809
-
810
- def parse_piece
811
- s0 = @current_pos
812
- s1 = match_str("成")
813
- s1 = "" if s1 == :failed
814
- if s1 != :failed
815
- s2 = match_regexp(/^[歩香桂銀金角飛王玉と杏圭全馬竜龍]/)
816
- if s2 != :failed
817
- @reported_pos = s0
818
- s0 = s1 = kind2csa(s1+s2)
819
- else
820
- @current_pos = s0
821
- s0 = :failed
822
- end
823
- else
824
- @current_pos = s0
825
- s0 = :failed
826
- end
827
- s0
828
- end
829
-
830
310
  def parse_from
831
311
  s0 = @current_pos
832
312
  s1 = match_str("打")
@@ -837,16 +317,14 @@ module Jkf::Parser
837
317
  s0 = s1
838
318
  if s0 == :failed
839
319
  s0 = @current_pos
840
- s1 = match_str("(")
841
- if s1 != :failed
320
+ if match_str("(") != :failed
842
321
  s2 = match_regexp(/^[1-9]/)
843
322
  if s2 != :failed
844
323
  s3 = match_regexp(/^[1-9]/)
845
324
  if s3 != :failed
846
- s4 = match_str(")")
847
- if s4 != :failed
325
+ if match_str(")") != :failed
848
326
  @reported_pos = s0
849
- s0 = s1 = { "x" => s2.to_i, "y" => s3.to_i }
327
+ s0 = { "x" => s2.to_i, "y" => s3.to_i }
850
328
  else
851
329
  @current_pos = s0
852
330
  s0 = :failed
@@ -869,30 +347,17 @@ module Jkf::Parser
869
347
 
870
348
  def parse_time
871
349
  s0 = @current_pos
872
- s1 = match_str("(")
873
- if s1 != :failed
874
- s2 = []
875
- s3 = match_str(" ")
876
- while s3 != :failed
877
- s2 << s3
878
- s3 = match_str(" ")
879
- end
880
- if s2 != :failed
881
- s3 = parse_ms
882
- if s3 != :failed
883
- s4 = match_str("/")
884
- if s4 != :failed
885
- s5 = parse_hms
886
- s5 = parse_ms(with_hour: true) if s5 == :failed
887
- if s5 != :failed
888
- s6 = match_str(")")
889
- if s6 != :failed
890
- @reported_pos = s0
891
- s0 = s1 = { "now" => s3, "total" => s5 }
892
- else
893
- @current_pos = s0
894
- s0 = :failed
895
- end
350
+ if match_str("(") != :failed
351
+ match_spaces
352
+ s3 = parse_ms
353
+ if s3 != :failed
354
+ if match_str("/") != :failed
355
+ s5 = parse_hms
356
+ s5 = parse_ms(with_hour: true) if s5 == :failed
357
+ if s5 != :failed
358
+ if match_str(")") != :failed
359
+ @reported_pos = s0
360
+ s0 = { "now" => s3, "total" => s5 }
896
361
  else
897
362
  @current_pos = s0
898
363
  s0 = :failed
@@ -918,46 +383,17 @@ module Jkf::Parser
918
383
 
919
384
  def parse_hms
920
385
  s0 = @current_pos
921
- s1 = []
922
- s2 = match_regexp(/^[0-9]/)
923
- if s2 != :failed
924
- while s2 != :failed
925
- s1 << s2
926
- s2 = match_regexp(/^[0-9]/)
927
- end
928
- else
929
- s1 = :failed
930
- end
386
+ s1 = match_digits!
931
387
 
932
388
  if s1 != :failed
933
- s2 = match_str(":")
934
- if s2 != :failed
935
- s3 = []
936
- s4 = match_regexp(/^[0-9]/)
937
- if s4 != :failed
938
- while s4 != :failed
939
- s3 << s4
940
- s4 = match_regexp(/^[0-9]/)
941
- end
942
- else
943
- s3 = :failed
944
- end
389
+ if match_str(":") != :failed
390
+ s3 = match_digits!
945
391
  if s3 != :failed
946
- s4 = match_str(":")
947
- if s4 != :failed
948
- s5 = []
949
- s6 = match_regexp(/^[0-9]/)
950
- if s6 != :failed
951
- while s6 != :failed
952
- s5 << s6
953
- s6 = match_regexp(/^[0-9]/)
954
- end
955
- else
956
- s5 = :failed
957
- end
392
+ if match_str(":") != :failed
393
+ s5 = match_digits!
958
394
  if s5 != :failed
959
395
  @reported_pos = s0
960
- s0 = s1 = { "h" => s1.join.to_i, "m" => s3.join.to_i, "s" => s5.join.to_i }
396
+ s0 = { "h" => s1.join.to_i, "m" => s3.join.to_i, "s" => s5.join.to_i }
961
397
  else
962
398
  @current_pos = s0
963
399
  s0 = :failed
@@ -983,29 +419,10 @@ module Jkf::Parser
983
419
 
984
420
  def parse_ms(with_hour: false)
985
421
  s0 = @current_pos
986
- s1 = []
987
- s2 = match_regexp(/^[0-9]/)
988
- if s2 != :failed
989
- while s2 != :failed
990
- s1 << s2
991
- s2 = match_regexp(/^[0-9]/)
992
- end
993
- else
994
- s1 = :failed
995
- end
422
+ s1 = match_digits!
996
423
  if s1 != :failed
997
- s2 = match_str(":")
998
- if s2 != :failed
999
- s3 = []
1000
- s4 = match_regexp(/^[0-9]/)
1001
- if s4 != :failed
1002
- while s4 != :failed
1003
- s3 << s4
1004
- s4 = match_regexp(/^[0-9]/)
1005
- end
1006
- else
1007
- s3 = :failed
1008
- end
424
+ if match_str(":") != :failed
425
+ s3 = match_digits!
1009
426
  if s3 != :failed
1010
427
  @reported_pos = s0
1011
428
  m = s1.join.to_i
@@ -1013,9 +430,9 @@ module Jkf::Parser
1013
430
  if with_hour
1014
431
  h = m / 60
1015
432
  m = m % 60
1016
- s0 = s1 = { "h" => h, "m" => m, "s" => s }
433
+ s0 = { "h" => h, "m" => m, "s" => s }
1017
434
  else
1018
- s0 = s1 = { "m" => m, "s" => s }
435
+ s0 = { "m" => m, "s" => s }
1019
436
  end
1020
437
  else
1021
438
  @current_pos = s0
@@ -1034,24 +451,11 @@ module Jkf::Parser
1034
451
 
1035
452
  def parse_comment
1036
453
  s0 = @current_pos
1037
- s1 = match_str("*")
1038
- if s1 != :failed
1039
- s2 = []
1040
- s3 = parse_nonl
1041
- while s3 != :failed
1042
- s2 << s3
1043
- s3 = parse_nonl
1044
- end
1045
- if s2 != :failed
1046
- s3 = parse_nl
1047
- if s3 != :failed
1048
- @reported_pos = s0
1049
- s1 = s2.join
1050
- s0 = s1
1051
- else
1052
- @current_pos = s0
1053
- s0 = :failed
1054
- end
454
+ if match_str("*") != :failed
455
+ s2 = parse_nonls
456
+ if parse_nl != :failed
457
+ @reported_pos = s0
458
+ s0 = s2.join
1055
459
  else
1056
460
  @current_pos = s0
1057
461
  s0 = :failed
@@ -1064,22 +468,10 @@ module Jkf::Parser
1064
468
  s0 = @current_pos
1065
469
  s1 = match_str("&")
1066
470
  if s1 != :failed
1067
- s2 = []
1068
- s3 = parse_nonl
1069
- while s3 != :failed
1070
- s2 << s3
1071
- s3 = parse_nonl
1072
- end
1073
-
1074
- if s2 != :failed
1075
- s3 = parse_nl
1076
- if s3 != :failed
1077
- @reported_pos = s0
1078
- s0 = s1 = "&" + s2.join
1079
- else
1080
- @current_pos = s0
1081
- s0 = :failed
1082
- end
471
+ s2 = parse_nonls
472
+ if parse_nl != :failed
473
+ @reported_pos = s0
474
+ s0 = "&" + s2.join
1083
475
  else
1084
476
  @current_pos = s0
1085
477
  s0 = :failed
@@ -1092,226 +484,18 @@ module Jkf::Parser
1092
484
  s0
1093
485
  end
1094
486
 
1095
- def parse_result
487
+ def parse_fork
1096
488
  s0 = @current_pos
1097
- s1 = match_str("まで")
1098
-
1099
- if s1 != :failed
1100
- s2 = []
1101
- s3 = match_regexp(/^[0-9]/)
489
+ if match_str("変化:") != :failed
490
+ match_spaces
491
+ s3 = parse_te
1102
492
  if s3 != :failed
1103
- while s3 != :failed
1104
- s2 << s3
1105
- s3 = match_regexp(/^[0-9]/)
1106
- end
1107
- else
1108
- s2 = :failed
1109
- end
1110
- if s2 != :failed
1111
- s3 = match_str("手")
1112
- if s3 != :failed
1113
- s4 = @current_pos
1114
- s5 = match_str("で")
1115
- if s5 != :failed
1116
- s6 = parse_turn
493
+ if match_str("手") != :failed
494
+ if parse_nl != :failed
495
+ s6 = parse_moves
1117
496
  if s6 != :failed
1118
- s7 = match_str("手の")
1119
- if s7 != :failed
1120
- s8 = @current_pos
1121
- s9 = match_str("勝ち")
1122
- if s9 != :failed
1123
- @reported_pos = s8
1124
- s9 = "TORYO"
1125
- end
1126
- s8 = s9
1127
- if s8 == :failed
1128
- s8 = @current_pos
1129
- s9 = match_str("反則")
1130
- if s9 != :failed
1131
- s10 = @current_pos
1132
- s11 = match_str("勝ち")
1133
- if s11 != :failed
1134
- @reported_pos = s10
1135
- s11 = "ILLEGAL_ACTION"
1136
- end
1137
- s10 = s11
1138
- if s10 == :failed
1139
- s10 = @current_pos
1140
- s11 = match_str("負け")
1141
- if s11 != :failed
1142
- @reported_pos = s10
1143
- s11 = "ILLEGAL_MOVE"
1144
- end
1145
- s10 = s11
1146
- end
1147
- if s10 != :failed
1148
- @reported_pos = s8
1149
- s8 = s9 = s10
1150
- else
1151
- @current_pos = s8
1152
- s8 = :failed
1153
- end
1154
- else
1155
- @current_pos = s8
1156
- s8 = :failed
1157
- end
1158
- end
1159
- if s8 != :failed
1160
- @reported_pos = s4
1161
- s4 = s5 = s8
1162
- else
1163
- @current_pos = s4
1164
- s4 = :failed
1165
- end
1166
- else
1167
- @current_pos = s4
1168
- s4 = :failed
1169
- end
1170
- else
1171
- @current_pos = s4
1172
- s4 = :failed
1173
- end
1174
- else
1175
- @current_pos = s4
1176
- s4 = :failed
1177
- end
1178
- if s4 == :failed
1179
- s4 = @current_pos
1180
- s5 = match_str("で時間切れにより")
1181
- if s5 != :failed
1182
- s6 = parse_turn
1183
- if s6 != :failed
1184
- s7 = match_str("手の勝ち")
1185
- if s7 != :failed
1186
- @reported_pos = s4
1187
- s4 = s5 = "TIME_UP"
1188
- else
1189
- @current_pos = s4
1190
- s4 = :failed
1191
- end
1192
- else
1193
- @current_pos = s4
1194
- s4 = :failed
1195
- end
1196
- else
1197
- @current_pos = s4
1198
- s4 = :failed
1199
- end
1200
- if s4 == :failed
1201
- s4 = @current_pos
1202
- s5 = match_str("で中断")
1203
- if s5 != :failed
1204
- @reported_pos = s4
1205
- s5 = "CHUDAN"
1206
- end
1207
- s4 = s5
1208
- if s4 == :failed
1209
- s4 = @current_pos
1210
- s5 = match_str("で持将棋")
1211
- if s5 != :failed
1212
- @reported_pos = s4
1213
- s5 = "JISHOGI"
1214
- end
1215
- s4 = s5
1216
- if s4 == :failed
1217
- s4 = @current_pos
1218
- s5 = match_str("で千日手")
1219
- if s5 != :failed
1220
- @reported_pos = s4
1221
- s5 = "SENNICHITE"
1222
- end
1223
- s4 = s5
1224
- if s4 == :failed
1225
- s4 = @current_pos
1226
- s5 = match_str("で")
1227
- s5 = nil if s5 == :failed
1228
- if s5 != :failed
1229
- s6 = match_str("詰")
1230
- if s6 != :failed
1231
- s7 = match_str("み")
1232
- s7 = nil if s7 == :failed
1233
- if s7 != :failed
1234
- @reported_pos = s4
1235
- s4 = s5 = "TSUMI"
1236
- else
1237
- @current_pos = s4
1238
- s4 = :failed
1239
- end
1240
- else
1241
- @current_pos = s4
1242
- s4 = :failed
1243
- end
1244
- else
1245
- @current_pos = s4
1246
- s4 = :failed
1247
- end
1248
- if s4 == :failed
1249
- s4 = @current_pos
1250
- s5 = match_str("で不詰")
1251
- if s5 != :failed
1252
- @reported_pos = s4
1253
- s5 = "FUZUMI"
1254
- end
1255
- s4 = s5
1256
- end
1257
- end
1258
- end
1259
- end
1260
- end
1261
- end
1262
- if s4 != :failed
1263
- s5 = parse_nl
1264
- if s5 != :failed
1265
497
  @reported_pos = s0
1266
- s0 = s1 = s4
1267
- else
1268
- @current_pos = s0
1269
- s0 = :failed
1270
- end
1271
- else
1272
- @current_pos = s0
1273
- s0 = :failed
1274
- end
1275
- else
1276
- @current_pos = s0
1277
- s0 = :failed
1278
- end
1279
- else
1280
- @current_pos = s0
1281
- s0 = :failed
1282
- end
1283
- else
1284
- @current_pos = s0
1285
- s0 = :failed
1286
- end
1287
- s0
1288
- end
1289
-
1290
- def parse_fork
1291
- s0 = @current_pos
1292
- s1 = match_str("変化:")
1293
- if s1 != :failed
1294
- s2 = []
1295
- s3 = match_str(" ")
1296
- while s3 != :failed
1297
- s2 << s3
1298
- s3 = match_str(" ")
1299
- end
1300
- if s2 != :failed
1301
- s3 = parse_te
1302
- if s3 != :failed
1303
- s4 = match_str("手")
1304
- if s4 != :failed
1305
- s5 = parse_nl
1306
- if s5 != :failed
1307
- s6 = parse_moves
1308
- if s6 != :failed
1309
- @reported_pos = s0
1310
- s0 = s1 = { "te" => s3.join.to_i, "moves" => s6[1..-1] }
1311
- else
1312
- @current_pos = s0
1313
- s0 = :failed
1314
- end
498
+ s0 = { "te" => s3.join.to_i, "moves" => s6[1..-1] }
1315
499
  else
1316
500
  @current_pos = s0
1317
501
  s0 = :failed
@@ -1335,164 +519,48 @@ module Jkf::Parser
1335
519
  s0
1336
520
  end
1337
521
 
1338
- def parse_nl
1339
- s0 = @current_pos
1340
- s1 = []
1341
- s2 = parse_newline
1342
- if s2 != :failed
1343
- while (s2 != :failed)
1344
- s1 << s2
1345
- s2 = parse_newline
1346
- end
1347
- else
1348
- s1 = :failed
1349
- end
1350
- if s1 != :failed
1351
- s2 = []
1352
- s3 = parse_skipline
1353
- while s3 != :failed
1354
- s2 << s3
1355
- s3 = parse_skipline
1356
- end
1357
- if s2 != :failed
1358
- s0 = s1 = [s1, s2]
1359
- else
1360
- @current_pos = s0
1361
- s0 = :failed
1362
- end
1363
- else
1364
- @current_pos = s0
1365
- s0 = :failed
1366
- end
1367
-
1368
- s0
1369
- end
1370
-
1371
- def parse_skipline
1372
- s0 = @current_pos
1373
- s1 = match_str("#")
1374
- if s1 != :failed
1375
- s2 = []
1376
- s3 = parse_nonl
1377
- while s3 != :failed
1378
- s2 << s3
1379
- s3 = parse_nonl
1380
- end
1381
- if s2 != :failed
1382
- s3 = parse_newline
1383
- if s3 != :failed
1384
- s0 = s1 = [s1, s2, s3]
1385
- else
1386
- @current_pos = s0
1387
- s0 = :failed
1388
- end
1389
- else
1390
- @current_pos = s0
1391
- s0 = :failed
1392
- end
1393
- else
1394
- @current_pos = s0
1395
- s0 = :failed
1396
- end
1397
- s0
1398
- end
1399
-
1400
- def parse_whitespace
1401
- match_regexp(/^[ \t]/)
1402
- end
1403
-
1404
- def parse_newline
1405
- s0 = @current_pos
1406
- s1 = []
1407
- s2 = parse_whitespace
1408
- while s2 != :failed
1409
- s1 << s2
1410
- s2 = parse_whitespace
1411
- end
1412
- if s1 != :failed
1413
- s2 = match_str("\n")
1414
- if s2 == :failed
1415
- s2 = @current_pos
1416
- s3 = match_str("\r")
1417
- if s3 != :failed
1418
- s4 = match_str("\n")
1419
- s4 = nil if s4 == :failed
1420
- if s4 != :failed
1421
- s2 = s3 = [s3, s4]
1422
- else
1423
- @current_pos = s2
1424
- s2 = :failed
1425
- end
1426
- else
1427
- @current_pos = s2
1428
- s2 = :failed
1429
- end
1430
- end
1431
- if s2 != :failed
1432
- s0 = s1 = [s1, s2]
1433
- else
1434
- @current_pos = s0
1435
- s0 = :failed
1436
- end
1437
- else
1438
- @current_pos = s0
1439
- s0 = :failed
1440
- end
1441
- s0
1442
- end
1443
-
1444
- def parse_nonl
1445
- match_regexp(/^[^\r\n]/)
1446
- end
1447
-
1448
522
  protected
1449
523
 
1450
- def zen2n(s)
1451
- "0123456789".index(s)
1452
- end
1453
-
1454
- def kan2n(s)
1455
- "〇一二三四五六七八九".index(s)
524
+ def transform_root(headers, ini, headers2, moves, forks)
525
+ ret = { "header" => {}, "moves" => moves }
526
+ headers.compact.each { |h| ret["header"][h["k"]] = h["v"] }
527
+ headers2.compact.each { |h| ret["header"][h["k"]] = h["v"] }
528
+ if ini
529
+ ret["initial"] = ini
530
+ elsif ret["header"]["手合割"]
531
+ preset = preset2str(ret["header"]["手合割"])
532
+ ret["initial"] = { "preset" => preset } if preset && preset != "OTHER"
533
+ end
534
+ transform_root_header_data(ret) if ret["initial"] && ret["initial"]["data"]
535
+ transform_root_forks(forks, moves)
536
+ if ret["initial"] && ret["initial"]["data"] && ret["initial"]["data"]["color"] == 1
537
+ reverse_color(ret["moves"])
538
+ end
539
+ ret
1456
540
  end
1457
541
 
1458
- def kan2n2(s)
1459
- case s.length
1460
- when 1
1461
- "〇一二三四五六七八九十".index(s)
1462
- when 2
1463
- "〇一二三四五六七八九十".index(s[1])+10
542
+ def transform_move(line, c)
543
+ ret = {}
544
+ ret["comments"] = c if !c.empty?
545
+ if line["move"].is_a? Hash
546
+ ret["move"] = line["move"]
1464
547
  else
1465
- raise "21以上の数値に対応していません"
548
+ ret["special"] = special2csa(line["move"])
1466
549
  end
550
+ ret["time"] = line["time"] if line["time"]
551
+ ret
1467
552
  end
1468
553
 
1469
- def kind2csa(kind)
1470
- if kind[0] == ""
1471
- {
1472
- "" => "NY",
1473
- "桂" => "NK",
1474
- "銀" => "NG"
1475
- }[kind[1]]
554
+ def transform_teban_fugou_from(teban, fugou, from)
555
+ ret = { "color" => teban2color(teban.join), "piece" => fugou["piece"] }
556
+ if fugou["to"]
557
+ ret["to"] = fugou["to"]
1476
558
  else
1477
- {
1478
- "歩" => "FU",
1479
- "香" => "KY",
1480
- "桂" => "KE",
1481
- "銀" => "GI",
1482
- "金" => "KI",
1483
- "角" => "KA",
1484
- "飛" => "HI",
1485
- "玉" => "OU",
1486
- "王" => "OU",
1487
- "と" => "TO",
1488
- "杏" => "NY",
1489
- "圭" => "NK",
1490
- "全" => "NG",
1491
- "馬" => "UM",
1492
- "竜" => "RY",
1493
- "龍" => "RY"
1494
- }[kind]
559
+ ret["same"] = true
1495
560
  end
561
+ ret["promote"] = true if fugou["promote"]
562
+ ret["from"] = from if from
563
+ ret
1496
564
  end
1497
565
 
1498
566
  def special2csa(str)
@@ -1509,38 +577,17 @@ module Jkf::Parser
1509
577
  }[str] || (raise ParseError)
1510
578
  end
1511
579
 
1512
- def preset2str(preset)
1513
- {
1514
- "平手" => "HIRATE",
1515
- "香落ち" => "KY",
1516
- "右香落ち" => "KY_R",
1517
- "角落ち" => "KA",
1518
- "飛車落ち" => "HI",
1519
- "飛香落ち" => "HIKY",
1520
- "二枚落ち" => "2",
1521
- "三枚落ち" => "3",
1522
- "四枚落ち" => "4",
1523
- "五枚落ち" => "5",
1524
- "左五枚落ち" => "5_L",
1525
- "六枚落ち" => "6",
1526
- "八枚落ち" => "8",
1527
- "十枚落ち" => "10",
1528
- "その他" => "OTHER",
1529
- }[preset.gsub(/\s/, "")]
1530
- end
1531
-
1532
580
  def teban2color(teban)
1533
581
  teban = teban.to_i unless teban.is_a? Fixnum
1534
- (teban+1) % 2
582
+ (teban + 1) % 2
1535
583
  end
1536
584
 
1537
585
  def make_hand(str)
1538
586
  # Kifu for iPhoneは半角スペース区切り
1539
- kinds = str.split(/[  ]/)
1540
587
  ret = { "FU" => 0, "KY" => 0, "KE" => 0, "GI" => 0, "KI" => 0, "KA" => 0, "HI" => 0 }
1541
588
  return ret if str.empty?
1542
589
 
1543
- kinds.each do |kind|
590
+ str.split(/[  ]/).each do |kind|
1544
591
  next if kind.empty?
1545
592
  ret[kind2csa(kind[0])] = kind.length == 1 ? 1 : kan2n2(kind[1..-1])
1546
593
  end
@@ -1550,8 +597,10 @@ module Jkf::Parser
1550
597
 
1551
598
  def reverse_color(moves)
1552
599
  moves.each do |move|
1553
- move['move']['color'] = (move['move']['color'] + 1) % 2 if move['move'] && move['move']['color']
1554
- move['forks'].each { |_fork| reverse_color(_fork) } if move['forks']
600
+ if move["move"] && move["move"]["color"]
601
+ move["move"]["color"] = (move["move"]["color"] + 1) % 2
602
+ end
603
+ move["forks"].each { |_fork| reverse_color(_fork) } if move["forks"]
1555
604
  end
1556
605
  end
1557
606
  end