Using Haskell's Text.ParserCombinators.ReadP library for the first time, and I enjoyed it thoroughly! It's nice avoiding a third-party library like MegaParsec.
		
			
				
	
	
		
			40 lines
		
	
	
	
		
			1.1 KiB
		
	
	
	
		
			Haskell
		
	
	
	
	
	
			
		
		
	
	
			40 lines
		
	
	
	
		
			1.1 KiB
		
	
	
	
		
			Haskell
		
	
	
	
	
	
| --------------------------------------------------------------------------------
 | |
| module Transforms where
 | |
| --------------------------------------------------------------------------------
 | |
| import Control.Applicative ((<|>))
 | |
| import Text.ParserCombinators.ReadP
 | |
| --------------------------------------------------------------------------------
 | |
| 
 | |
| data Transform = VerticalFlip
 | |
|                | HorizontalFlip
 | |
|                | Shift Integer
 | |
|                deriving (Eq, Show)
 | |
| 
 | |
| digit :: ReadP Char
 | |
| digit =
 | |
|   satisfy (\c -> c >= '0' && c <= '9')
 | |
| 
 | |
| command :: ReadP Transform
 | |
| command = vertical
 | |
|       <|> horizontal
 | |
|       <|> shift
 | |
|   where
 | |
|     vertical =
 | |
|       char 'V' >> pure VerticalFlip
 | |
| 
 | |
|     horizontal =
 | |
|       char 'H' >> pure HorizontalFlip
 | |
| 
 | |
|     shift = do
 | |
|       _ <- char 'S'
 | |
|       negative <- option Nothing $ fmap Just (satisfy (== '-'))
 | |
|       n <- read <$> many1 digit
 | |
|       case negative of
 | |
|         Nothing -> pure $ Shift n
 | |
|         Just _  -> pure $ Shift (-1 * n)
 | |
| 
 | |
| fromString :: String -> Maybe [Transform]
 | |
| fromString x =
 | |
|   case readP_to_S (manyTill command eof) x of
 | |
|    [(res, "")] -> Just res
 | |
|    _           -> Nothing
 |