commit 06dc23fb745d06ba346bdb643fc43358a9d9a3b3
parent 4affd9f8a6c7c6e1b4a10c092c04c937d6ef2f38
Author: Robert Russell <robert@rr3.xyz>
Date: Sun, 14 Dec 2025 11:31:05 -0800
Make exports explicit, and add/update char/rune predicates
Diffstat:
| M | Sparsec.hs | | | 189 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- |
1 file changed, 159 insertions(+), 30 deletions(-)
diff --git a/Sparsec.hs b/Sparsec.hs
@@ -1,4 +1,94 @@
-module Sparsec where
+module Sparsec (
+ -- Char
+ charIsUpperLatin,
+ charIsLowerLatin,
+ charIsLatin,
+ charIsUpperGreek,
+ charIsLowerGreek,
+ charIsGreek,
+ charIsSafeUpperGreek,
+ charIsSafeLowerGreek,
+ charIsSafeGreek,
+ charIsNum2,
+ charIsNum4,
+ charIsNum8,
+ charIsNum10,
+ charIsNum16,
+ -- Rune
+ Rune (..),
+ runeElim,
+ runeIsUpperLatin,
+ runeIsLowerLatin,
+ runeIsLatin,
+ runeIsUpperGreek,
+ runeIsLowerGreek,
+ runeIsGreek,
+ runeIsSafeUpperGreek,
+ runeIsSafeLowerGreek,
+ runeIsSafeGreek,
+ runeIsNum2,
+ runeIsNum4,
+ runeIsNum8,
+ runeIsNum10,
+ runeIsNum16,
+ -- Loc
+ Loc (..),
+ locZero,
+ -- Span
+ Span (..),
+ -- Result
+ Result (..),
+ -- Parse monad
+ ParseT (..),
+ runParseT,
+ mapParseT,
+ Parse,
+ runParse,
+ mapParse,
+ -- Core combinators
+ read,
+ write,
+ getLoc,
+ putLoc,
+ save,
+ load,
+ fail,
+ notp,
+ err,
+ catch,
+ -- Derived combinators
+ eof,
+ lookahead,
+ spanOf,
+ bytesOf,
+ cut,
+ try,
+ iter,
+ chainl,
+ chainr,
+ branch,
+ choice,
+ match,
+ someSepBy,
+ manySepBy,
+ -- TODO: Byte combinators
+ -- Utf8 combinators
+ Utf8Error (..),
+ nextRune,
+ nextChar,
+ runeIfM,
+ runeIf,
+ charIfM,
+ charIf,
+ runeWhileM,
+ runeWhile,
+ charWhileM,
+ charWhile,
+ rune,
+ char,
+ string,
+ natural,
+) where
import Control.Applicative
import Control.Monad hiding (fail)
@@ -16,7 +106,33 @@ import Text.Printf
import Prelude hiding (fail, read)
--------------------------------------------------------------------------------
+-- Char
+
+charIsUpperLatin, charIsLowerLatin, charIsLatin :: Char -> Bool
+charIsUpperLatin c = 'A' <= c && c <= 'Z'
+charIsLowerLatin c = 'a' <= c && c <= 'z'
+charIsLatin c = charIsUpperLatin c || charIsLowerLatin c
+
+charIsUpperGreek, charIsLowerGreek, charIsGreek :: Char -> Bool
+charIsUpperGreek c = 'Α' <= c && c <= 'Ω'
+charIsLowerGreek c = 'α' <= c && c <= 'ω'
+charIsGreek c = charIsUpperGreek c || charIsLowerGreek c
+
+charIsSafeUpperGreek, charIsSafeLowerGreek, charIsSafeGreek :: Char -> Bool
+charIsSafeUpperGreek c = c == 'Γ' || c == 'Δ' || c == 'Θ' || c == 'Λ' || c == 'Ξ' || c == 'Π' || c == 'Σ' || c == 'Φ' || c == 'Ψ' || c == 'Ω'
+charIsSafeLowerGreek c = charIsLowerGreek c && c /= 'ο'
+charIsSafeGreek c = charIsSafeUpperGreek c || charIsSafeLowerGreek c
+
+charIsNum2, charIsNum4, charIsNum8, charIsNum10, charIsNum16 :: Char -> Bool
+charIsNum2 c = '0' <= c && c <= '1'
+charIsNum4 c = '0' <= c && c <= '3'
+charIsNum8 c = '0' <= c && c <= '7'
+charIsNum10 c = '0' <= c && c <= '9'
+charIsNum16 c = '0' <= c && c <= '9' || 'A' <= c && c <= 'F' || 'a' <= c && c <= 'f'
+
+--------------------------------------------------------------------------------
-- Rune
+-- TODO: Are runes bloat? Should we delete them?
data Rune = RuneEof | RuneChar Char deriving (Eq)
@@ -30,14 +146,27 @@ runeElim eof chr = \case
RuneEof -> eof
RuneChar c -> chr c
-runeIsSpace :: Rune -> Bool
-runeIsSpace = runeElim False isSpace
+runeIsUpperLatin, runeIsLowerLatin, runeIsLatin :: Rune -> Bool
+runeIsUpperLatin = runeElim False charIsUpperLatin
+runeIsLowerLatin = runeElim False charIsLowerLatin
+runeIsLatin = runeElim False charIsLatin
-runeIsLetter :: Rune -> Bool
-runeIsLetter = runeElim False isLetter
+runeIsUpperGreek, runeIsLowerGreek, runeIsGreek :: Rune -> Bool
+runeIsUpperGreek = runeElim False charIsUpperGreek
+runeIsLowerGreek = runeElim False charIsLowerGreek
+runeIsGreek = runeElim False charIsGreek
-runeIsDigit :: Rune -> Bool
-runeIsDigit = runeElim False isDigit
+runeIsSafeUpperGreek, runeIsSafeLowerGreek, runeIsSafeGreek :: Rune -> Bool
+runeIsSafeUpperGreek = runeElim False charIsSafeUpperGreek
+runeIsSafeLowerGreek = runeElim False charIsSafeLowerGreek
+runeIsSafeGreek = runeElim False charIsSafeGreek
+
+runeIsNum2, runeIsNum4, runeIsNum8, runeIsNum10, runeIsNum16 :: Rune -> Bool
+runeIsNum2 = runeElim False charIsNum2
+runeIsNum4 = runeElim False charIsNum4
+runeIsNum8 = runeElim False charIsNum8
+runeIsNum10 = runeElim False charIsNum10
+runeIsNum16 = runeElim False charIsNum16
--------------------------------------------------------------------------------
-- Loc
@@ -122,6 +251,29 @@ runParse (ParseT f) input loc = runIdentity $ f input loc
mapParse :: (Result e a -> Result e' a') -> Parse e a -> Parse e' a'
mapParse f = mapParseT (Identity . f . runIdentity)
+-- handle generalizes the following:
+-- (<|>): provide a continuation for failure
+-- catch: provide a continuation for error
+-- (>>=): provide a continuation for ok
+-- handle let's you specify a continuation for all three cases.
+-- handle :: (Monad m) => ParseT e' m a' -> (e -> ParseT e' m a') -> (a -> ParseT e' m a') -> ParseT e m a -> ParseT e' m a'
+-- handle hf he ho p = ParseT \input loc ->
+-- runParseT p input loc >>= \case
+-- Failure -> runParseT hf input loc
+-- Error e -> runParseT (he e) input loc
+-- Ok a input' loc' -> runParseT (ho a) input' loc'
+-- bind2 :: (Monad m) => (a -> ParseT e m a') -> ParseT e m a -> ParseT e m a'
+-- bind2 h = handle fail err h
+-- catch2 :: (Monad m) => (e -> ParseT e' m a) -> ParseT e m a -> ParseT e' m a
+-- catch2 h = handle fail h pure
+-- alt2 :: (Monad m) => ParseT e m a -> ParseT e m a -> ParseT e m a
+-- alt2 h = handle h err pure
+-- branch2 :: (Monad m) => ParseT e m a' -> (a -> ParseT e m a') -> ParseT e m a -> ParseT e m a'
+-- branch2 hf ho = handle hf err ho
+-- -- TODO: Rename Ok to Success
+-- succeed :: (Monad m) => a -> ParseT e m a
+-- succeed = pure
+
instance (Monad m) => Functor (ParseT e m) where
fmap = liftM
@@ -206,29 +358,6 @@ p `catch` h = ParseT \input loc ->
Error e -> runParseT (h e) input loc
Ok a input' loc' -> pure $ Ok a input' loc'
--- handle generalizes the following:
--- (<|>): provide a continuation for failure
--- catch: provide a continuation for error
--- (>>=): provide a continuation for ok
--- handle let's you specify a continuation for all three cases.
--- handle :: (Monad m) => ParseT e' m a' -> (e -> ParseT e' m a') -> (a -> ParseT e' m a') -> ParseT e m a -> ParseT e' m a'
--- handle hf he ho p = ParseT \input loc ->
--- runParseT p input loc >>= \case
--- Failure -> runParseT hf input loc
--- Error e -> runParseT (he e) input loc
--- Ok a input' loc' -> runParseT (ho a) input' loc'
--- bind2 :: (Monad m) => (a -> ParseT e m a') -> ParseT e m a -> ParseT e m a'
--- bind2 h = handle fail err h
--- catch2 :: (Monad m) => (e -> ParseT e' m a) -> ParseT e m a -> ParseT e' m a
--- catch2 h = handle fail h pure
--- alt2 :: (Monad m) => ParseT e m a -> ParseT e m a -> ParseT e m a
--- alt2 h = handle h err pure
--- branch2 :: (Monad m) => ParseT e m a' -> (a -> ParseT e m a') -> ParseT e m a -> ParseT e m a'
--- branch2 hf ho = handle hf err ho
--- -- TODO: Rename Ok to Success
--- succeed :: (Monad m) => a -> ParseT e m a
--- succeed = pure
-
--------------------------------------------------------------------------------
-- General combinators