Skip to content

Instantly share code, notes, and snippets.

@rugyoga
Last active November 25, 2019 19:16
Show Gist options
  • Save rugyoga/bd5a6a1ed84e5c8b86124240fbe5e888 to your computer and use it in GitHub Desktop.
Save rugyoga/bd5a6a1ed84e5c8b86124240fbe5e888 to your computer and use it in GitHub Desktop.
Attempt at a simple PGN parser using Combine library
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