有没有更简单的方法来为8位十进制整数编写这个Haskell Parsec解析器?

时间:2013-11-04 17:45:07

标签: parsing haskell parsec

我编写了以下Parsec代码来解码代表Word8的文本(无符号8位整数):

decOctetP = try e <|> try d <|> try c <|> try b <|> a
    where
        a = fmap (:[]) digit
        b = do
            m <- oneOf "123456789"
            n <- digit
            return [m, n]
        c = do
            char '1'
            m <- count 2 digit
            return ('1':m)
        d = do
            char '2'
            m <- oneOf "01234"
            n <- digit
            return ['2', m, n]
        e = do
            string "25"
            m <- oneOf "012345"
            return ['2', '5', m]

我不禁觉得有一种更简单的方法可以做到这一点。有人可以开导我吗?

3 个答案:

答案 0 :(得分:6)

老实说,最简单的方法就是将其解析为自然数,然后通过返回mzero,如果超出界限0-255则无法解析。

import Control.Monad

import Text.Parsec
import Text.Parsec.String (Parser)
import qualified Text.Parsec.Token as Tok

natural :: Parser Integer
natural = Tok.natural lexer

number :: Parser Integer
number = do
  n <- natural
  if n < 256 then return n
  else mzero

答案 1 :(得分:1)

结束了我认为干净直观的这个版本:

decOctetP = choice [e, d, c, b, a]
    where
        a = fmap (:[]) digit
        b = sequence [oneOf "123456789", digit]
        c = sequence [char '1', digit, digit]
        d = sequence [char '2', oneOf "01234", digit]
        e = sequence [char '2', char '5', oneOf "012345"]

答案 2 :(得分:0)

您可以使用以下内容替换cde

decOctetP = try c <|> try b <|> a
where
    a = fmap (:[]) digit
    b = do
        m <- oneOf "123456789"
        n <- digit
        return [m, n]
    c = do
        m <- (:) <$> oneOf "123456789" <*> count 2 digit
        guard $ combine m <= 255
        return m
    combine = foldl' (\r d -> 10 * r + (ord d - ord '0')) 0

仍然不是很漂亮,但它有点短。