Parsecにちょっと触ってみる(5):字句解析

サンプルはバージョンが古いのでインポートするモジュール名が違います。
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