lib/jkf/parser/kif.rb in jkf-0.4.1 vs lib/jkf/parser/kif.rb in jkf-0.4.2
- old
+ new
@@ -1,11 +1,15 @@
# coding: utf-8
module Jkf::Parser
+ # KIF Parser
class Kif < Base
include Kifuable
+ protected
+
+ # kifu : skipline* header* initialboard? header* split? moves fork* nl?
def parse_root
@input += "\n" unless @input.end_with?("\n")
s0 = @current_pos
s1 = []
@@ -47,10 +51,13 @@
end
s0
end
+ # header : [^:\r\n]+ ":" nonls nl
+ # | turn "手番" nl
+ # | "盤面回転" nl
def parse_header
s0 = @current_pos
s2 = match_regexp(/^[^:\r\n]/)
if s2 != :failed
s1 = []
@@ -118,14 +125,16 @@
end
s0
end
+ # turn : [先後上下]
def parse_turn
- match_regexp(/[先後上下]/)
+ match_regexp(/^[先後上下]/)
end
+ # split : "手数----指手--" "-------消費時間--"? nl
def parse_split
s0 = @current_pos
s1 = match_str("手数----指手--")
if s1 != :failed
s2 = match_str("-------消費時間--")
@@ -142,10 +151,11 @@
s0 = :failed
end
s0
end
+ # moves : firstboard split? move* result?
def parse_moves
s0 = @current_pos
s1 = parse_firstboard
if s1 != :failed
parse_split
@@ -163,10 +173,11 @@
s0 = :failed
end
s0
end
+ # firstboard : comment* pointer?
def parse_firstboard
s0 = @current_pos
s1 = []
s2 = parse_comment
while s2 != :failed
@@ -177,10 +188,11 @@
@reported_pos = s0
s0 = s1.empty? ? {} : { "comments" => s1 }
s0
end
+ # move : line comment* pointer?
def parse_move
s0 = @current_pos
s1 = parse_line
if s1 != :failed
s2 = []
@@ -197,10 +209,11 @@
s0 = :failed
end
s0
end
+ # line : " "* te " "* (fugou from | [^\r\n ]*) " "* time? "+"? nl
def parse_line
s0 = @current_pos
match_spaces
s2 = parse_te
if s2 != :failed
@@ -252,14 +265,16 @@
s0 = :failed
end
s0
end
+ # te : [0-9]+
def parse_te
match_digits!
end
+ # fugou : place piece "成"?
def parse_fugou
s0 = @current_pos
s1 = parse_place
if s1 != :failed
s2 = parse_piece
@@ -277,10 +292,11 @@
s0 = :failed
end
s0
end
+ # place : num numkan | "同 "
def parse_place
s0 = @current_pos
s1 = parse_num
if s1 != :failed
s2 = parse_numkan
@@ -305,10 +321,11 @@
s0 = s1
end
s0
end
+ # from : "打" | "(" [1-9] [1-9] ")"
def parse_from
s0 = @current_pos
s1 = match_str("打")
if s1 != :failed
@reported_pos = s0
@@ -343,20 +360,24 @@
end
end
s0
end
+ # time : "(" " "* ms " "* "/" " "* (hms | ms) " "* ")"
def parse_time
s0 = @current_pos
if match_str("(") != :failed
match_spaces
s3 = parse_ms
if s3 != :failed
+ match_spaces
if match_str("/") != :failed
+ match_spaces
s5 = parse_hms
s5 = parse_ms(with_hour: true) if s5 == :failed
if s5 != :failed
+ match_spaces
if match_str(")") != :failed
@reported_pos = s0
s0 = { "now" => s3, "total" => s5 }
else
@current_pos = s0
@@ -379,10 +400,11 @@
s0 = :failed
end
s0
end
+ # hms : [0-9]+ ":" [0-9]+ ":" [0-9]+
def parse_hms
s0 = @current_pos
s1 = match_digits!
if s1 != :failed
@@ -415,10 +437,11 @@
s0 = :failed
end
s0
end
+ # ms : [0-9]+ ":" [0-9]+
def parse_ms(with_hour: false)
s0 = @current_pos
s1 = match_digits!
if s1 != :failed
if match_str(":") != :failed
@@ -447,10 +470,11 @@
s0 = :failed
end
s0
end
+ # comment : "*" nonls nl | "&" nonls nl
def parse_comment
s0 = @current_pos
if match_str("*") != :failed
s2 = parse_nonls
if parse_nl != :failed
@@ -482,10 +506,11 @@
end
end
s0
end
+ # fork : "変化:" " "* [0-9]+ "手" nl moves
def parse_fork
s0 = @current_pos
if match_str("変化:") != :failed
match_spaces
s3 = parse_te
@@ -517,12 +542,11 @@
s0 = :failed
end
s0
end
- protected
-
+ # transfrom to jkf
def transform_root(headers, ini, headers2, moves, forks)
ret = { "header" => {}, "moves" => moves }
headers.compact.each { |h| ret["header"][h["k"]] = h["v"] }
headers2.compact.each { |h| ret["header"][h["k"]] = h["v"] }
if ini
@@ -537,10 +561,11 @@
reverse_color(ret["moves"])
end
ret
end
+ # transform move to jkf
def transform_move(line, c)
ret = {}
ret["comments"] = c if !c.empty?
if line["move"].is_a? Hash
ret["move"] = line["move"]
@@ -549,10 +574,11 @@
end
ret["time"] = line["time"] if line["time"]
ret
end
+ # transform teban-fugou-from to jkf
def transform_teban_fugou_from(teban, fugou, from)
ret = { "color" => teban2color(teban.join), "piece" => fugou["piece"] }
if fugou["to"]
ret["to"] = fugou["to"]
else
@@ -561,10 +587,11 @@
ret["promote"] = true if fugou["promote"]
ret["from"] = from if from
ret
end
+ # special string to csa
def special2csa(str)
{
"中断" => "CHUDAN",
"投了" => "TORYO",
"持将棋" => "JISHOGI",
@@ -575,15 +602,17 @@
"反則勝ち" => "ILLEGAL_ACTION", # 直前の手が反則(先頭に+か-で反則した側の情報を含める必要が有る)
"反則負け" => "ILLEGAL_MOVE" # ここで手番側が反則,反則の内容はコメントで表現
}[str] || (raise ParseError)
end
+ # teban to color
def teban2color(teban)
teban = teban.to_i unless teban.is_a? Fixnum
(teban + 1) % 2
end
+ # generate motigoma
def make_hand(str)
# Kifu for iPhoneは半角スペース区切り
ret = { "FU" => 0, "KY" => 0, "KE" => 0, "GI" => 0, "KI" => 0, "KA" => 0, "HI" => 0 }
return ret if str.empty?
@@ -593,9 +622,10 @@
end
ret
end
+ # exchange sente gote
def reverse_color(moves)
moves.each do |move|
if move["move"] && move["move"]["color"]
move["move"]["color"] = (move["move"]["color"] + 1) % 2
end