Source code on Github
{-# OPTIONS --cubical-compatible --safe #-}
open import Data.Char.Base using (Char)
open import Data.Maybe.Base using (Maybe)
module Text.Format.Generic where
open import Level using (0ℓ)
open import Category.Applicative
open import Data.List.Base as List
open import Data.Maybe as Maybe
open import Data.Nat.Base
open import Data.Product
open import Data.Product.Nary.NonDependent
open import Data.Sum.Base
open import Data.String.Base
import Data.Sum.Categorical.Left as Sumₗ
open import Function
open import Function.Nary.NonDependent using (0ℓs; Sets)
open import Strict
record FormatSpec : Set₁ where
field
ArgChunk : Set
ArgType : ArgChunk → Set
lexArg : Char → Maybe ArgChunk
module _ where
open FormatSpec
unionSpec : FormatSpec → FormatSpec → FormatSpec
unionSpec spec₁ spec₂ .ArgChunk = spec₁ .ArgChunk ⊎ spec₂ .ArgChunk
unionSpec spec₁ spec₂ .ArgType (inj₁ a) = spec₁ .ArgType a
unionSpec spec₁ spec₂ .ArgType (inj₂ a) = spec₂ .ArgType a
unionSpec spec₁ spec₂ .lexArg c =
Maybe.map inj₁ (spec₁ .lexArg c) <∣>
Maybe.map inj₂ (spec₂ .lexArg c)
module Format (spec : FormatSpec) where
open FormatSpec spec
data Chunk : Set where
Arg : ArgChunk → 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
⟦ [] ⟧ = _
⟦ Arg a ∷ cs ⟧ = ArgType a , ⟦ 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 c =
case lexArg c of λ where
(just ch) → pure (Arg ch)
nothing →
force′ (toRevString bef) λ prefix →
force′ (fromList cs) λ suffix →
inj₁ (InvalidType prefix c suffix)