{-# Language Safe #-}
{-|
Module      : Intcode.Parse
Description : Intcode source file parser
Copyright   : (c) Eric Mertens, 2019
License     : ISC
Maintainer  : emertens@gmail.com

This module implements a parser for the simple comma, separated format
used in the Advent of Code input files.

-}
module Intcode.Parse (parseInts) where

-- | Parse a list of comma separated integers.
--
-- >>> parseInts "1, - 2, 3,-4"
-- Just [1,-2,3,-4]
--
-- >>> parseInts " "
-- Just []
--
-- >>> parseInts "1,2,3,x"
-- Nothing
parseInts ::
  String      {- ^ parser input    -} ->
  Maybe [Int] {- ^ parsed integers -}
parseInts :: String -> Maybe [Int]
parseInts String
str
  | [(Int
i,String
str1)] <- ReadS Int
forall a. Read a => ReadS a
reads String
str = [Int] -> String -> Maybe [Int]
parseInts' [Int
i] String
str1
  | [(String
"",String
"")]  <- ReadS String
lex String
str   = [Int] -> Maybe [Int]
forall a. a -> Maybe a
Just []
  | Bool
otherwise               = Maybe [Int]
forall a. Maybe a
Nothing

-- | Helper function for 'parseInts'
parseInts' ::
  [Int]       {- ^ reversed accumulator -} ->
  String      {- ^ parser input         -} ->
  Maybe [Int] {- ^ parsed integers      -}
parseInts' :: [Int] -> String -> Maybe [Int]
parseInts' [Int]
xs String
str =
  case ReadS String
lex String
str of
    [(String
",",String
str1)] | [(Int
x,String
str2)] <- ReadS Int
forall a. Read a => ReadS a
reads String
str1 -> [Int] -> String -> Maybe [Int]
parseInts' (Int
xInt -> [Int] -> [Int]
forall a. a -> [a] -> [a]
:[Int]
xs) String
str2
    [(String
"",String
"")]                               -> [Int] -> Maybe [Int]
forall a. a -> Maybe a
Just ([Int] -> [Int]
forall a. [a] -> [a]
reverse [Int]
xs)
    [(String, String)]
_                                       -> Maybe [Int]
forall a. Maybe a
Nothing