我编写了以下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]
我不禁觉得有一种更简单的方法可以做到这一点。有人可以开导我吗?
答案 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)
您可以使用以下内容替换c
,d
和e
:
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
仍然不是很漂亮,但它有点短。