Skip to content

Instantly share code, notes, and snippets.

@mjhoy
Created September 29, 2013 11:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mjhoy/6751909 to your computer and use it in GitHub Desktop.
Save mjhoy/6751909 to your computer and use it in GitHub Desktop.
parsing ipv4, not allowing leading 0s
import Text.ParserCombinators.Parsec
import Control.Monad (liftM2)
-- helper function
manyNtoM :: Int -> Int -> GenParser a b c -> GenParser a b [c]
manyNtoM n m p
| n < 0 = return []
| n > m = return []
| n == m = count n p
| n == 0 = foldr (<|>) (return []) (map (\x -> try $ count x p) (reverse [1..m]))
| otherwise = liftM2 (++) (count n p) (manyNtoM 0 (m-n) p)
part = do
r <- choice [ zero, nonzero ]
return r
where
zero = string "0"
nonzero = do
a <- oneOf ['1'..'9'] <?> "non-zero digit with non-zero part"
rest <- manyNtoM 0 2 digit
if (read (a:rest) :: Int) > 255
then fail "IP address parts must be 0 <= x <= 255"
else return (a:rest)
ipv4 = do
p1 <- part
char '.'
p2 <- part
char '.'
p3 <- part
char '.'
p4 <- part
notFollowedBy digit
return [p1,p2,p3,p4]
-- ghci> parse ipv4 "" "1.0.0.1"
-- Right ["1","0","0","1"]
-- ghci> parse ipv4 "" "192.168.01.0"
-- Left (line 1, column 10):
-- unexpected "1"
-- expecting "."
-- ghci> parse ipv4 "" "0.368.0.1"
-- Left (line 1, column 6):
-- IP address parts must be 0 <= x <= 255
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment