module Day7.Parser ( parseTerminalLines, TerminalCommand (..), ListingEntry (..), DirName, FileName, Size ) where import Text.ParserCombinators.Parsec type DirName = String type FileName = String type Size = Int data ListingEntry = DirListing DirName | FileListing FileName Size deriving (Show, Eq) data TerminalCommand = In DirName | Out | Root | Listing [ListingEntry] deriving (Show, Eq) parseTerminalLines :: String -> Either ParseError [TerminalCommand] parseTerminalLines = parse terminal "(error)" terminal :: GenParser Char st [TerminalCommand] terminal = many command command :: GenParser Char st TerminalCommand command = do _ <- string "$ " cd <|> ls ls :: GenParser Char st TerminalCommand ls = do _ <- string "ls\n" entries <- many listingEntry return $ Listing entries listingEntry :: GenParser Char st ListingEntry listingEntry = dirListing <|> fileListing dirListing :: GenParser Char st ListingEntry dirListing = do _ <- string "dir " dirName <- many $ noneOf "\n" _ <- char '\n' return $ DirListing dirName fileListing :: GenParser Char st ListingEntry fileListing = do fileSize <- many1 digit _ <- char ' ' fileName <- many $ noneOf "\n" _ <- char '\n' return $ FileListing fileName (read fileSize) cd :: GenParser Char st TerminalCommand cd = do _ <- string "cd " name <- many $ noneOf "\n" _ <- char '\n' return (nameToDir name) nameToDir :: DirName -> TerminalCommand nameToDir "/" = Root nameToDir ".." = Out nameToDir ds = In ds