module Data.String.Interpolate.Parse where

import           Data.String.Interpolate.Internal.Util

data Node a = Literal String | Expression String | Abstraction a

parseNodes :: String -> [Node ()]
parseNodes :: String -> [Node ()]
parseNodes = String -> String -> [Node ()]
go String
""
  where
    go :: String -> String -> [Node ()]
    go :: String -> String -> [Node ()]
go String
acc String
input = case String
input of
      String
""  -> [Node ()] -> [Node ()]
lit []
      Char
'\\':Char
x:String
xs -> String -> String -> [Node ()]
go (Char
xChar -> String -> String
forall a. a -> [a] -> [a]
:Char
'\\'Char -> String -> String
forall a. a -> [a] -> [a]
:String
acc) String
xs
      Char
'#':Char
'{':String
xs | (String
e, Char
'}':String
ys) <- (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
span (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'}') String
xs -> [Node ()] -> [Node ()]
lit ([Node ()] -> [Node ()]) -> [Node ()] -> [Node ()]
forall a b. (a -> b) -> a -> b
$ String -> Node ()
expression String
e Node () -> [Node ()] -> [Node ()]
forall a. a -> [a] -> [a]
: String -> String -> [Node ()]
go String
"" String
ys
      Char
x:String
xs -> String -> String -> [Node ()]
go (Char
xChar -> String -> String
forall a. a -> [a] -> [a]
:String
acc) String
xs
      where
        expression :: String -> Node ()
expression String
e
          | String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
e = () -> Node ()
forall a. a -> Node a
Abstraction ()
          | Bool
otherwise = String -> Node ()
forall a. String -> Node a
Expression String
e

        lit :: [Node ()] -> [Node ()]
        lit :: [Node ()] -> [Node ()]
lit [Node ()]
nodes
          | String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
acc = [Node ()]
nodes
          | Bool
otherwise = (String -> Node ()
forall a. String -> Node a
Literal (String -> Node ()) -> (String -> String) -> String -> Node ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
unescape (String -> Node ()) -> String -> Node ()
forall a b. (a -> b) -> a -> b
$ String -> String
forall a. [a] -> [a]
reverse String
acc) Node () -> [Node ()] -> [Node ()]
forall a. a -> [a] -> [a]
: [Node ()]
nodes