Skip to content

Instantly share code, notes, and snippets.

@mizunashi-mana
Created June 5, 2017 16:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mizunashi-mana/d9d3b4134a27b643c83dfc8613748de7 to your computer and use it in GitHub Desktop.
Save mizunashi-mana/d9d3b4134a27b643c83dfc8613748de7 to your computer and use it in GitHub Desktop.
import Control.Applicative
import qualified Text.Parsec as P
import Text.Parsec.String
data Command = Command
{ addr :: Maybe Addr
, cmdName :: Char
, param :: Maybe String
} deriving (Show, Eq)
data Addr
= AddrSingle AddrVal
| AddrPair AddrVal AddrVal
deriving (Show, Eq)
data AddrVal
= AddrLine Int
| AddrCrr Int
| AddrEOF
deriving (Show, Eq)
addrCrrLine :: AddrVal
addrCrrLine = AddrCrr 0
-- | A Parser for Command
--
-- >>> P.parse parseCmd "command" "w test.txt"
-- Right (Command {addr = Nothing, cmdName = 'w', param = Just "test.txt"})
-- >>> P.parse parseCmd "command" "1,2a"
-- Right (Command {addr = Just (AddrPair (AddrLine 1) (AddrLine 2)), cmdName = 'a', param = Nothing})
-- >>> P.parse parseCmd "command" ",d"
-- Right (Command {addr = Just (AddrPair (AddrLine 1) AddrEOF), cmdName = 'd', param = Nothing})
-- >>> P.parse parseCmd "command" ""
--
-- unexpected end of input
-- expecting ",", ";", digit or letter
parseCmd :: Parser Command
parseCmd = Command
<$> parseAddr
<*> parseCmdName
<*> parseParam
parseAddr :: Parser (Maybe Addr)
parseAddr = optional parseAddr'
where
parseAddr'
= parseHeadToEOF
<|> parseCrrToEOF
<|> parseAddresses
parseHeadToEOF = P.char ','
*> pure (AddrPair (AddrLine 1) AddrEOF)
parseCrrToEOF = P.char ';'
*> pure (AddrPair addrCrrLine AddrEOF)
parseAddresses = do
(x:xs) <- parseIntList
return $ if null xs
then AddrSingle $ AddrLine x
else AddrPair (AddrLine x) (AddrLine $ last xs)
parseCmdName :: Parser Char
parseCmdName = P.letter
parseParam :: Parser (Maybe String)
parseParam = P.spaces
*> (listToMaybeList <$> P.many P.anyChar)
where
listToMaybeList [] = Nothing
listToMaybeList xs = Just xs
parseIntList :: Parser [Int]
parseIntList = parseText
parseText :: Parser [Int]
parseText = parseInt `P.sepBy1` P.char ','
parseInt :: Parser Int
parseInt = do
value <- P.many1 P.digit
return (read value)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment