module Exercise04 where {-WETT-} xmlLight :: String -> Bool xmlLight str = helper str [] "" helper :: String -> [String] -> String -> Bool helper "" lastTags nextTag = null lastTags && null nextTag helper (char:str) lastTags nextTag | char == '<' = null nextTag && helper str lastTags (nextTag ++ [char]) | char == '>' = not (null nextTag) && isValidTag newNextTag False && if isClosingTag newNextTag then not (null lastTags) && (getTagId (last lastTags) == getTagId newNextTag) && helper str (init lastTags) "" else helper str (lastTags ++ [newNextTag]) "" | otherwise = if null nextTag then helper str lastTags nextTag else helper str lastTags newNextTag where newNextTag = nextTag ++ [char] isClosingTag xs = xs !! 1 == '/' getTagId xs = [x | x <- xs, x /= '/', x /= ' ', x /= '<', x /= '>'] isValidTag :: String -> Bool -> Bool isValidTag "" _ = True isValidTag (char:str) whiteSpace | char == ' ' = isValidTag str True | char == '>' = True | otherwise = not whiteSpace && isValidTag str whiteSpace {-TTEW-} -- 1st Iteration: -- xmlLight2 :: String -> Bool -- xmlLight2 "" = True -- xmlLight2 str = length potentialTags == lengthActualTags && lengthActualTags == length validTags && isValidTagOrder validTags [] -- where -- parsedToList = parseToList str "" [] -- potentialTags = [xs | xs<- parsedToList, head xs == '<' || last xs == '>'] -- actualTags = [ys | ys <- potentialTags, head ys == '<', last ys == '>'] -- validTags = [zs | zs <- actualTags, isValidTag zs False] -- lengthActualTags = length actualTags -- parseToList :: String -> String -> [String] -> [String] -- parseToList [] accList list = if null accList then list else list ++ [accList] -- parseToList (char:str) accList list -- | char == '<' = if null accList then parseToList str "<" list else parseToList str "<" (list ++ [accList]) -- | char == '>' = parseToList str "" (list ++ [accList ++ ">"]) -- | otherwise = parseToList str (accList ++ [char]) list -- isValidTagOrder :: [String] -> [String] -> Bool -- isValidTagOrder [] accList = null accList -- isValidTagOrder (tag:list) accList -- | isOpeningTag tag = isValidTagOrder list (accList ++ [tag]) -- | otherwise = not (null accList) && (getTagId tag == getTagId (last accList)) && isValidTagOrder list (init accList) -- where -- getTagId str = [char | char <- str, char /= '/', char /= ' ', char /= '<', char /= '>'] -- isOpeningTag str = str !! 1 == '/' -- 2nd Iteration: -- helper :: String -> [String] -> String -> Bool -- helper "" _ _ = True -- helper (char:"") lastTags nextTag -- | char == '<' = False -- | char == '>' = let newTag = nextTag ++ [char] in -- not (null nextTag) && not (null lastTags) && null (init lastTags) && -- isValidTag newTag False && -- isClosingTag newTag && (getTagId (last lastTags) == getTagId newTag) -- | otherwise = null lastTags && null nextTag -- helper (char:str) lastTags nextTag -- | char == '<' = null nextTag && helper str lastTags (nextTag ++ [char]) -- | char == '>' = let newTag = nextTag ++ [char] in -- not (null nextTag) && isValidTag newTag False && -- if isClosingTag newTag then not (null lastTags) && (getTagId (last lastTags) == getTagId newTag) && helper str (init lastTags) "" -- else helper str (lastTags ++ [newTag]) "" -- | otherwise = if null nextTag then helper str lastTags nextTag else helper str lastTags (nextTag ++ [char])