Last active
November 25, 2019 19:16
-
-
Save rugyoga/bd5a6a1ed84e5c8b86124240fbe5e888 to your computer and use it in GitHub Desktop.
Attempt at a simple PGN parser using Combine library
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Chess.PGN do | |
use Combine | |
@dquote ?" | |
@open_square ?[ | |
@close_square ?] | |
@backslash ?\ | |
def parse(str) do | |
Combine.parse(str, parser) | |
end | |
def parser do | |
game | |
end | |
def open_square(parser), do: parser |> char(@open_square) | |
def close_square(parser), do: parser |> char(@close_square) | |
def dquote(parser), do: parser |> char(@dquote) | |
def backslash(parser), do: parser |> char(@backslash) | |
def non_dquote(parser), do: parser |> none_of(char, ["\""]) | |
def one_whitespace(parser), do: parser |> choice([space, tab, newline]) | |
def whitespace(parser), do: skip_many(one_whitespace(parser)) | |
def non_open_square_bracket(parser), do: parser |> none_of(char, ["["]) | |
def non_close_square_bracket(parser), do: parser |> none_of(char, ["]"]) | |
def escaped_dquote(parser), do: parser |> skip(backslash) |> dquote | |
def escaped_backslash(parser), do: parser |> skip(backslash) |> backslash | |
def moves(parser) do | |
parser |> pipe([many(non_open_square_bracket)], &Enum.join/1) | |
end | |
def game(parser) do | |
parser | |
|> whitespace | |
|> many(header) | |
#|> moves() | |
|> eof | |
end | |
def header(parser) do | |
parser | |
|> between(open_square(), | |
pair_both(key, value), | |
close_square) | |
|> whitespace | |
end | |
def key(parser) do | |
parser | |
|> whitespace | |
|> label(word, "key") | |
|> whitespace | |
end | |
def value do | |
parser | |
|> label(value_string(), "value") | |
|> whitespace | |
end | |
def value_string(parser) do | |
parser | |
|> between(dquote, | |
map(many(valid), &Enum.join/1), | |
dquote) | |
end | |
def valid(parser) do | |
parser | |
|> choice([escaped_dquote, | |
escaped_backslash, | |
non_dquote]) | |
end | |
end | |
#input = File.read!(Path.join([__DIR__, "..", "data", "one_game.pgn"])) | |
input = """ | |
[Event "Mechanics' Bedjanian TNM; G/2 d/5"] | |
[Site "San Francisco"] | |
[Date "2018.11.13"] | |
[Round "4.42"] | |
[White "Abdi, Mehron Edward"] | |
[Black "Chan, John"] | |
[Result "0-1"] | |
[ECO "C00"] | |
[WhiteElo "1142"] | |
[BlackElo "1546"] | |
[PlyCount "106"] | |
[EventDate "2018.??.??"] | |
[Source "ChessBase"] | |
[SourceDate "2007.09.04"] | |
1. e4 e6 2. Bc4 c6 3. Nf3 b5 4. Bb3 a5 5. d3 ({Both scoresheets say} 5. c3 { | |
Well, one says "Pc3"...}) 5... h6 6. O-O Bb7 7. a4 b4 8. c3 {Both scoresheets} | |
Na6 9. Re1 d6 10. d4 Ne7 11. d5 cxd5 12. exd5 e5 13. Bc4 Bc8 14. Qe2 Nc5 15. | |
Bd2 Qb6 16. Rc1 Ng6 17. Qe1 b3 18. Qe2 Be7 19. Na3 O-O 20. Be3 Kh8 21. Nb5 f5 | |
22. Bxb3 f4 23. Bxc5 Qxc5 24. Bc4 Qb6 25. b4 Bf6 26. Qc2 Ne7 27. bxa5 Rxa5 28. | |
Na3 Qc7 29. Bb5 Nxd5 30. Nc4 Ra7 31. a5 Ne7 32. Rd1 d5 33. Nb6 Bf5 34. Qb3 Rxa5 | |
35. Ba4 Rb8 36. Qa3 Bc2 37. Rd2 Bxa4 38. Nxa4 Qc4 39. Rda2 Qc7 40. Qc1 Rba8 41. | |
Qd1 Nf5 42. g4 fxg3 43. hxg3 Nd6 44. Ne1 e4 45. Nc2 Nc4 46. Nb4 Qb7 47. Rd2 | |
Nxd2 48. Rc1 Nf3+ 49. Kg2 Rd8 50. c4 Qxb4 51. cxd5 Raxd5 52. Qxd5 Rxd5 53. Rc8+ | |
Kh7 0-1 | |
""" | |
IO.inspect(Chess.PGN.parse(input)) | |
#Chess.PGN.parse() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment