quoridor-hs-0.1.0.0: src/Quoridor/Cmdline/Parse.hs
module Quoridor.Cmdline.Parse
( parseTurn
) where
import Control.Applicative (pure)
import Data.Char (toUpper)
import Data.Functor ((<$>))
import Data.List (elemIndex)
import Data.Maybe (fromJust)
import Text.Parsec (Parsec, char, digit, eof, many1,
oneOf, parse, spaces, (<|>))
import Quoridor
import Quoridor.Cmdline.Messages (validMovesChars)
type Parse = Parsec String ()
-- helper functions
pTurn :: Parse Turn
pTurn = do
res <- pMove <|> pShortCutMove <|> pPutGate
eof
return res
-- m y x
pMove :: Parse Turn
pMove = do
char 'm'
Move <$> pCell
-- one of 'validMovesChars', translated
-- into their index.
pShortCutMove :: Parse Turn
pShortCutMove = do
c <- oneOf validMovesChars
return $ ShortCutMove $ translate c
where translate c = fromJust $ elemIndex c validMovesChars
-- g y x h|v
pPutGate :: Parse Turn
pPutGate = do
char 'g'
c <- pCell
PutGate . gateUpperLeft c <$> pDirection
pCell :: Parse Cell
pCell = do
y <- pInt
x <- pInt
return (y,x)
pDirection :: Parse Direction
pDirection = cToDirection <$> asToken (oneOf "hv")
where cToDirection = (read :: String -> Direction) . pure . toUpper
pInt :: Parse Int
pInt = (read :: String -> Int) <$> asToken (many1 digit)
asToken :: Parse a -> Parse a
asToken p = spaces >> p
-- exported functions
-- | Given a string representing a turn,
-- Parses it and returns the Turn
--
-- Note: This is not the same string as show turn, it is
-- a more concise, for example: "m y x" to move
-- to (y,x)
parseTurn :: String -> Either String Turn
parseTurn s = func $ parse pTurn "" s
where func (Left errMsgs) = Left $ show errMsgs
func (Right x) = Right x