parse-0.1.0.0: src/Parse/Internal/Parse.hs
module Parse.Internal.Parse (parseParts, ParseTuple, parseTuple) where
import Data.List (inits, tails)
import Data.List.Split (splitOn)
import Data.Maybe (mapMaybe, catMaybes)
import Parse.Internal.Instances
parseParts :: [String] -> String -> Either String [String]
parseParts (part:parts@(nextPart:_)) str = do
case dropBy part str of
Just str' ->
let candidates = filter (beginEqual nextPart . snd) (splits str')
(parsed, rest) = head candidates
in if null candidates
then Left $ "No candidates for \"" ++ part ++ "\" in \"" ++ str ++ "\"."
else (parsed:) <$> parseParts parts rest
Nothing -> Left $ "Expected \"" ++ part ++ "\", instead got \"" ++ str ++ "\"."
where
beginEqual :: String -> String -> Bool
beginEqual "" target = target == ""
beginEqual str target = take (length str) target == str
dropBy :: String -> String -> Maybe String
dropBy str target =
if take (length str) target == str
then Just (drop (length str) target)
else Nothing
splits :: [a] -> [([a], [a])]
splits x = zip (inits x) (tails x)
parseParts _ _ = Right []
$(parseTupleInstances [2..62])
instance ParseTuple String where
parseTuple format str =
case parseParts (splitOn "{}" format) str of
Right [x] -> Right x
Right result -> Left $ "Parsed " ++ show (length result) ++ " values, expected 1."
Left x -> Left x