jkf 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,988 @@
1
+ # coding: utf-8
2
+
3
+ module Jkf::Parser
4
+ class Csa < Base
5
+ def parse_root
6
+ @input += "\n" unless @input[-1] =~ /\n|\r|,/ # FIXME
7
+ s0 = parse_csa2
8
+ s0 = parse_csa1 if s0 == :failed
9
+ s0
10
+ end
11
+
12
+ def parse_csa2
13
+ s0 = @current_pos
14
+ s1 = parse_version22
15
+ if s1 != :failed
16
+ s2 = parse_information
17
+ s2 = nil if s2 == :failed
18
+ if s2 != :failed
19
+ s3 = parse_initial_board
20
+ if s3 != :failed
21
+ s4 = parse_moves
22
+ s4 = nil if s4 == :failed
23
+ if s4 != :failed
24
+ @reported_pos = s0
25
+ s0 = s1 = -> (info, ini, ms) {
26
+ ret = { "header" => info["header"], "initial" => ini, "moves" => ms }
27
+ if info && info["players"]
28
+ ret["header"]["先手"] = info["players"][0] if info["players"][0]
29
+ ret["header"]["後手"] = info["players"][1] if info["players"][1]
30
+ end
31
+ ret
32
+ }.call(s2, s3, s4)
33
+ else
34
+ @current_pos = s0
35
+ s0 = :failed
36
+ end
37
+ else
38
+ @current_pos = s0
39
+ s0 = :failed
40
+ end
41
+ else
42
+ @current_pos = s0
43
+ s0 = :failed
44
+ end
45
+ else
46
+ @current_pos = s0
47
+ s0 = :failed
48
+ end
49
+ s0
50
+ end
51
+
52
+ def parse_version22
53
+ s0 = @current_pos
54
+ s1 = []
55
+ s2 = parse_comment
56
+ while s2 != :failed
57
+ s1 << s2
58
+ s2 = parse_comment
59
+ end
60
+ if s1 != :failed
61
+ s2 = match_str("V2.2")
62
+ if s2 != :failed
63
+ s3 = parse_nl
64
+ if s3 != :failed
65
+ s0 = s1 = [s1, s2, s3]
66
+ else
67
+ @current_pos = s0
68
+ s0 = :failed
69
+ end
70
+ else
71
+ @current_pos = s0
72
+ s0 = :failed
73
+ end
74
+ else
75
+ @current_pos = s0
76
+ s0 = :failed
77
+ end
78
+ s0
79
+ end
80
+
81
+ def parse_information
82
+ s0 = @current_pos
83
+ s1 = parse_players
84
+ s1 = nil if s1 == :failed
85
+ if s1 != :failed
86
+ s2 = parse_headers
87
+ if s2 != :failed
88
+ @reported_pos = s0
89
+ s0 = s1 = { "players" => s1, "header" => s2 }
90
+ else
91
+ @current_pos = s0
92
+ s0 = :failed
93
+ end
94
+ else
95
+ @current_pos = s0
96
+ s0 = :failed
97
+ end
98
+ s0
99
+ end
100
+
101
+ def parse_headers
102
+ s0 = @current_pos
103
+ s1 = []
104
+ s2 = parse_header
105
+ while s2 != :failed
106
+ s1 << s2
107
+ s2 = parse_header
108
+ end
109
+ if s1 != :failed
110
+ @reported_pos = s0
111
+ s1 = -> (header) {
112
+ ret = {}
113
+ header.each do |data|
114
+ ret[normalize_header_key(data["k"])] = data["v"]
115
+ end
116
+ ret
117
+ }.call(s1)
118
+ end
119
+ s0 = s1
120
+ s0
121
+ end
122
+
123
+ def parse_header
124
+ s0 = @current_pos
125
+ s1 = []
126
+ s2 = parse_comment
127
+ while s2 != :failed
128
+ s1 << s2
129
+ s2 = parse_comment
130
+ end
131
+ if s1 != :failed
132
+ s2 = match_str("$")
133
+ if s2 != :failed
134
+ s3 = []
135
+ s4 = match_regexp(/^[^:]/)
136
+ if s4 != :failed
137
+ while s4 != :failed
138
+ s3 << s4
139
+ s4 = match_regexp(/^[^:]/)
140
+ end
141
+ else
142
+ s3 = :failed
143
+ end
144
+ if s3 != :failed
145
+ s4 = match_str(":")
146
+ if s4 != :failed
147
+ s5 = []
148
+ s6 = parse_nonl
149
+ while s6 != :failed
150
+ s5 << s6
151
+ s6 = parse_nonl
152
+ end
153
+ if s5 != :failed
154
+ s6 = parse_nl
155
+ if s6 != :failed
156
+ @reported_pos = s0
157
+ s0 = s1 = { "k" => s3.join, "v" => s5.join }
158
+ else
159
+ @current_pos = s0
160
+ s0 = :failed
161
+ end
162
+ else
163
+ @current_pos = s0
164
+ s0 = :failed
165
+ end
166
+ else
167
+ @current_pos = s0
168
+ s0 = :failed
169
+ end
170
+ else
171
+ @current_pos = s0
172
+ s0 = :failed
173
+ end
174
+ else
175
+ @current_pos = s0
176
+ s0 = :failed
177
+ end
178
+ else
179
+ @current_pos = s0
180
+ s0 = :failed
181
+ end
182
+ s0
183
+ end
184
+
185
+ def parse_csa1
186
+ s0 = @current_pos
187
+ s1 = parse_players
188
+ s1 = nil if s1 == :failed
189
+ if s1 != :failed
190
+ s2 = parse_initial_board
191
+ s2 = nil if s2 == :failed
192
+ if s2 != :failed
193
+ s3 = parse_moves
194
+ if s3 != :failed
195
+ @reported_pos = s0
196
+ s0 = s1 = -> (ply, ini, ms) {
197
+ ret = { "header" => {}, "initial" => ini, "moves" => ms }
198
+ if ply
199
+ ret["header"]["先手"] = ply[0] if ply[0]
200
+ ret["header"]["後手"] = ply[1] if ply[1]
201
+ end
202
+ ret
203
+ }.call(s1, s2, s3)
204
+ else
205
+ @current_pos = s0
206
+ s0 = :failed
207
+ end
208
+ else
209
+ @current_pos = s0
210
+ s0 = :failed
211
+ end
212
+ else
213
+ @current_pos = s0
214
+ s0 = :failed
215
+ end
216
+ s0
217
+ end
218
+
219
+ def parse_players
220
+ s0 = @current_pos
221
+ s1 = []
222
+ s2 = parse_comment
223
+ while s2 != :failed
224
+ s1 << s2
225
+ s2 = parse_comment
226
+ end
227
+ if s1 != :failed
228
+ s2 = @current_pos
229
+ s3 = match_str("N+")
230
+ if s3 != :failed
231
+ s4 = []
232
+ s5 = parse_nonl
233
+ while s5 != :failed
234
+ s4 << s5
235
+ s5 = parse_nonl
236
+ end
237
+ if s4 != :failed
238
+ s5 = parse_nl
239
+ if s5 != :failed
240
+ @reported_pos = s2
241
+ s2 = s3 = s4
242
+ else
243
+ @current_pos = s2
244
+ s2 = :failed
245
+ end
246
+ else
247
+ @current_pos = s2
248
+ s2 = :failed
249
+ end
250
+ else
251
+ @current_pos = s2
252
+ s2 = :failed
253
+ end
254
+ s2 = nil if s2 == :failed
255
+ if s2 != :failed
256
+ s3 = []
257
+ s4 = parse_comment
258
+ while s4 != :failed
259
+ s3 << s4
260
+ s4 = parse_comment
261
+ end
262
+ if s3 != :failed
263
+ s4 = @current_pos
264
+ s5 = match_str("N-")
265
+ if s5 != :failed
266
+ s6 = []
267
+ s7 = parse_nonl
268
+ while s7 != :failed
269
+ s6 << s7
270
+ s7 = parse_nonl
271
+ end
272
+ if s6 != :failed
273
+ s7 = parse_nl
274
+ if s7 != :failed
275
+ @reported_pos = s4
276
+ s4 = s5 = s6
277
+ else
278
+ @current_pos = s4
279
+ s4 = :failed
280
+ end
281
+ else
282
+ @current_pos = s4
283
+ s4 = :failed
284
+ end
285
+ else
286
+ @current_pos = s4
287
+ s4 = :failed
288
+ end
289
+ s4 = nil if s4 == :failed
290
+ if s4 != :failed
291
+ @reported_pos = s0
292
+ s0 = s1 = [(s2 ? s2.join : nil), (s4 ? s4.join : nil)]
293
+ else
294
+ @current_pos = s0
295
+ s0 = :failed
296
+ end
297
+ else
298
+ @current_pos = s0
299
+ s0 = :failed
300
+ end
301
+ else
302
+ @current_pos = s0
303
+ s0 = :failed
304
+ end
305
+ else
306
+ @current_pos = s0
307
+ s0 = :failed
308
+ end
309
+ s0
310
+ end
311
+
312
+ def parse_initial_board
313
+ s0 = @current_pos
314
+ s1 = []
315
+ s2 = parse_comment
316
+ while s2 != :failed
317
+ s1 << s2
318
+ s2 = parse_comment
319
+ end
320
+ if s1 != :failed
321
+ s2 = parse_hirate
322
+ if s2 == :failed
323
+ s2 = parse_ikkatsu
324
+ if s2 == :failed
325
+ s2 = @current_pos
326
+ s3 = match_str("")
327
+ if s3 != :failed
328
+ @reported_pos = s2
329
+ s3 = "NO"
330
+ end
331
+ s2 = s3
332
+ end
333
+ end
334
+ if s2 != :failed
335
+ s3 = parse_komabetsu
336
+ if s3 != :failed
337
+ s4 = []
338
+ s5 = parse_comment
339
+ while s5 != :failed
340
+ s4 << s5
341
+ s5 = parse_comment
342
+ end
343
+ if s4 != :failed
344
+ s5 = parse_teban
345
+ if s5 != :failed
346
+ s6 = parse_nl
347
+ if s6 != :failed
348
+ @reported_pos = s0
349
+ s0 = s1 = -> (data, koma, teban) {
350
+ if data == "NO"
351
+ data = koma
352
+ else
353
+ data["data"]["hands"] = koma["data"]["hands"]
354
+ end
355
+ data["data"]["color"] = teban
356
+ data
357
+ }.call(s2, s3, s5)
358
+ else
359
+ @current_pos = s0
360
+ s0 = :failed
361
+ end
362
+ else
363
+ @current_pos = s0
364
+ s0 = :failed
365
+ end
366
+ else
367
+ @current_pos = s0
368
+ s0 = :failed
369
+ end
370
+ else
371
+ @current_pos = s0
372
+ s0 = :failed
373
+ end
374
+ else
375
+ @current_pos = s0
376
+ s0 = :failed
377
+ end
378
+ else
379
+ @current_pos = s0
380
+ s0 = :failed
381
+ end
382
+ s0
383
+ end
384
+
385
+ def parse_hirate
386
+ s0 = @current_pos
387
+ s1 = match_str("PI")
388
+ if s1 != :failed
389
+ s2 = []
390
+ s3 = parse_xy_piece
391
+ while s3 != :failed
392
+ s2 << s3
393
+ s3 = parse_xy_piece
394
+ end
395
+ if s2 != :failed
396
+ s3 = parse_nl
397
+ if s3 != :failed
398
+ @reported_pos = s0
399
+ s0 = s1 = -> (ps) {
400
+ ret = { "preset" => "OTHER", "data" => { "board" => get_hirate } }
401
+ ps.each do |piece|
402
+ ret["data"]["board"][piece["xy"]["x"]-1][piece["xy"]["y"]-1] = {}
403
+ end
404
+ ret
405
+ }.call(s2)
406
+ else
407
+ @current_pos = s0
408
+ s0 = :failed
409
+ end
410
+ else
411
+ @current_pos = s0
412
+ s0 = :failed
413
+ end
414
+ else
415
+ @current_pos = s0
416
+ s0 = :failed
417
+ end
418
+ s0
419
+ end
420
+
421
+ def parse_ikkatsu
422
+ s0 = @current_pos
423
+ s1 = []
424
+ s2 = parse_ikkatsu_line
425
+ if s2 != :failed
426
+ while s2 != :failed
427
+ s1 << s2
428
+ s2 = parse_ikkatsu_line
429
+ end
430
+ else
431
+ s1 = :failed
432
+ end
433
+ if s1 != :failed
434
+ @reported_pos = s0
435
+ s1 = -> (lines) {
436
+ board = []
437
+ 9.times { |i|
438
+ line = []
439
+ 9.times { |j|
440
+ line << lines[j][8-i]
441
+ }
442
+ board << line
443
+ }
444
+ { "preset" => "OTHER", "data" => { "board" => board } }
445
+ }.call(s1)
446
+ end
447
+ s0 = s1
448
+ s0
449
+ end
450
+
451
+ def parse_ikkatsu_line
452
+ s0 = @current_pos
453
+ s1 = match_str("P")
454
+ if s1 != :failed
455
+ s2 = match_regexp(/^[1-9]/)
456
+ if s2 != :failed
457
+ s3 = []
458
+ s4 = parse_masu
459
+ if s4 != :failed
460
+ while s4 != :failed
461
+ s3 << s4
462
+ s4 = parse_masu
463
+ end
464
+ else
465
+ s3 = :failed
466
+ end
467
+ if s3 != :failed
468
+ s4 = parse_nl
469
+ if s4 != :failed
470
+ @reported_pos = s0
471
+ s0 = s1 = s3
472
+ else
473
+ @current_pos = s0
474
+ s0 = :failed
475
+ end
476
+ else
477
+ @current_pos = s0
478
+ s0 = :failed
479
+ end
480
+ else
481
+ @current_pos = s0
482
+ s0 = :failed
483
+ end
484
+ else
485
+ @current_pos = s0
486
+ s0 = :failed
487
+ end
488
+ s0
489
+ end
490
+
491
+ def parse_masu
492
+ s0 = @current_pos
493
+ s1 = parse_teban
494
+ if s1 != :failed
495
+ s2 = parse_piece
496
+ if s2 != :failed
497
+ @reported_pos = s0
498
+ s0 = s1 = { "color" => s1, "kind" => s2 }
499
+ else
500
+ @current_pos = s0
501
+ s0 = :failed
502
+ end
503
+ else
504
+ @current_pos = s0
505
+ s0 = :failed
506
+ end
507
+ if s0 == :failed
508
+ s0 = @current_pos
509
+ s1 = match_str(" * ")
510
+ if s1 != :failed
511
+ @reported_pos = s0
512
+ s1 = {}
513
+ end
514
+ s0 = s1
515
+ end
516
+ s0
517
+ end
518
+
519
+ def parse_komabetsu
520
+ s0 = @current_pos
521
+ s1 = []
522
+ s2 = parse_komabetsu_line
523
+ while s2 != :failed
524
+ s1 << s2
525
+ s2 = parse_komabetsu_line
526
+ end
527
+ if s1 != :failed
528
+ @reported_pos = s0
529
+ s1 = -> (lines) {
530
+ board = []
531
+ hands = [
532
+ {"FU"=>0,"KY"=>0,"KE"=>0,"GI"=>0,"KI"=>0,"KA"=>0,"HI"=>0},
533
+ {"FU"=>0,"KY"=>0,"KE"=>0,"GI"=>0,"KI"=>0,"KA"=>0,"HI"=>0}
534
+ ]
535
+ all = {"FU"=>18,"KY"=>4,"KE"=>4,"GI"=>4,"KI"=>4,"KA"=>2,"HI"=>2}
536
+ 9.times { |i|
537
+ line = []
538
+ 9.times { |j|
539
+ line << {}
540
+ }
541
+ board << line
542
+ }
543
+
544
+ lines.each do |line|
545
+ line["pieces"].each do |piece|
546
+ if piece["xy"]["x"] == 0
547
+ if piece["piece"] == "AL"
548
+ hands[line["teban"]] = all
549
+ return { "preset" => "OTHER", "data" => { "board" => board, "hands" => hands } }
550
+ end
551
+ obj = hands[line["teban"]]
552
+ obj[piece["piece"]] += 1
553
+ else
554
+ board[piece["xy"]["x"]-1][piece["xy"]["y"]-1] = { "color" => line["teban"], "kind" => piece["piece"] }
555
+ end
556
+ all[piece["piece"]] -= 1 if piece["piece"] != "OU"
557
+ end
558
+ end
559
+
560
+ { "preset" => "OTHER", "data" => { "board" => board, "hands" => hands } }
561
+ }.call(s1)
562
+ end
563
+ s0 = s1
564
+ s0
565
+ end
566
+
567
+ def parse_komabetsu_line
568
+ s0 = @current_pos
569
+ s1 = match_str("P")
570
+ if s1 != :failed
571
+ s2 = parse_teban
572
+ if s2 != :failed
573
+ s3 = []
574
+ s4 = parse_xy_piece
575
+ if s4 != :failed
576
+ while s4 != :failed
577
+ s3 << s4
578
+ s4 = parse_xy_piece
579
+ end
580
+ else
581
+ s3 = :failed
582
+ end
583
+ if s3 != :failed
584
+ s4 = parse_nl
585
+ if s4 != :failed
586
+ @reported_pos = s0
587
+ s0 = s1 = { "teban" => s2, "pieces" => s3 }
588
+ else
589
+ @current_pos = s0
590
+ s0 = :failed
591
+ end
592
+ else
593
+ @current_pos = s0
594
+ s0 = :failed
595
+ end
596
+ else
597
+ @current_pos = s0
598
+ s0 = :failed
599
+ end
600
+ else
601
+ @current_pos = s0
602
+ s0 = :failed
603
+ end
604
+ s0
605
+ end
606
+
607
+ def parse_moves
608
+ s0 = @current_pos
609
+ s1 = parse_firstboard
610
+ if s1 != :failed
611
+ s2 = []
612
+ s3 = parse_move
613
+ while s3 != :failed
614
+ s2 << s3
615
+ s3 = parse_move
616
+ end
617
+ if s2 != :failed
618
+ s3 = []
619
+ s4 = parse_comment
620
+ while s4 != :failed
621
+ s3 << s4
622
+ s4 = parse_comment
623
+ end
624
+ if s3 != :failed
625
+ @reported_pos = s0
626
+ s0 = s1 = s2.unshift(s1)
627
+ else
628
+ @current_pos = s0
629
+ s0 = :failed
630
+ end
631
+ else
632
+ @current_pos = s0
633
+ s0 = :failed
634
+ end
635
+ else
636
+ @current_pos = s0
637
+ s0 = :failed
638
+ end
639
+ s0
640
+ end
641
+
642
+ def parse_firstboard
643
+ s0 = @current_pos
644
+ s1 = []
645
+ s2 = parse_comment
646
+ while s2 != :failed
647
+ s1 << s2
648
+ s2 = parse_comment
649
+ end
650
+ if s1 != :failed
651
+ @reported_pos = s0
652
+ s1 = s1.length > 0 ? { "comments" => s1 } : {}
653
+ end
654
+ s0 = s1
655
+ s0
656
+ end
657
+
658
+ def parse_move
659
+ s0 = @current_pos
660
+ s1 = parse_normal_move
661
+ s1 = parse_special_move if s1 == :failed
662
+ if s1 != :failed
663
+ s2 = parse_time
664
+ s2 = nil if s2 == :failed
665
+ if s2 != :failed
666
+ s3 = []
667
+ s4 = parse_comment
668
+ while s4 != :failed
669
+ s3 << s4
670
+ s4 = parse_comment
671
+ end
672
+ if s3 != :failed
673
+ @reported_pos = s0
674
+ s0 = s1 = -> (move, time, comments) {
675
+ ret = {}
676
+ ret["comments"] = comments if comments.length > 0
677
+ ret["time"] = time if time
678
+ if move["special"]
679
+ ret["special"] = move["special"]
680
+ else
681
+ ret["move"] = move
682
+ end
683
+ ret
684
+ }.call(s1, s2, s3)
685
+ else
686
+ @current_pos = s0
687
+ s0 = :failed
688
+ end
689
+ else
690
+ @current_pos = s0
691
+ s0 = :failed
692
+ end
693
+ else
694
+ @current_pos = s0
695
+ s0 = :failed
696
+ end
697
+ s0
698
+ end
699
+
700
+ def parse_normal_move
701
+ s0 = @current_pos
702
+ s1 = parse_teban
703
+ if s1 != :failed
704
+ s2 = parse_xy
705
+ if s2 != :failed
706
+ s3 = parse_xy
707
+ if s3 != :failed
708
+ s4 = parse_piece
709
+ if s4 != :failed
710
+ s5 = parse_nl
711
+ if s5 != :failed
712
+ @reported_pos = s0
713
+ s0 = s1 = -> (from, to, piece) {
714
+ ret = { "to" => to, "piece" => piece }
715
+ ret["from"] = from if from["x"] != 0
716
+ ret
717
+ }.call(s2, s3, s4)
718
+ else
719
+ @current_pos = s0
720
+ s0 = :failed
721
+ end
722
+ else
723
+ @current_pos = s0
724
+ s0 = :failed
725
+ end
726
+ else
727
+ @current_pos = s0
728
+ s0 = :failed
729
+ end
730
+ else
731
+ @current_pos = s0
732
+ s0 = :failed
733
+ end
734
+ else
735
+ @current_pos = s0
736
+ s0 = :failed
737
+ end
738
+ s0
739
+ end
740
+
741
+ def parse_special_move
742
+ s0 = @current_pos
743
+ s1 = match_str("%")
744
+ if s1 != :failed
745
+ s2 = []
746
+ s3 = match_regexp(/^[\-+_A-Z]/)
747
+ if s3 != :failed
748
+ while s3 != :failed
749
+ s2 << s3
750
+ s3 = match_regexp(/^[\-+_A-Z]/)
751
+ end
752
+ else
753
+ s2 = :failed
754
+ end
755
+ if s2 != :failed
756
+ s3 = parse_nl
757
+ if s3 != :failed
758
+ @reported_pos = s0
759
+ s0 = s1 = { "special" => s2.join }
760
+ else
761
+ @current_pos = s0
762
+ s0 = :failed
763
+ end
764
+ else
765
+ @current_pos = s0
766
+ s0 = :failed
767
+ end
768
+ else
769
+ @current_pos = s0
770
+ s0 = :failed
771
+ end
772
+ s0
773
+ end
774
+
775
+ def parse_teban
776
+ s0 = @current_pos
777
+ s1 = match_str("+")
778
+ if s1 != :failed
779
+ @reported_pos = s0
780
+ s1 = 0
781
+ end
782
+ s0 = s1
783
+ if s0 == :failed
784
+ s0 = @current_pos
785
+ s1 = match_str("-")
786
+ if s1 != :failed
787
+ @reported_pos = s0
788
+ s1 = 1
789
+ end
790
+ s0 = s1
791
+ end
792
+ s0
793
+ end
794
+
795
+ def parse_comment
796
+ s0 = @current_pos
797
+ s1 = match_str("'")
798
+ if s1 != :failed
799
+ s2 = []
800
+ s3 = parse_nonl
801
+ while s3 != :failed
802
+ s2 << s3
803
+ s3 = parse_nonl
804
+ end
805
+ if s2 != :failed
806
+ s3 = parse_nl
807
+ if s3 != :failed
808
+ @reported_pos = s0
809
+ s0 = s1 = s2.join
810
+ else
811
+ @current_pos = s0
812
+ s0 = :failed
813
+ end
814
+ else
815
+ @current_pos = s0
816
+ s0 = :failed
817
+ end
818
+ else
819
+ @current_pos = s0
820
+ s0 = :failed
821
+ end
822
+ s0
823
+ end
824
+
825
+ def parse_time
826
+ s0 = @current_pos
827
+ s1 = match_str("T")
828
+ if s1 != :failed
829
+ s2 = []
830
+ s3 = match_regexp(/^[0-9]/)
831
+ while s3 != :failed
832
+ s2 << s3
833
+ s3 = match_regexp(/^[0-9]/)
834
+ end
835
+ if s2 != :failed
836
+ s3 = parse_nl
837
+ if s3 != :failed
838
+ @reported_pos = s0
839
+ s0 = s1 = { "now" => sec2time(s2.join.to_i) }
840
+ else
841
+ @current_pos = s0
842
+ s0 = :failed
843
+ end
844
+ else
845
+ @current_pos = s0
846
+ s0 = :failed
847
+ end
848
+ else
849
+ @current_pos = s0
850
+ s0 = :failed
851
+ end
852
+ s0
853
+ end
854
+
855
+ def parse_xy
856
+ s0 = @current_pos
857
+ s1 = match_regexp(/^[0-9]/)
858
+ if s1 != :failed
859
+ s2 = match_regexp(/^[0-9]/)
860
+ if s2 != :failed
861
+ @reported_pos = s0
862
+ s0 = s1 = { "x" => s1.to_i, "y" => s2.to_i }
863
+ else
864
+ @current_pos = s0
865
+ s0 = :failed
866
+ end
867
+ else
868
+ @current_pos = s0
869
+ s0 = :failed
870
+ end
871
+ s0
872
+ end
873
+
874
+ def parse_piece
875
+ s0 = @current_pos
876
+ s1 = match_regexp(/^[A-Z]/)
877
+ if s1 != :failed
878
+ s2 = match_regexp(/^[A-Z]/)
879
+ if s2 != :failed
880
+ @reported_pos = s0
881
+ s0 = s1 = s1 + s2
882
+ else
883
+ @current_pos = s0
884
+ s0 = :failed
885
+ end
886
+ else
887
+ @current_pos = s0
888
+ s0 = :failed
889
+ end
890
+ s0
891
+ end
892
+
893
+ def parse_xy_piece
894
+ s0 = @current_pos
895
+ s1 = parse_xy
896
+ if s1 != :failed
897
+ s2 = parse_piece
898
+ if s2 != :failed
899
+ @reported_pos = s0
900
+ s0 = s1 = { "xy" => s1, "piece" => s2 }
901
+ else
902
+ @current_pos = s0
903
+ s0 = :failed
904
+ end
905
+ else
906
+ @current_pos = s0
907
+ s0 = :failed
908
+ end
909
+ s0
910
+ end
911
+
912
+ def parse_nl
913
+ s0 = @current_pos
914
+ s1 = match_str("\r")
915
+ s1 = nil if s1 == :failed
916
+ if s1 != :failed
917
+ s2 = match_str("\n")
918
+ if s2 != :failed
919
+ s0 = s1 = [s1, s2]
920
+ else
921
+ @current_pos = s0
922
+ s0 = :failed
923
+ end
924
+ else
925
+ @current_pos = s0
926
+ s0 = :failed
927
+ end
928
+ if s0 == :failed
929
+ s0 = @current_pos
930
+ s1 = []
931
+ s2 = match_str(" ")
932
+ while s2 != :failed
933
+ s1 << s2
934
+ s2 = match_str(" ")
935
+ end
936
+ if s1 != :failed
937
+ s2 = match_str(",")
938
+ if s2 != :failed
939
+ s0 = s1 = [s1, s2]
940
+ else
941
+ @current_pos = s0
942
+ s0 = :failed
943
+ end
944
+ else
945
+ @current_pos = s0
946
+ s0 = :failed
947
+ end
948
+ end
949
+ s0
950
+ end
951
+
952
+ def parse_nonl
953
+ match_regexp(/^[^\r\n]/)
954
+ end
955
+
956
+ protected
957
+
958
+ def sec2time(sec)
959
+ s = sec % 60
960
+ m = (sec-s) / 60
961
+ { "m" => m, "s" => s }
962
+ end
963
+
964
+ def get_hirate
965
+ [
966
+ [{"color" => 1,"kind" => "KY"},{ },{"color" => 1,"kind" => "FU"},{},{},{},{"color" => 0,"kind" => "FU"},{ },{"color" => 0,"kind" => "KY"},],
967
+ [{"color" => 1,"kind" => "KE"},{"color" => 1,"kind" => "KA"},{"color" => 1,"kind" => "FU"},{},{},{},{"color" => 0,"kind" => "FU"},{"color" => 0,"kind" => "HI"},{"color" => 0,"kind" => "KE"},],
968
+ [{"color" => 1,"kind" => "GI"},{ },{"color" => 1,"kind" => "FU"},{},{},{},{"color" => 0,"kind" => "FU"},{ },{"color" => 0,"kind" => "GI"},],
969
+ [{"color" => 1,"kind" => "KI"},{ },{"color" => 1,"kind" => "FU"},{},{},{},{"color" => 0,"kind" => "FU"},{ },{"color" => 0,"kind" => "KI"},],
970
+ [{"color" => 1,"kind" => "OU"},{ },{"color" => 1,"kind" => "FU"},{},{},{},{"color" => 0,"kind" => "FU"},{ },{"color" => 0,"kind" => "OU"},],
971
+ [{"color" => 1,"kind" => "KI"},{ },{"color" => 1,"kind" => "FU"},{},{},{},{"color" => 0,"kind" => "FU"},{ },{"color" => 0,"kind" => "KI"},],
972
+ [{"color" => 1,"kind" => "GI"},{ },{"color" => 1,"kind" => "FU"},{},{},{},{"color" => 0,"kind" => "FU"},{ },{"color" => 0,"kind" => "GI"},],
973
+ [{"color" => 1,"kind" => "KE"},{"color" => 1,"kind" => "HI"},{"color" => 1,"kind" => "FU"},{},{},{},{"color" => 0,"kind" => "FU"},{"color" => 0,"kind" => "KA"},{"color" => 0,"kind" => "KE"},],
974
+ [{"color" => 1,"kind" => "KY"},{ },{"color" => 1,"kind" => "FU"},{},{},{},{"color" => 0,"kind" => "FU"},{ },{"color" => 0,"kind" => "KY"},],
975
+ ]
976
+ end
977
+
978
+ def normalize_header_key(key)
979
+ {
980
+ "EVENT" => "棋戦",
981
+ "SITE" => "場所",
982
+ "START_TIME" => "開始日時",
983
+ "END_TIME" => "終了日時",
984
+ "TIME_LIMIT" => "持ち時間",
985
+ }[key] || key
986
+ end
987
+ end
988
+ end