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