ParsecでPHPのパーサを書こう
ということで書いていきます。Parsec/Haskellで。何故PHPかと言ったら使ってるからです。何故Haskellかといったら好きだからです。
では先ずはIntとDouble。
+-符号を考慮して、Intは8進法と16進法を考慮して。
PHPにNumber型とか多分無いですが、IntとDoubleを合わせたものと定義してます。
import Text.ParserCombinators.Parsec typeInteger :: Parser String typeInteger = do f <- lookAhead anyChar case f of c | (c=='+')||(c=='-') -> -- 符号有り do s <- anyChar skipMany space cs <- typeInteger return (s:cs) | otherwise -> -- 符号無し do -- 10進数 d <- oneOf "123456789" ds <- many digit return (d:ds) <|> do -- 16進数 try (string "0x") cs <- many1 (digit <|> oneOf "abcdefABCDEF") return ("0x"++cs) <|> do -- 8進数 char '0' cs <- many (oneOf "01234567") return ("0"++cs) typeDouble :: Parser String typeDouble = do f <- lookAhead anyChar case f of c | (c=='+')||(c=='-') -> do s <- anyChar skipMany space cs <- typeDouble return (s:cs) | otherwise -> do ds <- many (oneOf "0123456789") char '.' ds' <- many1 (oneOf "0123456789") return (ds++['.']++ds') typeNumber :: Parser String typeNumber = do n <- (try(typeDouble) <|> typeInteger) return n
演算子は本当は全部別個に書くべきなのだろうな。優先度考慮しつつ。
次にString型書こうとしたら分からなくて困った。
2文字ずつくらい先読みすれば出来そうだけど。