shnewto / pgn / Pgn

This is a library for parsing "Portable Game Notation" (PGN) for standard chess. PGN is a plain text standard for recording chess games. For more information check out the Wikipedia entry on PGN or the PGN spec itself.

Data Structures


type alias Pgn =
{ tagPairs : List TagPair
, moves : List Move 
}

The Pgn object represents a complete PGN. The tag pairs (or roster) typically contain archival or supplemental information for the game itself. And then there are the moves of the game itself.


type alias TagPair =
{ title : String
, value : String 
}

The TagPair strcuture should minimally contain what is also known as the "Seven Tag Roster" (STR). The tag pairs can extend beyond the standard seven however. A good example of a the tag pairs describing a game looks like this:

    [ Event "Russia - The Rest of the World" ]

    [ Site "Moscow RUS" ]

    [ Date "2002.09.09" ]

    [ EventDate "2002.09.08" ]

    [ Round "5" ]

    [ Result "1-0" ]

    [ White "Judit Polgar" ]

    [ Black "Garry Kasparov"]

    [ ECO "C67" ]

    [ WhiteElo "2681" ]

    [ BlackElo "2838" ]

    [ PlyCount "84" ]

Each statement (starting with [ and ending with ]) is a tag pair. So the tag pair [Result "1-0"] would be represented in the data structure as { title: "Result", value: "1-0"}

It's important to note that tag pairs are treated something like key, value pairs and the value must be in quotes!


type alias Move =
{ number : String
, white : String
, black : String 
}

The Move data structure contains the move number and the move of each player. A move in PGN like 42. Rxg7 Kc8 would be represented in this data structure as { number: "42", white: "Rxg7", black: "Kc8"}

The Parsers

parse : String -> Result (List Parser.DeadEnd) Pgn

The parse function expects a complete PGN as a string and returns either a PGN or a DeadEnd error.

For more information from any errors you see, check out the parseErrorToString function.

parseMove : String -> Result (List Parser.DeadEnd) Move

The parseMove function accepts input in the shape of a single line of Movetext, i.e. 1. e4 e5

    parseMove "1. e4 e5" ==
        Ok { number = "1", white = "e4", black = "e5" }

parseMoves : String -> Result (List Parser.DeadEnd) (List Move)

The parseMoves function accepts string input in the shape of a multiple lines of Movetext, i.e. 1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6

    parseMoves "1. e4 e5 2. Nf3 Nc6 3. Bb5 Nf6" ==
        Ok
            [ { number = "1"
              , white = "e4"
              , black = "e5"
              }
            , { number = "2", white = "Nf3", black = "Nc6" }
            , { number = "3", white = "Bb5", black = "Nf6" }
            ]

parseTagPair : String -> Result (List Parser.DeadEnd) TagPair

The parseTagPair function accepts string input in the shape of a single tag pair, i.e. [EventDate "2002.09.08"]

    parseTagPair "[EventDate \"2002.09.08\"]" ==
        Ok { title = "EventDate", value = "2002.09.08" }

parseTagPairs : String -> Result (List Parser.DeadEnd) (List TagPair)

The parseTagPairs function accepts string input in the shape of a series of tag pairs, i.e. [EventDate "2002.09.08"] [Round "5"]

    parseTagPairs "[EventDate \"2002.09.08\"]  [Round \"5\"]" ==
        Ok
            [ { title = "EventDate"
              , value = "2002.09.08"
              }
            , { title = "Round", value = "5" }
            ]

Errors

parseErrorToString : String -> List Parser.DeadEnd -> String

The parseErrorToString is to help pinpoint what's causing issues with a parse. It simply produces a string for human consumption that describes what the parser thinks went wrong, followed by the line of the error then a ^ below where it thinks the problem is. For example, attempting to parse this invalid tag pair:

    [EventTitle After the title, everything else in the tag pair needs to be in quotes!]

would result in this output:

    error on row:  1, col: 13. Problem: Expecting: \"
    > [EventTitle After the title everything else in the tag pair needs to be in quotes!]
                  ^