Created
June 5, 2017 16:54
-
-
Save mizunashi-mana/d9d3b4134a27b643c83dfc8613748de7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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