import Data.Char ------------------------------------------------------------------------- -- the expression datatype data Expr = Num Int | Add Expr Expr | Mul Expr Expr deriving ( Show, Eq ) ------------------------------------------------------------------------- -- parsing numbers type Parser a = String -> Maybe (a,String) number :: Parser Int number (c:s) | isDigit c = Just (digits 0 (c:s)) number _ = Nothing digits :: Int -> String -> (Int,String) digits n (c:s) | isDigit c = digits (10*n + digitToInt c) s digits n s = (n,s) num :: Parser Expr num s = case number s of Just (n,s') -> Just (Num n, s') Nothing -> Nothing ------------------------------------------------------------------------- -- expr and term {- * an expression is a '+'-chain of terms * a term is a '*'-chain of factors -} expr, term :: Parser Expr expr = chain term '+' Add term = chain factor '*' Mul {- chain p op f s1 parsers a "chain" of things. The things are parsed by the parser p. The things are separated by the symbol op. The things are combined by the function f. For example, 12+23+1+172 is a chain of numbers, separated by the symbol '+'. -} chain :: Parser a -> Char -> (a -> a -> a) -> Parser a chain p op f s1 = case p s1 of Just (a,s2) -> case s2 of c:s3 | c == op -> case chain p op f s3 of Just (b,s4) -> Just (f a b, s4) Nothing -> Just (a,s2) _ -> Just (a,s2) Nothing -> Nothing ------------------------------------------------------------------------- -- factor factor :: Parser Expr factor ('(':s) = case expr s of Just (a, ')':s1) -> Just (a, s1) _ -> Nothing factor s = num s ------------------------------------------------------------------------- -- reading expressions readExpr :: String -> Maybe Expr readExpr s = case expr s of Just (a,"") -> Just a _ -> Nothing -------------------------------------------------------------------------