module Main
where
-import Text.Parsec
-import Text.Parsec.String ( Parser )
-
-newtype IPv4Octet = IPv4Octet Int
- deriving (Show)
-
-data IPv4SequenceMember =
- IPv4SequenceMemberOctet IPv4Octet
- | IPv4SequenceMemberOctetRange IPv4Octet IPv4Octet
- deriving (Show)
-
-data IPv4Sequence =
- IPv4SequenceSingleMember IPv4SequenceMember
- | IPv4SequenceOptions IPv4SequenceMember IPv4Sequence
- deriving (Show)
-
-data IPv4Field = IPv4FieldOctet IPv4Octet | IPv4FieldSequence IPv4Sequence
- deriving (Show)
-
-data IPv4Pattern =
- IPv4Pattern IPv4Field IPv4Field IPv4Field IPv4Field
- deriving (Show)
-
--- An IPv4 address pattern has four fields separated by ".". Each
--- field is either a decimal number, or a sequence inside "[]" that
--- contains one or more ";"-separated decimal numbers or number..number
--- ranges.
---
--- Thus, any pattern field can be a sequence inside "[]", but a "[]"
--- sequence cannot span multiple address fields, and a pattern field
--- cannot contain both a number and a "[]" sequence at the same time.
---
--- This means that the pattern 1.2.[3.4] is not valid (the sequence
--- [3.4] cannot span two address fields) and the pattern 1.2.3.3[6..9]
--- is also not valid (the last field cannot be both number 3 and
--- sequence [6..9] at the same time).
---
--- The syntax for IPv4 patterns is as follows:
---
--- v4pattern = v4field "." v4field "." v4field "." v4field
--- v4field = v4octet | "[" v4sequence "]"
--- v4octet = any decimal number in the range 0 through 255
--- v4sequence = v4seq_member | v4sequence ";" v4seq_member
--- v4seq_member = v4octet | v4octet ".." v4octet
-
-v4seq_member :: Parser IPv4SequenceMember
-v4seq_member = try both <|> just_one
- where
- both = do
- oct1 <- v4octet
- _ <- string ".."
- oct2 <- v4octet
- return $ IPv4SequenceMemberOctetRange oct1 oct2
-
- just_one = fmap IPv4SequenceMemberOctet v4octet
-
-
-v4sequence :: Parser IPv4Sequence
-v4sequence = try both <|> just_one
- where
- both = do
- sm <- v4seq_member
- _ <- char ';'
- s <- v4sequence
- return $ IPv4SequenceOptions sm s
-
- just_one = fmap IPv4SequenceSingleMember v4seq_member
-
-
-v4field :: Parser IPv4Field
-v4field = just_octet <|> brackets
- where
- just_octet = fmap IPv4FieldOctet v4octet
-
- brackets = do
- _ <- char '['
- s <- v4sequence
- _ <- char ']'
- return $ IPv4FieldSequence s
-
-v4octet :: Parser IPv4Octet
-v4octet = fmap (IPv4Octet . read) $ many1 digit
-
-v4pattern :: Parser IPv4Pattern
-v4pattern = do
- field1 <- v4field
- _ <- char '.'
- field2 <- v4field
- _ <- char '.'
- field3 <- v4field
- _ <- char '.'
- field4 <- v4field
- return $ IPv4Pattern field1 field2 field3 field4
-
-
-sequence_members :: IPv4SequenceMember -> [String]
-sequence_members (IPv4SequenceMemberOctet (IPv4Octet i)) = [show i]
-sequence_members (IPv4SequenceMemberOctetRange (IPv4Octet start) (IPv4Octet end)) =
- [show x | x <- [start..end]]
-
-sequences :: IPv4Sequence -> [String]
-sequences (IPv4SequenceSingleMember sm) = sequence_members sm
-sequences (IPv4SequenceOptions sm s) =
- (sequence_members sm) ++ (sequences s)
-
-
-fields :: IPv4Field -> [String]
-fields (IPv4FieldOctet (IPv4Octet i)) = [show i]
-fields (IPv4FieldSequence s) = sequences s
-
-
-addresses :: IPv4Pattern -> [String]
-addresses (IPv4Pattern field1 field2 field3 field4) = do
- f1 <- fields field1
- f2 <- fields field2
- f3 <- fields field3
- f4 <- fields field4
- return $ f1 ++ "." ++ f2 ++ "." ++ f3 ++ "." ++ f4
-
main :: IO ()
-main = do
- putStrLn "Hello, world!"
+main = putStrLn "Hello, world!"