練習にS式っぽい計算機を作ってみました。
import Text.ParserCombinators.Parsec import Data.List -- sexpは'('と')'に囲まれていて、"*/+-"のどれかの次にスペースがあって、 -- スペースで区切られたexprがある。 sexp :: Parser Double sexp = do char '(' op <- oneOf "*/+-" spaces s <- sepBy (many1 expr) spaces char ')' case op of '*' -> return $ foldl1' (*) $ concat s '/' -> return $ foldl1' (/) $ concat s '+' -> return $ foldl1' (+) $ concat s '-' -> return $ foldl1' (-) $ concat s -- exprは数字かsexp expr :: Parser Double expr = do{n <-try number;return n} <|> do{ n <- sexp; return n } number :: Parser Double number = do spaces ds <- sepBy1 (many1 digit) (char '.') spaces case ds of [int,decimal] -> return (read (int++"."++decimal)) [int] -> return (read int) _ -> return 0 {- > parseTest sexp "(- 100 56)" -- > 44.0 > parseTest sexp "(+ 1 2 3 4 5 6 7 8 9 10)" -- > 55.0 > parseTest sexp "(+ 345 (+ 1 2) (* 34 78 9))" -- > 24216.0 > parseTest sexp "(/ (+ 345 (+ 1 2) (* 34 78 9)) 3)" -- > 8072.0 > parseTest sexp "(+ 345 (+ 1 2 (- 10 3)) (* 34 78 9))" -- > 24223.0 > parseTest sexp "(a 345 5)" -- > parse error at (line 1, column 2): unexpected "a" -}
- noneOf "'( )" ・・・指定Char 以外に一致
> parseTest (do{s<-many1 (noneOf "'( )");return(map toUpper s)}) "abc" -- > "ABC"