Parsecで簡単な電卓を作ってみた
LanguageDef と TokenParser と ExpressionParser を使ってみたかったので。。。
空白の扱いについて、ごちゃごちゃ書く必要がなくて楽でいいですね。
module Main (main) where import Text.ParserCombinators.Parsec as Parsec import qualified Text.ParserCombinators.Parsec.Token as Token import qualified Text.ParserCombinators.Parsec.Language as Lang import qualified Text.ParserCombinators.Parsec.Expr as Expr languageDef :: Lang.LanguageDef () languageDef = Lang.emptyDef { Lang.opLetter = oneOf "+-*/" } lexer :: Token.TokenParser () lexer = Token.makeTokenParser languageDef term :: Parser Integer term = parens expr <|> natural where parens = Token.parens lexer natural = Token.natural lexer expr :: Parser Integer expr = Expr.buildExpressionParser table term where table = [ [op "*" (*), op "/" div], [op "+" (+), op "-" (-)] ] op sym fn = Expr.Infix (Token.reservedOp lexer sym >> return fn) Expr.AssocLeft program :: Parser Integer program = Token.whiteSpace lexer >> expr >>= (\x -> eof >> return x) main :: IO () main = rep >> main where rep = getLine >>= print . eval eval = either (error . show) id . parse program "input"