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 :: [String] -> String -> Either String [String] parseParts (String part:parts :: [String] parts@(String nextPart:[String] _)) String str = do case String -> String -> Maybe String dropBy String part String str of Just String str' -> let candidates :: [(String, String)] candidates = ((String, String) -> Bool) -> [(String, String)] -> [(String, String)] forall a. (a -> Bool) -> [a] -> [a] filter (String -> String -> Bool beginEqual String nextPart (String -> Bool) -> ((String, String) -> String) -> (String, String) -> Bool forall b c a. (b -> c) -> (a -> b) -> a -> c . (String, String) -> String forall a b. (a, b) -> b snd) (String -> [(String, String)] forall a. [a] -> [([a], [a])] splits String str') (String parsed, String rest) = [(String, String)] -> (String, String) forall a. [a] -> a head [(String, String)] candidates in if [(String, String)] -> Bool forall (t :: * -> *) a. Foldable t => t a -> Bool null [(String, String)] candidates then String -> Either String [String] forall a b. a -> Either a b Left (String -> Either String [String]) -> String -> Either String [String] forall a b. (a -> b) -> a -> b $ String "No candidates for \"" String -> String -> String forall a. [a] -> [a] -> [a] ++ String part String -> String -> String forall a. [a] -> [a] -> [a] ++ String "\" in \"" String -> String -> String forall a. [a] -> [a] -> [a] ++ String str String -> String -> String forall a. [a] -> [a] -> [a] ++ String "\"." else (String parsedString -> [String] -> [String] forall a. a -> [a] -> [a] :) ([String] -> [String]) -> Either String [String] -> Either String [String] forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> [String] -> String -> Either String [String] parseParts [String] parts String rest Maybe String Nothing -> String -> Either String [String] forall a b. a -> Either a b Left (String -> Either String [String]) -> String -> Either String [String] forall a b. (a -> b) -> a -> b $ String "Expected \"" String -> String -> String forall a. [a] -> [a] -> [a] ++ String part String -> String -> String forall a. [a] -> [a] -> [a] ++ String "\", instead got \"" String -> String -> String forall a. [a] -> [a] -> [a] ++ String str String -> String -> String forall a. [a] -> [a] -> [a] ++ String "\"." where beginEqual :: String -> String -> Bool beginEqual :: String -> String -> Bool beginEqual String "" String target = String target String -> String -> Bool forall a. Eq a => a -> a -> Bool == String "" beginEqual String str String target = Int -> String -> String forall a. Int -> [a] -> [a] take (String -> Int forall (t :: * -> *) a. Foldable t => t a -> Int length String str) String target String -> String -> Bool forall a. Eq a => a -> a -> Bool == String str dropBy :: String -> String -> Maybe String dropBy :: String -> String -> Maybe String dropBy String str String target = if Int -> String -> String forall a. Int -> [a] -> [a] take (String -> Int forall (t :: * -> *) a. Foldable t => t a -> Int length String str) String target String -> String -> Bool forall a. Eq a => a -> a -> Bool == String str then String -> Maybe String forall a. a -> Maybe a Just (Int -> String -> String forall a. Int -> [a] -> [a] drop (String -> Int forall (t :: * -> *) a. Foldable t => t a -> Int length String str) String target) else Maybe String forall a. Maybe a Nothing splits :: [a] -> [([a], [a])] splits :: [a] -> [([a], [a])] splits [a] x = [[a]] -> [[a]] -> [([a], [a])] forall a b. [a] -> [b] -> [(a, b)] zip ([a] -> [[a]] forall a. [a] -> [[a]] inits [a] x) ([a] -> [[a]] forall a. [a] -> [[a]] tails [a] x) parseParts [String] _ String _ = [String] -> Either String [String] forall a b. b -> Either a b Right [] $(parseTupleInstances [2..62]) instance ParseTuple String where parseTuple :: String -> String -> Either String String parseTuple String format String str = case [String] -> String -> Either String [String] parseParts (String -> String -> [String] forall a. Eq a => [a] -> [a] -> [[a]] splitOn String "{}" String format) String str of Right [String x] -> String -> Either String String forall a b. b -> Either a b Right String x Right [String] result -> String -> Either String String forall a b. a -> Either a b Left (String -> Either String String) -> String -> Either String String forall a b. (a -> b) -> a -> b $ String "Parsed " String -> String -> String forall a. [a] -> [a] -> [a] ++ Int -> String forall a. Show a => a -> String show ([String] -> Int forall (t :: * -> *) a. Foldable t => t a -> Int length [String] result) String -> String -> String forall a. [a] -> [a] -> [a] ++ String " values, expected 1." Left String x -> String -> Either String String forall a b. a -> Either a b Left String x