- Parsec, 高速なコンビネータパーサ の写経の続きです。
サンプルはバージョンが古いのでインポートするモジュール名が違います。
Parsec には 2 系バージョンと 3 系バージョンがあり、最新のバージョンは3.1.0。私のPCには 2.1.0.1 がインストールされています。
とりあえずサンプルが動いたので、これから少しずつ動作を追っていきます。
-- parsec-2.1.0.1: Monadic parser combinators module Main where import Text.ParserCombinators.Parsec.Prim (Parser, (<?>), (<|>),parse) import Text.ParserCombinators.Parsec.Combinator (eof) import Text.ParserCombinators.Parsec.Token (TokenParser, makeTokenParser, reservedOpNames) import Text.ParserCombinators.Parsec.Language ( haskellStyle, haskellDef) import Text.ParserCombinators.Parsec.Expr ( Assoc(AssocLeft), Operator(Infix), buildExpressionParser) import qualified Text.ParserCombinators.Parsec.Token as P lexer :: TokenParser () lexer = makeTokenParser (haskellDef { reservedOpNames = ["*","/","+","-"] }) whiteSpace= P.whiteSpace lexer lexeme = P.lexeme lexer symbol = P.symbol lexer natural = P.natural lexer parens = P.parens lexer semi = P.semi lexer identifier= P.identifier lexer reserved = P.reserved lexer reservedOp= P.reservedOp lexer expr :: Parser Integer expr = buildExpressionParser table factor <?> "expression" table = [[op "*" (*) AssocLeft, op "/" div AssocLeft] ,[op "+" (+) AssocLeft, op "-" (-) AssocLeft] ] where op s f assoc = Infix (do{ reservedOp s; return f} <?> "operator") assoc factor = parens expr <|> natural <?> "simple expression" 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 runLex :: Show a => Parser a -> String -> IO () runLex p input = run (do{ whiteSpace ; x <- p ; eof ; return x }) input
*Main> runLex expr "1 + 2" Loading package parsec-2.1.0.1 ... linking ... done. 3 *Main> runLex expr "1 + {- comment -} 2 * 3 --multiply has higher priority" 7 *Main> runLex expr " 0xAA / 0o37 / 2" 2 *Main> runLex expr "0xAA / 0o37 2 " parse error at (line 1, column 13): unexpected "2" expecting operator or end of input