Created
June 26, 2014 12:08
-
-
Save lnicola/37f2b5d821510a4c13de to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| module Main where | |
| import Control.Monad | |
| newtype Parser a = Parser (String -> [(a, String)]) | |
| parse (Parser p) = p | |
| instance Monad Parser where | |
| return r = Parser (\s -> [(r, s)]) | |
| p >>= q = Parser (\s -> concat [parse (q r) s' | (r, s') <- parse p s]) | |
| instance MonadPlus Parser where | |
| mzero = Parser (const []) | |
| mplus p q = Parser (\s -> parse p s ++ parse q s) | |
| p >>> q = Parser (\s -> case parse (p `mplus` q) s of | |
| [] -> mzero | |
| (x : _) -> [x]) | |
| char = Parser (\s -> case s of | |
| [] -> mzero | |
| (c : cs) -> [(c, cs)]) | |
| charp p = do | |
| c <- char | |
| if p c | |
| then return c | |
| else mzero | |
| rep p = (do | |
| c <- p | |
| cs <- rep p >>> return [] | |
| return (c : cs)) >>> mzero | |
| alt p q = (do | |
| a <- p | |
| as <- rep (q >> p) >>> return [] | |
| return (a : as)) >>> mzero | |
| eqp c c' = c == c' | |
| letterp c = c >= 'a' && c <= 'z' | |
| digitp d = d >= '0' && d <= '9' | |
| whitespacep c = c == ' ' || c == '\t' | |
| eq = charp . eqp | |
| letter = charp letterp | |
| digit = charp digitp | |
| whitespace = charp whitespacep | |
| word = rep letter | |
| number :: (Read a, Num a) => Parser a | |
| --number :: Parser Integer | |
| number = liftM read $ rep digit | |
| --data Op a = Add [Op a] | Sub [Op a] | Mul [Op a] | Div [Op a] | Val a | |
| -- deriving Show | |
| op = do | |
| c <- char | |
| case c of | |
| '+' -> return $ foldl1 (+) | |
| '-' -> return $ foldl1 (-) | |
| '*' -> return $ foldl1 (*) | |
| '/' -> return $ foldl1 (/) | |
| otherwise -> mzero | |
| expr = (do | |
| eq '(' | |
| op <- op | |
| rep whitespace | |
| par <- alt expr (rep whitespace) | |
| eq ')' | |
| return $ op par) >>> number |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment