module Agda.Utils.Suffix where import Data.Char import qualified Data.List as List import Agda.Utils.Impossible ------------------------------------------------------------------------ -- Subscript digits -- | Is the character one of the subscripts @'₀'@-@'₉'@? isSubscriptDigit :: Char -> Bool isSubscriptDigit c = '₀' <= c && c <= '₉' -- | Converts @'0'@-@'9'@ to @'₀'@-@'₉'@ -- -- Precondition: The digit needs to be in range. toSubscriptDigit :: Char -> Char toSubscriptDigit d | isDigit d = toEnum (fromEnum '₀' + (fromEnum d - fromEnum '0')) | otherwise = __IMPOSSIBLE__ -- | Converts @'₀'@-@'₉'@ to @'0'@-@'9'@. -- -- Precondition: The digit needs to be in range. fromSubscriptDigit :: Char -> Char fromSubscriptDigit d | isSubscriptDigit d = toEnum (fromEnum '0' + (fromEnum d - fromEnum '₀')) | otherwise = __IMPOSSIBLE__ ------------------------------------------------------------------------ -- Suffices -- | Classification of identifier variants. data Suffix = Prime Integer -- ^ Identifier ends in @Integer@ many primes. | Index Integer -- ^ Identifier ends in number @Integer@ (ordinary digits). | Subscript Integer -- ^ Identifier ends in number @Integer@ (subscript digits). -- | Increase the suffix by one. nextSuffix :: Suffix -> Suffix nextSuffix (Prime i) = Prime $ i + 1 nextSuffix (Index i) = Index $ i + 1 nextSuffix (Subscript i) = Subscript $ i + 1 -- | Parse suffix. suffixView :: String -> (String, Maybe Suffix) suffixView s | (ps@(_:_), s') <- span (=='\'') rs = (reverse s', Just $ Prime $ List.genericLength ps) | (ns@(_:_), s') <- span isDigit rs = (reverse s', Just $ Index $ read $ reverse ns) | (ns@(_:_), s') <- span isSubscriptDigit rs = (reverse s', Just $ Subscript $ read $ map fromSubscriptDigit $ reverse ns) | otherwise = (s, Nothing) where rs = reverse s -- Note: suffixView could be implemented using spanEnd, but the implementation using reverse -- looks more efficient, since the reversal is only done once. -- -- suffixView :: String -> (String, Maybe Suffix) -- suffixView s -- | (s', ps@(_:_)) <- spanEnd (=='\'') s = (s', Just $ Prime $ length ps) -- | (s', ns@(_:_)) <- spanEnd isDigit s = (s', Just $ Index $ read ns) -- | (s', ns@(_:_)) <- spanEnd isSubscriptDigit s = (s', Just $ Subscript $ read $ map fromSubscriptDigit ns) -- | otherwise = (s, Nothing) -- | Print suffix. renderSuffix :: Suffix -> String renderSuffix (Prime n) = List.genericReplicate n '\'' renderSuffix (Index i) = show i renderSuffix (Subscript i) = map toSubscriptDigit (show i) addSuffix :: String -> Suffix -> String addSuffix str suffix = str ++ renderSuffix suffix