Parsing
Tip
Understanding parser combinators is a prerequisite for this module. See here for information.
| Parser.hs | |
|---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | |
- It's often useful to make a custom type for errors specific to the domain in question.
asumcomes from theAlternativetypeclass:asum [x,y,z]=x <|> y <|> z.either :: (a -> c) -> (b -> c) -> Either a b -> cis a useful function for handling anEither X Y.- Viewed with the Haskell Language Server, this will be underlined in blue, with a simplification suggested.
- Like anything else in Haskell, parsers are just values, so it's possible (and idiomatic) to put them in a list and then fold the list.
- Observe how the parser as a whole is built out of smaller parsers.
"place"is itself a parser, thanks to OverloadedStrings.a <$> b = fmap a b. That is:<$>is an infix synonym forfmap. Example withconst:fmap (const 1) [1,2,3,4] = [1,1,1,1]- We abstract some boilerplate with a function that makes a simple parser given a name and return value.
eofonly succeeds at the end of a line, so ensures there are no more characters left.returnis not a keyword. Here, it converts anInstructioninto aParser Instruction, namely the trivial parser that does nothing and immediately returns anInstruction. ThisParser Instructionis the final parser in the sequence of parsers in thedo-notationcode block.- do-notation used to build a complex parser out of a series of simpler ones and their results.
- Explicit imports like this are useful both for readability and to avoid namespace clashes.
- Another way to avoid namespace clashes. Common for both
Data.MapandData.Text. - Void is the empty type. This says that the custom error type is
Void(i.e. doesn't exist), and that the type of the input sequence isText.
Analysis¶
This module exists to parse user input on the command line into the Instruction type. Parsing directly into a custom type is idiomatic Haskell because it handles errors nicely: either parsing succeeds and you're guaranteed to get an Instruction, or you get an interpretable parse failure.
Note the use of word, a function which takes a parser and returns a new parser that handles white space. This abstracts white space handling to a single function, and makes for clean, idiomatic parsing.
parsePiece¶
parsePiece :: Ord a => Parsec a Text Piece
parsePiece = do
color <- word $ (const White <$> "white") <|> (const Black <$> "black")
pieceType <-
word $
try (const Bishop <$> "bishop")
<|> try (const King <$> "king")
<|> try (const Queen <$> "queen")
<|> try (const Knight <$> "knight")
<|> try (const Rook <$> "rook")
<|> try (const Pawn <$> "pawn")
return (Piece pieceType color)
parseRank¶
Last update:
January 18, 2023
Created: August 18, 2022
Created: August 18, 2022