 readMaybe ('0':'x':xs) of
          Just c → pure (Char c)
          Nothing → LNothing <$ tell ["unknown letter ‘" ⊕ xs ⊕ "’"]

ligatures ∷ (Logger m, Parser m, MonadFail m) ⇒ m [(Pos, Int, String)]
ligatures = do
    ["LIGATURE"] ← readLine
    catMaybes <$> many (try ligature)

ligature ∷ (Logger m, Parser m, MonadFail m) ⇒ m (Maybe (Pos, Int, String))
ligature = do
    sc:i:chars ← readLine
    guard (not (null chars))
    runMayb
parseLetter xs
    | last xs ≡ '@' =
        case chr <$> readMaybe ('0':'x':init xs) of
            Just c → pure (CustomDead Nothing (DeadKey [c] (BaseChar c) (∅)))
            Nothing → LNothing <$ tell ["no number in dead key ‘" ⊕ xs ⊕ "’"]
    | otherwise =
        case chr <$> readMaybe ('0':'x':xs) of
          Just c → pure (Char c)
          Nothing → LNothing <$ tell ["unknown letter ‘" ⊕ xs ⊕ "’"]
parseLetter xs
    | last xs ≡ '@' =
        case chr <$> readMaybe ('0':'x':init xs) of
            Just c → pure (CustomDead Nothing (DeadKey [c] (BaseChar c) (∅)))
            Nothing → LNothing <$ tell ["no number in dead key ‘" ⊕ xs ⊕ "’"]
    | otherwise =
        case chr <$> readMaybe ('0':'x':xs) of
          Just c → pure (Char c)
          Nothing → LNothing <$ tell ["unknown letter ‘" ⊕ xs ⊕ "’"]