40 lines
1.1 KiB
Haskell
40 lines
1.1 KiB
Haskell
|
module Parser where
|
||
|
|
||
|
import qualified Data.Char as Char
|
||
|
|
||
|
newtype Parser i o = Parser (i -> Maybe (o, i))
|
||
|
|
||
|
instance Functor (Parser i) where
|
||
|
fmap f (Parser p) = Parser $ \i -> fmap (\(o, i') -> (f o, i')) $ p i
|
||
|
|
||
|
instance Applicative (Parser i) where
|
||
|
pure x = Parser $ \i -> Just (x, i)
|
||
|
|
||
|
Parser ff <*> Parser fv = Parser $ \i -> case ff i of
|
||
|
Just (f, i') -> case fv i' of
|
||
|
Just (v, i'') -> Just (f v, i'')
|
||
|
Nothing -> Nothing
|
||
|
Nothing -> Nothing
|
||
|
|
||
|
charParser :: Char -> Parser String Char
|
||
|
charParser c = Parser $ \i -> case i of
|
||
|
(x : xs) | x == c -> Just (c, xs)
|
||
|
_ -> Nothing
|
||
|
|
||
|
newtype Digit = Digit { getIntOfDigit :: Int } deriving (Show, Eq, Ord)
|
||
|
|
||
|
charToDigit :: Char -> Maybe Digit
|
||
|
charToDigit c =
|
||
|
if Char.isDigit c then Just $ Digit (Char.digitToInt c) else Nothing
|
||
|
|
||
|
digitParser :: Parser String Digit
|
||
|
digitParser = Parser $ \i -> case i of
|
||
|
(c : cs) -> fmap (\d -> (d, cs)) . charToDigit $ c
|
||
|
_ -> Nothing
|
||
|
|
||
|
numberParser :: Parser String Int
|
||
|
numberParser = undefined
|
||
|
|
||
|
runParser :: i -> Parser i o -> Maybe o
|
||
|
runParser i (Parser p) = fmap fst (p i)
|