module Hasklet2 where -- -- * Parser type -- -- | Given a string, a parser either fails or returns a parsed value and -- the rest of the string to be parsed. type Parser a = String -> Maybe (a, String) -- -- * Single character parsers -- -- | Match the end of the input string. end :: Parser () end "" = Just ((),"") end _ = Nothing -- | Return the next character if it satisfies the given predicate. nextIf :: (Char -> Bool) -> Parser Char nextIf f (c:s) | f c = Just (c,s) nextIf _ _ = Nothing -- | Parse the given character. char :: Char -> Parser Char char c = nextIf (c ==) -- | Parse one of the given characters. oneOf :: [Char] -> Parser Char oneOf cs = nextIf (flip elem cs) -- | Parse a particular class of character. lower, upper, digit, space :: Parser Char lower = oneOf ['a'..'z'] upper = oneOf ['A'..'Z'] digit = oneOf ['0'..'9'] space = oneOf " \t\n\r" -- | Parse a digit as an integer. digitInt :: Parser Int digitInt s = case digit s of Just (c, s') -> Just (fromEnum c - fromEnum '0', s') Nothing -> Nothing -- -- * Alternative and repeating parsers -- -- | Run the first parser. If it succeeds, return the result. Otherwise run -- the second parser. -- -- >>> (upper <|> digit) "Hi" -- Just ('H',"i") -- -- >>> (upper <|> digit) "42" -- Just ('4',"2") -- -- >>> (upper <|> digit) "w00t" -- Nothing -- (<|>) :: Parser a -> Parser a -> Parser a (<|>) = undefined -- | Parse a sequence of one or more items, returning the results as a list. -- Parses the longest possible sequence (i.e. until the given parser fails). -- -- >>> many1 lower "abcDEF123" -- Just ("abc","DEF123") -- -- >>> many1 lower "ABCdef123" -- Nothing -- -- >>> many1 (lower <|> upper) "ABCdef123" -- Just ("ABCdef","123") -- -- >>> many1 digitInt "123abc" -- Just ([1,2,3],"abc") -- many1 = undefined -- | Parse a sequence of zero or more items, returning the results as a list. -- -- >>> many lower "abcDEF123" -- Just ("abc","DEF123") -- -- >>> many lower "ABCdef123" -- Just ("","ABCdef123") -- -- >>> many (lower <|> upper) "abcDEF123" -- Just ("abcDEF","123") -- -- >>> many digitInt "123abc" -- Just ([1,2,3],"abc") -- -- >>> many digitInt "abc123" -- Just ([],"abc123") -- many = undefined -- | Parse a natural number into a Haskell integer. -- -- >>> nat "123abc" -- Just (123,"abc") -- -- >>> nat "abc" -- Nothing -- nat :: Parser Int nat = undefined -- -- * Parsing structured data -- -- | Parse a pair of natural numbers into a Haskell pair of integers. You can -- assume there are no spaces within the substring encoding the pair, -- although you're welcome to try to generalize it to handle whitespace too, -- e.g. before/after parentheses and the comma. -- -- This may get a little bit hairy, but the ugliness here will motivate some -- key abstractions later. :-) -- -- >>> natPair "(123,45) 678" -- Just ((123,45)," 678") -- -- >>> natPair "(123,45" -- Nothing -- -- >>> natPair "(123,x) 678" -- Nothing -- natPair = undefined -- | A simple tree data structure, isomorphic to arbitrarily nested pairs with -- integers at the leaves. data Tree = Leaf Int | Node Tree Tree deriving (Eq,Show) -- | Parse a tree encoded as arbitrarily nested pairs. This is basically just -- the 'natPair' parser, now with recursion. -- -- >>> natTree "((1,2),3) abc" -- Just (Node (Node (Leaf 1) (Leaf 2)) (Leaf 3)," abc") -- -- >>> natTree "(1,((100,101),10))" -- Just (Node (Leaf 1) (Node (Node (Leaf 100) (Leaf 101)) (Leaf 10)),"") -- natTree :: Parser Tree natTree = undefined