{-# OPTIONS --without-K --safe #-}
module Text.Format where
open import Level using (0ℓ)
open import Category.Applicative
open import Data.List.Base as List
open import Data.Product
open import Data.Product.Nary.NonDependent
open import Data.Sum.Base
import Data.Sum.Categorical.Left as Sumₗ
open import Function
open import Function.Nary.NonDependent using (0ℓs; Sets)
open import Strict
open import Data.Char.Base
open import Data.Integer.Base
open import Data.Float
open import Data.Nat.Base
open import Data.String.Base
data Chunk : Set where
`ℕ `ℤ `Float `Char `String : Chunk
Raw : String → Chunk
Format : Set
Format = List Chunk
size : Format → ℕ
size = List.sum ∘′ List.map λ { (Raw _) → 0; _ → 1 }
⟦_⟧ : (fmt : Format) → Sets (size fmt) 0ℓs
⟦ [] ⟧ = _
⟦ `ℕ ∷ cs ⟧ = ℕ , ⟦ cs ⟧
⟦ `ℤ ∷ cs ⟧ = ℤ , ⟦ cs ⟧
⟦ `Float ∷ cs ⟧ = Float , ⟦ cs ⟧
⟦ `Char ∷ cs ⟧ = Char , ⟦ cs ⟧
⟦ `String ∷ cs ⟧ = String , ⟦ cs ⟧
⟦ Raw _ ∷ cs ⟧ = ⟦ cs ⟧
data Error : Set where
UnexpectedEndOfString : String → Error
InvalidType : String → Char → String → Error
lexer : String → Error ⊎ List Chunk
lexer input = loop [] [] (toList input) where
open RawApplicative (Sumₗ.applicative Error 0ℓ)
RevWord = List Char
Prefix = RevWord
toRevString : RevWord → String
toRevString = fromList ∘′ reverse
push : RevWord → List Chunk → List Chunk
push [] ks = ks
push cs ks = Raw (toRevString cs) ∷ ks
loop : RevWord → Prefix → List Char → Error ⊎ List Chunk
type : Prefix → List Char → Error ⊎ List Chunk
loop acc bef [] = pure (push acc [])
loop acc bef ('%' ∷ '%' ∷ cs) = loop ('%' ∷ acc) ('%' ∷ '%' ∷ bef) cs
loop acc bef ('%' ∷ cs) = push acc <$> type ('%' ∷ bef) cs
loop acc bef (c ∷ cs) = loop (c ∷ acc) (c ∷ bef) cs
type bef [] = inj₁ (UnexpectedEndOfString input)
type bef (c ∷ cs) = _∷_ <$> chunk c ⊛ loop [] (c ∷ bef) cs where
chunk : Char → Error ⊎ Chunk
chunk 'd' = pure `ℤ
chunk 'i' = pure `ℤ
chunk 'u' = pure `ℕ
chunk 'f' = pure `Float
chunk 'c' = pure `Char
chunk 's' = pure `String
chunk _ = force′ (toRevString bef) $′ λ prefix →
force′ (fromList cs) $′ λ suffix →
inj₁ (InvalidType prefix c suffix)