- しばらくやっていなかったのですっかり忘れました。Parsec, 高速なコンビネータパーサ を参考にして簡単な掛け算。
- パースは何をするものかと言うと、数字文字列から本物の数字、S式の文字列から本物のS式、配列の文字列から本物の配列を作ります。文字列から意味のある値を生成します。
import Text.ParserCombinators.Parsec
multiply :: Parser Integer
multiply = do{ x <- number
; char '*'
; y <- number
; return (x * y)
}
number :: Parser Integer
number = do{ spaces
; ds <- many1 digit
; spaces
; return (read ds)
}
run :: Show a => Parser a -> String -> IO ()
run p input
= case (parse p "" input) of
Left err -> do{ putStr "parse error at "
; print err
}
Right x -> print x
> run multiply "1234 * 10000"
> run multiply "1234g * 10000"
parse error at (line 1, column 5):
unexpected "g"
expecting digit, white space or "*"
> parse multiply "Error" "1234 * 10000"
> parse multiply "Error" "g1234 * 10000"
Left "Error" (line 1, column 1):
unexpected "g"
expecting white space or digit
> parse (do{x<-char '1';return ((read [x])::Integer)}) "Error" "1234"
import Text.ParserCombinators.Parsec
calc :: Parser Integer
calc = do x <- number
op <- operator
y <- number
case op of
'+' -> return (x + y)
'-' -> return (x - y)
'*' -> return (x * y)
'/' -> return (x `div` y)
number :: Parser Integer
number = do spaces
ds <- many1 digit
spaces
return (read ds)
operator :: Parser Char
operator = oneOf "+-*/"
run :: Show a => Parser a -> String -> IO ()
run p input
= case (parse p "" input) of
Left err -> do{ putStr "parse error at "
; print err
}
Right x -> print x
ghci> run calc "12300 / 234"
ghci> run calc "123 + 234"
ghci> run calc "123 - 234"
ghci> run calc "123 * 234"
ghci> run calc "234 / 12"
- sepBy は指定された区切りで文字列を分割し、リストにして返す。
> parseTest (sepBy (many digit) (char ',')) "123,456,789"
import Text.ParserCombinators.Parsec
calc :: Parser Double
calc = do x <- number
op <- operat
y <- number
case op of
'+' -> return (x + y)
'-' -> return (x - y)
'*' -> return (x * y)
'/' -> return (x / y)
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
operat :: Parser Char
operat = oneOf "+-*/"
run :: Show a => Parser a -> String -> IO ()
run p input
= case (parse p "" input) of
Left err -> putStr "parse error at " >> print err
Right x -> print x
> run calc "123.4 + 34.67"
> run calc "123.4 - 34.67"
> run calc "123.4 * 34.67"
> run calc "123.4 / 34.67"
> run calc "123 * 3"