packages feed

gigaparsec 0.2.3.0 → 0.2.4.0

raw patch · 17 files changed

+863/−350 lines, 17 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Text.Gigaparsec.Errors.Combinator: mapEitherS :: (a -> Either (NonEmpty String) b) -> Parsec a -> Parsec b
+ Text.Gigaparsec.Token.Errors: B16 :: Bits
+ Text.Gigaparsec.Token.Errors: B32 :: Bits
+ Text.Gigaparsec.Token.Errors: B64 :: Bits
+ Text.Gigaparsec.Token.Errors: B8 :: Bits
+ Text.Gigaparsec.Token.Errors: badCharsFail :: Map Char (NonEmpty String) -> VerifiedBadChars
+ Text.Gigaparsec.Token.Errors: badCharsReason :: Map Char String -> VerifiedBadChars
+ Text.Gigaparsec.Token.Errors: basicFilter :: BasicFilterConfigurable config => config a
+ Text.Gigaparsec.Token.Errors: because :: VanillaFilterConfigurable config => (a -> String) -> config a
+ Text.Gigaparsec.Token.Errors: class BasicFilterConfigurable config
+ Text.Gigaparsec.Token.Errors: class ExplainConfigurable config
+ Text.Gigaparsec.Token.Errors: class LabelConfigurable config
+ Text.Gigaparsec.Token.Errors: class LabelWithExplainConfigurable config
+ Text.Gigaparsec.Token.Errors: class NotConfigurable config
+ Text.Gigaparsec.Token.Errors: class SpecializedFilterConfigurable config
+ Text.Gigaparsec.Token.Errors: class Unverified config
+ Text.Gigaparsec.Token.Errors: class VanillaFilterConfigurable config
+ Text.Gigaparsec.Token.Errors: data Bits
+ Text.Gigaparsec.Token.Errors: data ErrorConfig
+ Text.Gigaparsec.Token.Errors: data ExplainConfig
+ Text.Gigaparsec.Token.Errors: data FilterConfig a
+ Text.Gigaparsec.Token.Errors: data LabelConfig
+ Text.Gigaparsec.Token.Errors: data LabelWithExplainConfig
+ Text.Gigaparsec.Token.Errors: data SpecializedFilterConfig a
+ Text.Gigaparsec.Token.Errors: data VanillaFilterConfig a
+ Text.Gigaparsec.Token.Errors: data VerifiedBadChars
+ Text.Gigaparsec.Token.Errors: defaultErrorConfig :: ErrorConfig
+ Text.Gigaparsec.Token.Errors: hidden :: LabelConfigurable config => config
+ Text.Gigaparsec.Token.Errors: instance Text.Gigaparsec.Token.Errors.BasicFilterConfigurable Text.Gigaparsec.Internal.Token.Errors.FilterConfig
+ Text.Gigaparsec.Token.Errors: instance Text.Gigaparsec.Token.Errors.BasicFilterConfigurable Text.Gigaparsec.Internal.Token.Errors.SpecializedFilterConfig
+ Text.Gigaparsec.Token.Errors: instance Text.Gigaparsec.Token.Errors.BasicFilterConfigurable Text.Gigaparsec.Internal.Token.Errors.VanillaFilterConfig
+ Text.Gigaparsec.Token.Errors: instance Text.Gigaparsec.Token.Errors.ExplainConfigurable Text.Gigaparsec.Internal.Token.Errors.ExplainConfig
+ Text.Gigaparsec.Token.Errors: instance Text.Gigaparsec.Token.Errors.ExplainConfigurable Text.Gigaparsec.Internal.Token.Errors.LabelWithExplainConfig
+ Text.Gigaparsec.Token.Errors: instance Text.Gigaparsec.Token.Errors.LabelConfigurable Text.Gigaparsec.Internal.Token.Errors.LabelConfig
+ Text.Gigaparsec.Token.Errors: instance Text.Gigaparsec.Token.Errors.LabelConfigurable Text.Gigaparsec.Internal.Token.Errors.LabelWithExplainConfig
+ Text.Gigaparsec.Token.Errors: instance Text.Gigaparsec.Token.Errors.LabelWithExplainConfigurable Text.Gigaparsec.Internal.Token.Errors.LabelWithExplainConfig
+ Text.Gigaparsec.Token.Errors: instance Text.Gigaparsec.Token.Errors.NotConfigurable Text.Gigaparsec.Internal.Token.Errors.ExplainConfig
+ Text.Gigaparsec.Token.Errors: instance Text.Gigaparsec.Token.Errors.NotConfigurable Text.Gigaparsec.Internal.Token.Errors.LabelConfig
+ Text.Gigaparsec.Token.Errors: instance Text.Gigaparsec.Token.Errors.NotConfigurable Text.Gigaparsec.Internal.Token.Errors.LabelWithExplainConfig
+ Text.Gigaparsec.Token.Errors: instance Text.Gigaparsec.Token.Errors.SpecializedFilterConfigurable Text.Gigaparsec.Internal.Token.Errors.FilterConfig
+ Text.Gigaparsec.Token.Errors: instance Text.Gigaparsec.Token.Errors.SpecializedFilterConfigurable Text.Gigaparsec.Internal.Token.Errors.SpecializedFilterConfig
+ Text.Gigaparsec.Token.Errors: instance Text.Gigaparsec.Token.Errors.Unverified Text.Gigaparsec.Internal.Token.Errors.VerifiedBadChars
+ Text.Gigaparsec.Token.Errors: instance Text.Gigaparsec.Token.Errors.VanillaFilterConfigurable Text.Gigaparsec.Internal.Token.Errors.FilterConfig
+ Text.Gigaparsec.Token.Errors: instance Text.Gigaparsec.Token.Errors.VanillaFilterConfigurable Text.Gigaparsec.Internal.Token.Errors.VanillaFilterConfig
+ Text.Gigaparsec.Token.Errors: label :: LabelConfigurable config => Set String -> config
+ Text.Gigaparsec.Token.Errors: labelAndReason :: LabelWithExplainConfigurable config => Set String -> String -> config
+ Text.Gigaparsec.Token.Errors: notConfigured :: NotConfigurable config => config
+ Text.Gigaparsec.Token.Errors: reason :: ExplainConfigurable config => String -> config
+ Text.Gigaparsec.Token.Errors: specializedFilter :: SpecializedFilterConfigurable config => (a -> NonEmpty String) -> config a
+ Text.Gigaparsec.Token.Errors: unexpected :: VanillaFilterConfigurable config => (a -> String) -> config a
+ Text.Gigaparsec.Token.Errors: unexpectedBecause :: VanillaFilterConfigurable config => (a -> String) -> (a -> String) -> config a
+ Text.Gigaparsec.Token.Errors: unverified :: Unverified config => config
+ Text.Gigaparsec.Token.Lexer: mkLexerWithErrorConfig :: LexicalDesc -> ErrorConfig -> Lexer

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # Revision history for gigaparsec +## 0.2.4.0 -- 2024-02-03+* Added `ErrorConfig` and related types, along with `mkLexerWithErrorConfig`, to now allow+  for custom lexing errors.+ ## 0.2.3.0 -- 2024-01-29 * Added _Verified Errors_ and _Preventative Errors_ in `Text.Gigaparsec.Errors.Patterns`. 
gigaparsec.cabal view
@@ -20,7 +20,7 @@ -- PVP summary:     +-+------- breaking API changes --                  | | +----- non-breaking API additions --                  | | | +--- code changes with no API change-version:            0.2.3.0+version:            0.2.4.0  -- A short (one-line) description of the package. synopsis:@@ -97,6 +97,7 @@                       Text.Gigaparsec.Position,                       Text.Gigaparsec.Registers,                       Text.Gigaparsec.Token.Descriptions,+                      Text.Gigaparsec.Token.Errors,                       Text.Gigaparsec.Token.Lexer,                       Text.Gigaparsec.Token.Patterns, @@ -112,6 +113,8 @@                       Text.Gigaparsec.Internal.Errors.ParseError,                       Text.Gigaparsec.Internal.RT,                       Text.Gigaparsec.Internal.Require,+                      Text.Gigaparsec.Internal.Token.BitBounds,+                      Text.Gigaparsec.Internal.Token.Errors,                       Text.Gigaparsec.Internal.Token.Generic,                       Text.Gigaparsec.Internal.Token.Lexer,                       Text.Gigaparsec.Internal.Token.Names,
src/Text/Gigaparsec/Errors/Combinator.hs view
@@ -45,7 +45,9 @@     amend, partialAmend, entrench, dislodge, dislodgeBy,     amendThenDislodge, amendThenDislodgeBy, partialAmendThenDislodge, partialAmendThenDislodgeBy,     markAsToken,-    filterSWith, mapMaybeSWith, filterOut, guardAgainst, unexpectedWhen, unexpectedWithReasonWhen+    filterSWith, mapMaybeSWith,+    filterOut, guardAgainst, unexpectedWhen, unexpectedWithReasonWhen,+    mapEitherS   ) where  {-@@ -379,6 +381,7 @@ {- @since 0.2.2.0 -}+-- FIXME: 0.3.0.0 change to NonEmptyList guardAgainst :: (a -> Maybe [String]) -> Parsec a -> Parsec a guardAgainst p =   filterSWith (specializedGen { ErrorGen.messages = fromJust . p }) (isNothing . p)@@ -406,3 +409,10 @@ mapMaybeSWith :: ErrorGen a -> (a -> Maybe b) -> Parsec a -> Parsec b mapMaybeSWith errGen f p = amendThenDislodgeBy 1 $ withWidth (entrench p) >>= \(x, w) ->   maybe (ErrorGen.asErr errGen x w) pure (f x)++{-+@since 0.2.4.0+-}+mapEitherS :: (a -> Either (NonEmpty String) b) -> Parsec a -> Parsec b+mapEitherS f p = amendThenDislodgeBy 1 $ withWidth (entrench p) >>= \(x, w) ->+  either (failWide w) pure (f x)
src/Text/Gigaparsec/Errors/ErrorGen.hs view
@@ -9,7 +9,7 @@ import Text.Gigaparsec.Internal.Errors qualified as Internal (Error, CaretWidth(RigidCaret), addReason)  type ErrorGen :: * -> *-data ErrorGen a = SpecializedGen { messages :: a -> [String]+data ErrorGen a = SpecializedGen { messages :: a -> [String] -- FIXME: 0.3.0.0 change to NonEmptyList                                  , adjustWidth :: a -> Word -> Word                                  }                 | VanillaGen { unexpected :: a -> UnexpectedItem
src/Text/Gigaparsec/Internal/Errors/DefuncError.hs view
@@ -11,7 +11,7 @@   ) where  import Data.Word (Word32)-import Data.Bits ((.&.), testBit, clearBit, setBit, complement, bit)+import Data.Bits ((.&.), (.|.), testBit, clearBit, setBit, complement, bit) import Data.Set (Set) import Data.Set qualified as Set (null) @@ -91,16 +91,18 @@       EQ -> case k1 of         IsSpecialised -> case k2 of           IsSpecialised ->-            DefuncError IsSpecialised (flags1 .&. flags2) pOff1 uOff1 (Op (Merged errTy1 errTy2))+            DefuncError IsSpecialised (combineFlags flags1 flags2) pOff1 uOff1 (Op (Merged errTy1 errTy2))           IsVanilla | isFlexibleCaret err1 ->             DefuncError IsSpecialised flags1 pOff1 uOff1 (Op (AdjustCaret errTy1 errTy2))           _ -> err1         IsVanilla -> case k2 of           IsVanilla ->-            DefuncError IsVanilla (flags1 .&. flags2) pOff1 uOff1 (Op (Merged errTy1 errTy2))+            DefuncError IsVanilla (combineFlags flags1 flags2) pOff1 uOff1 (Op (Merged errTy1 errTy2))           IsSpecialised | isFlexibleCaret err2 ->             DefuncError IsSpecialised flags1 pOff1 uOff1 (Op (AdjustCaret errTy2 errTy1))           _ -> err2+  where combineFlags f1 f2 =+          (f1 .&. f2 .&. complement entrenchedMask) .|. max (f1 .&. entrenchedMask) (f2 .&. entrenchedMask)  withHints :: DefuncHints -> DefuncError -> DefuncError withHints Blank err = err
+ src/Text/Gigaparsec/Internal/Token/BitBounds.hs view
@@ -0,0 +1,123 @@+{-# LANGUAGE Safe #-}+{-# LANGUAGE DataKinds, ConstraintKinds, MultiParamTypeClasses, AllowAmbiguousTypes, FlexibleInstances, UndecidableInstances, TypeFamilies, TypeOperators, CPP #-}+{-# OPTIONS_GHC -Wno-incomplete-record-updates #-}+{-# OPTIONS_HADDOCK hide #-}+module Text.Gigaparsec.Internal.Token.BitBounds (+    module Text.Gigaparsec.Internal.Token.BitBounds+  ) where++import Data.Kind (Constraint)+import Data.Int (Int8, Int16, Int32, Int64)+import Data.Word (Word8, Word16, Word32, Word64)+import Numeric.Natural (Natural)++#if __GLASGOW_HASKELL__ >= 904++import GHC.TypeLits (type (<=?), Nat)+import GHC.TypeError (TypeError, ErrorMessage(Text, (:<>:), ShowType), Assert)++#else++import GHC.TypeLits (type (<=?), Nat, TypeError, ErrorMessage(Text, (:<>:), ShowType))++type Assert :: Bool -> Constraint -> Constraint+type family Assert b c where+  Assert 'True  _ = ()+  Assert 'False c = c++#endif++type Bits :: *+data Bits = B8 | B16 | B32 | B64++type BitWidth :: * -> Bits+type family BitWidth t where+  BitWidth Integer = 'B64+  BitWidth Int     = 'B64+  BitWidth Word    = 'B64+  BitWidth Word64  = 'B64+  BitWidth Natural = 'B64+  BitWidth Int32   = 'B32+  BitWidth Word32  = 'B32+  BitWidth Int16   = 'B16+  BitWidth Word16  = 'B16+  BitWidth Int8    = 'B8+  BitWidth Word8   = 'B8+  BitWidth t       = TypeError ('Text "The type '" ' :<>: 'ShowType t+                          ':<>: 'Text "' is not a numeric type supported by Gigaparsec")++type SignednessK :: *+data SignednessK = Signed | Unsigned++type Signedness :: * -> SignednessK -> Constraint+type family Signedness t s where+  Signedness Integer _         = () -- integers are allowed to serve as both unsigned and signed+  Signedness Int     'Signed   = ()+  Signedness Word    'Unsigned = ()+  Signedness Word64  'Unsigned = ()+  Signedness Natural 'Unsigned = ()+  Signedness Int32   'Signed   = ()+  Signedness Word32  'Unsigned = ()+  Signedness Int16   'Signed   = ()+  Signedness Word16  'Unsigned = ()+  Signedness Int8    'Signed   = ()+  Signedness Word8   'Unsigned = ()+  Signedness t       'Signed   = TypeError ('Text "The type '" ':<>: 'ShowType t+                                      ':<>: 'Text "' does not hold signed numbers")+  Signedness t       'Unsigned = TypeError ('Text "The type '" ' :<>: 'ShowType t+                                      ':<>: 'Text "' does not hold unsigned numbers")++type ShowBits :: Bits -> ErrorMessage+type ShowBits b = 'ShowType (BitsNat b)++-- This is intentionally not a type alias. On GHC versions < 9.4.1 it appears that TypeErrors are+-- reported slightly more eagerly and we get an error on this definition because+-- > BitsNat b <=? BitsNat (BitWidth t)+-- cannot be solved+type HasWidthFor :: Bits -> * -> Constraint+type family HasWidthFor bits t where+  HasWidthFor bits t = Assert (BitsNat bits <=? BitsNat (BitWidth t))+                              (TypeError ('Text "The type '"+                                    ':<>: 'ShowType t  ' :<>: 'Text "' cannot store a "+                                    ':<>: ShowBits bits ' :<>: 'Text " bit number (only supports up to "+                                    ':<>: ShowBits (BitWidth t) ' :<>: 'Text " bits)."))++type BitBounds :: Bits -> Constraint+class BitBounds b where+  upperSigned :: Integer+  lowerSigned :: Integer+  upperUnsigned :: Integer+  bits :: Bits+  type BitsNat b :: Nat+instance BitBounds 'B8 where+  upperSigned = fromIntegral (maxBound @Int8)+  lowerSigned = fromIntegral (minBound @Int8)+  upperUnsigned = fromIntegral (maxBound @Word8)+  bits = B8+  type BitsNat 'B8 = 8+instance BitBounds 'B16 where+  upperSigned = fromIntegral (maxBound @Int16)+  lowerSigned = fromIntegral (minBound @Int16)+  upperUnsigned = fromIntegral (maxBound @Word16)+  bits = B16+  type BitsNat 'B16 = 16+instance BitBounds 'B32 where+  upperSigned = fromIntegral (maxBound @Int32)+  lowerSigned = fromIntegral (minBound @Int32)+  upperUnsigned = fromIntegral (maxBound @Word32)+  bits = B32+  type BitsNat 'B32 = 32+instance BitBounds 'B64 where+  upperSigned = fromIntegral (maxBound @Int64)+  lowerSigned = fromIntegral (minBound @Int64)+  upperUnsigned = fromIntegral (maxBound @Word64)+  bits = B64+  type BitsNat 'B64 = 64++type CanHoldSigned :: Bits -> * -> Constraint+class (BitBounds bits, Num t) => CanHoldSigned bits t where+instance (BitBounds bits, Num t, Signedness t 'Signed, HasWidthFor bits t) => CanHoldSigned bits t++type CanHoldUnsigned :: Bits -> * -> Constraint+class (BitBounds bits, Num t) => CanHoldUnsigned bits t where+instance (BitBounds bits, Num t, Signedness t 'Unsigned, HasWidthFor bits t) => CanHoldUnsigned bits t
+ src/Text/Gigaparsec/Internal/Token/Errors.hs view
@@ -0,0 +1,137 @@+{-# LANGUAGE Safe #-}+{-# LANGUAGE BlockArguments #-}+{-# OPTIONS_HADDOCK hide #-}+module Text.Gigaparsec.Internal.Token.Errors (module Text.Gigaparsec.Internal.Token.Errors) where++import Text.Gigaparsec (Parsec, empty)+import Text.Gigaparsec qualified as Errors (filterS, mapMaybeS)+import Text.Gigaparsec.Char (satisfy)+import Text.Gigaparsec.Errors.Combinator qualified as Errors (+    label, explain, hide,+    filterOut, guardAgainst, mapEitherS, unexpectedWhen, unexpectedWithReasonWhen+  )+import Text.Gigaparsec.Errors.Patterns (verifiedFail, verifiedExplain)++import Data.Set (Set)+import Data.Map (Map)++import Data.Map qualified as Map (member, (!))+import Data.Kind (Constraint)+import Data.Maybe (isJust, fromJust)+import Data.List.NonEmpty (NonEmpty)+import Data.List.NonEmpty qualified as NonEmpty (toList)++type LabelWithExplainConfig :: *+data LabelWithExplainConfig = LENotConfigured+                            | LELabel !(Set String)+                            | LEReason !String+                            | LEHidden+                            | LELabelAndReason !(Set String) !String++type LabelConfig :: *+data LabelConfig = LNotConfigured+                 | LLabel !(Set String)+                 | LHidden++type ExplainConfig :: *+data ExplainConfig = ENotConfigured+                   | EReason !String++type Annotate :: * -> Constraint+class Annotate config where+  annotate :: config -> Parsec a -> Parsec a++instance Annotate LabelConfig where+  annotate LNotConfigured = id+  annotate (LLabel ls) = Errors.label ls+  annotate LHidden = Errors.hide++instance Annotate ExplainConfig where+  annotate ENotConfigured = id+  annotate (EReason r) = Errors.explain r++instance Annotate LabelWithExplainConfig where+  annotate LENotConfigured = id+  annotate (LELabel ls) = Errors.label ls+  annotate LEHidden = Errors.hide+  annotate (LEReason r) = Errors.explain r+  annotate (LELabelAndReason ls r) = Errors.label ls . Errors.explain r++type FilterConfig :: * -> *+data FilterConfig a = VSBasicFilter+                    | VSSpecializedFilter (a -> NonEmpty String)+                    | VSUnexpected (a -> String)+                    | VSBecause (a -> String)+                    | VSUnexpectedBecause (a -> String) (a -> String)++type VanillaFilterConfig :: * -> *+data VanillaFilterConfig a = VBasicFilter+                           | VUnexpected (a -> String)+                           | VBecause (a -> String)+                           | VUnexpectedBecause (a -> String) (a -> String)++type SpecializedFilterConfig :: * -> *+data SpecializedFilterConfig a = SBasicFilter+                               | SSpecializedFilter (a -> NonEmpty String)++type Filter :: (* -> *) -> Constraint+class Filter config where+  filterS :: config a -> (a -> Bool) -> Parsec a -> Parsec a+  filterS = filterS' id+  mapMaybeS :: config a -> (a -> Maybe b) -> Parsec a -> Parsec b+  mapMaybeS = mapMaybeS' id++  filterS' :: (a -> x) -> config x -> (a -> Bool) -> Parsec a -> Parsec a+  mapMaybeS' :: (a -> x) -> config x -> (a -> Maybe b) -> Parsec a -> Parsec b++instance Filter FilterConfig where+  filterS' _ VSBasicFilter g = Errors.filterS g+  filterS' f (VSSpecializedFilter msgs) g = Errors.guardAgainst (errWhen f (NonEmpty.toList . msgs) g)+  filterS' f (VSBecause reason) g = Errors.filterOut (errWhen f reason g)+  filterS' f (VSUnexpected unex) g = Errors.unexpectedWhen (errWhen f unex g)+  filterS' f (VSUnexpectedBecause unex reason) g =+    Errors.unexpectedWithReasonWhen (errWhen f (\x -> (unex x, reason x)) g)++  mapMaybeS' _ VSBasicFilter g = Errors.mapMaybeS g+  mapMaybeS' f (VSSpecializedFilter msgs) g = Errors.mapEitherS (errMap f msgs g)+  mapMaybeS' f config g = mapMaybeSDefault filterS' f config g++instance Filter VanillaFilterConfig where+  filterS' _ VBasicFilter g = Errors.filterS g+  filterS' f (VBecause reason) g = Errors.filterOut (errWhen f reason g)+  filterS' f (VUnexpected unex) g = Errors.unexpectedWhen (errWhen f unex g)+  filterS' f (VUnexpectedBecause unex reason) g =+    Errors.unexpectedWithReasonWhen (errWhen f (\x -> (unex x, reason x)) g)++  mapMaybeS' _ VBasicFilter g = Errors.mapMaybeS g+  mapMaybeS' f config g = mapMaybeSDefault filterS' f config g++instance Filter SpecializedFilterConfig where+  filterS' _ SBasicFilter g = Errors.filterS g+  filterS' f (SSpecializedFilter msgs) g = Errors.guardAgainst (errWhen f (NonEmpty.toList . msgs) g)++  mapMaybeS' _ SBasicFilter g = Errors.mapMaybeS g+  mapMaybeS' f (SSpecializedFilter msgs) g = Errors.mapEitherS (errMap f msgs g)++errWhen :: (a -> x) -> (x -> e) -> (a -> Bool) -> (a -> Maybe e)+errWhen f g p x+  | p x = Just (g (f x))+  | otherwise = Nothing++errMap :: (a -> x) -> (x -> e) -> (a -> Maybe b) -> (a -> Either e b)+errMap f g p x = maybe (Left (g (f x))) Right (p x)++mapMaybeSDefault :: ((a -> x) -> config x -> (a -> Bool) -> Parsec a -> Parsec a)+                 -> ((a -> x) -> config x -> (a -> Maybe b) -> Parsec a -> Parsec b)+mapMaybeSDefault filt f config g = fmap (fromJust . g) . filt f config (isJust . g)+++type VerifiedBadChars :: *+data VerifiedBadChars = BadCharsFail !(Map Char (NonEmpty String))+                      | BadCharsReason !(Map Char String)+                      | BadCharsUnverified++checkBadChar :: VerifiedBadChars -> Parsec a+checkBadChar (BadCharsFail cs) = verifiedFail (NonEmpty.toList . (cs Map.!)) (satisfy (`Map.member` cs))+checkBadChar (BadCharsReason cs) = verifiedExplain (cs Map.!) (satisfy (`Map.member` cs))+checkBadChar BadCharsUnverified = empty
src/Text/Gigaparsec/Internal/Token/Generic.hs view
@@ -14,36 +14,37 @@  import Data.Char (isDigit, isHexDigit, isOctDigit, digitToInt) import Data.List (foldl')+import Text.Gigaparsec.Token.Errors (ErrorConfig (labelNumericBreakChar))+import Text.Gigaparsec.Internal.Token.Errors (annotate, LabelConfig)  type GenericNumeric :: *-data GenericNumeric = Generic { zeroAllowedDecimal :: Parsec Integer-                              , zeroAllowedHexadecimal :: Parsec Integer-                              , zeroAllowedOctal :: Parsec Integer-                              , zeroAllowedBinary :: Parsec Integer-                              , zeroNotAllowedDecimal :: Parsec Integer-                              , zeroNotAllowedHexadecimal :: Parsec Integer-                              , zeroNotAllowedOctal :: Parsec Integer-                              , zeroNotAllowedBinary :: Parsec Integer-                              -- FIXME: labels are configurable here-                              , plainDecimal :: NumericDesc -> Parsec Integer-                              , plainHexadecimal :: NumericDesc -> Parsec Integer-                              , plainOctal :: NumericDesc -> Parsec Integer-                              , plainBinary :: NumericDesc -> Parsec Integer+data GenericNumeric = Generic { zeroAllowedDecimal :: LabelConfig -> Parsec Integer+                              , zeroAllowedHexadecimal :: LabelConfig -> Parsec Integer+                              , zeroAllowedOctal :: LabelConfig -> Parsec Integer+                              , zeroAllowedBinary :: LabelConfig -> Parsec Integer+                              , zeroNotAllowedDecimal :: LabelConfig -> Parsec Integer+                              , zeroNotAllowedHexadecimal :: LabelConfig -> Parsec Integer+                              , zeroNotAllowedOctal :: LabelConfig -> Parsec Integer+                              , zeroNotAllowedBinary :: LabelConfig -> Parsec Integer+                              , plainDecimal :: NumericDesc -> LabelConfig -> Parsec Integer+                              , plainHexadecimal :: NumericDesc -> LabelConfig -> Parsec Integer+                              , plainOctal :: NumericDesc -> LabelConfig -> Parsec Integer+                              , plainBinary :: NumericDesc -> LabelConfig -> Parsec Integer                               } -mkGeneric :: GenericNumeric-mkGeneric = Generic {..}-  where ofRadix1 :: Integer -> Parsec Char -> Parsec Integer+mkGeneric :: ErrorConfig -> GenericNumeric+mkGeneric !err = Generic {..}+  where ofRadix1 :: Integer -> Parsec Char -> LabelConfig -> Parsec Integer         ofRadix1 radix dig = ofRadix2 radix dig dig-        ofRadix2 :: Integer -> Parsec Char -> Parsec Char -> Parsec Integer-        ofRadix2 radix startDig dig =-          foldl' (withDigit radix) 0 <$> (startDig <:> many dig) --TODO: improve+        ofRadix2 :: Integer -> Parsec Char -> Parsec Char -> LabelConfig -> Parsec Integer+        ofRadix2 radix startDig dig label =+          foldl' (withDigit radix) 0 <$> (startDig <:> many (annotate label dig)) --TODO: improve -        ofRadixBreak1 :: Integer -> Parsec Char -> Char -> Parsec Integer+        ofRadixBreak1 :: Integer -> Parsec Char -> Char -> LabelConfig -> Parsec Integer         ofRadixBreak1 radix dig = ofRadixBreak2 radix dig dig-        ofRadixBreak2 :: Integer -> Parsec Char -> Parsec Char -> Char -> Parsec Integer-        ofRadixBreak2 radix startDig dig breakChar =-          foldl' (withDigit radix) 0 <$> (startDig <:> many (optional (char breakChar) *> dig)) --TODO: improve+        ofRadixBreak2 :: Integer -> Parsec Char -> Parsec Char -> Char -> LabelConfig -> Parsec Integer+        ofRadixBreak2 radix startDig dig breakChar label =+          foldl' (withDigit radix) 0 <$> (startDig <:> many (optional (annotate (labelNumericBreakChar err) (annotate label (char breakChar))) *> annotate label dig)) --TODO: improve          nonZeroDigit = satisfy (\c -> isDigit c && c /= '0') <?> ["digit"]         nonZeroHexDigit = satisfy (\c -> isHexDigit c && c /= '0') <?> ["hexadecimal digit"]@@ -58,34 +59,34 @@         zeroAllowedOctal = ofRadix1 8 octDigit         zeroAllowedBinary = ofRadix1 2 bit -        zeroNotAllowedDecimal = ofRadix2 10 nonZeroDigit digit <|> secretZero-        zeroNotAllowedHexadecimal = ofRadix2 16 nonZeroHexDigit hexDigit <|> secretZero-        zeroNotAllowedOctal = ofRadix2 8 nonZeroOctDigit octDigit <|> secretZero-        zeroNotAllowedBinary = ofRadix2 2 nonZeroBit bit <|> secretZero+        zeroNotAllowedDecimal label = ofRadix2 10 nonZeroDigit digit label <|> secretZero+        zeroNotAllowedHexadecimal label = ofRadix2 16 nonZeroHexDigit hexDigit label <|> secretZero+        zeroNotAllowedOctal label = ofRadix2 8 nonZeroOctDigit octDigit label <|> secretZero+        zeroNotAllowedBinary label = ofRadix2 2 nonZeroBit bit label <|> secretZero -        plainDecimal NumericDesc{leadingZerosAllowed, literalBreakChar} = case literalBreakChar of-          NoBreakChar | leadingZerosAllowed            -> zeroAllowedDecimal-          NoBreakChar                                  -> zeroNotAllowedDecimal-          BreakCharSupported c _ | leadingZerosAllowed -> ofRadixBreak1 10 digit c-          BreakCharSupported c _                       -> ofRadixBreak2 10 nonZeroDigit digit c <|> secretZero+        plainDecimal NumericDesc{leadingZerosAllowed, literalBreakChar} label = case literalBreakChar of+          NoBreakChar | leadingZerosAllowed            -> zeroAllowedDecimal label+          NoBreakChar                                  -> zeroNotAllowedDecimal label+          BreakCharSupported c _ | leadingZerosAllowed -> ofRadixBreak1 10 digit c label+          BreakCharSupported c _                       -> ofRadixBreak2 10 nonZeroDigit digit c label <|> secretZero -        plainHexadecimal NumericDesc{leadingZerosAllowed, literalBreakChar} = case literalBreakChar of-          NoBreakChar | leadingZerosAllowed            -> zeroAllowedDecimal-          NoBreakChar                                  -> zeroNotAllowedDecimal-          BreakCharSupported c _ | leadingZerosAllowed -> ofRadixBreak1 16 hexDigit c-          BreakCharSupported c _                       -> ofRadixBreak2 16 nonZeroHexDigit hexDigit c <|> secretZero+        plainHexadecimal NumericDesc{leadingZerosAllowed, literalBreakChar} label = case literalBreakChar of+          NoBreakChar | leadingZerosAllowed            -> zeroAllowedDecimal label+          NoBreakChar                                  -> zeroNotAllowedDecimal label+          BreakCharSupported c _ | leadingZerosAllowed -> ofRadixBreak1 16 hexDigit c label+          BreakCharSupported c _                       -> ofRadixBreak2 16 nonZeroHexDigit hexDigit c label <|> secretZero -        plainOctal NumericDesc{leadingZerosAllowed, literalBreakChar} = case literalBreakChar of-          NoBreakChar | leadingZerosAllowed            -> zeroAllowedDecimal-          NoBreakChar                                  -> zeroNotAllowedDecimal-          BreakCharSupported c _ | leadingZerosAllowed -> ofRadixBreak1 8 octDigit c-          BreakCharSupported c _                       -> ofRadixBreak2 8 nonZeroOctDigit octDigit c <|> secretZero+        plainOctal NumericDesc{leadingZerosAllowed, literalBreakChar} label = case literalBreakChar of+          NoBreakChar | leadingZerosAllowed            -> zeroAllowedDecimal label+          NoBreakChar                                  -> zeroNotAllowedDecimal label+          BreakCharSupported c _ | leadingZerosAllowed -> ofRadixBreak1 8 octDigit c label+          BreakCharSupported c _                       -> ofRadixBreak2 8 nonZeroOctDigit octDigit c label <|> secretZero -        plainBinary NumericDesc{leadingZerosAllowed, literalBreakChar} = case literalBreakChar of-          NoBreakChar | leadingZerosAllowed            -> zeroAllowedDecimal-          NoBreakChar                                  -> zeroNotAllowedDecimal-          BreakCharSupported c _ | leadingZerosAllowed -> ofRadixBreak1 2 bit c-          BreakCharSupported c _                       -> ofRadixBreak2 2 nonZeroBit bit c <|> secretZero+        plainBinary NumericDesc{leadingZerosAllowed, literalBreakChar} label = case literalBreakChar of+          NoBreakChar | leadingZerosAllowed            -> zeroAllowedDecimal label+          NoBreakChar                                  -> zeroNotAllowedDecimal label+          BreakCharSupported c _ | leadingZerosAllowed -> ofRadixBreak1 2 bit c label+          BreakCharSupported c _                       -> ofRadixBreak2 2 nonZeroBit bit c label <|> secretZero  withDigit :: Integer -> Integer -> Char -> Integer withDigit radix n d = n * radix + fromIntegral (digitToInt d)
src/Text/Gigaparsec/Internal/Token/Lexer.hs view
@@ -1,9 +1,8 @@ {-# LANGUAGE Trustworthy #-}-{-# LANGUAGE OverloadedLists #-} {-# OPTIONS_GHC -Wno-partial-fields #-} {-# OPTIONS_HADDOCK hide #-} module Text.Gigaparsec.Internal.Token.Lexer (-    Lexer, mkLexer,+    Lexer, mkLexer, mkLexerWithErrorConfig,     Lexeme, lexeme, nonlexeme, fully, space,     apply, sym, symbol, names, -- more go here, no numeric and no text     -- Numeric@@ -19,9 +18,14 @@ import Text.Gigaparsec.Char (satisfy, string, item, endOfLine) import Text.Gigaparsec.Combinator (skipMany, skipManyTill) import Text.Gigaparsec.Registers (put, get, localWith, rollback)-import Text.Gigaparsec.Errors.Combinator (hide, (<?>))+import Text.Gigaparsec.Errors.Combinator (hide)  import Text.Gigaparsec.Token.Descriptions qualified as Desc+import Text.Gigaparsec.Token.Errors (+    ErrorConfig (labelSpaceEndOfLineComment, labelSpaceEndOfMultiComment),+    defaultErrorConfig+  )+import Text.Gigaparsec.Internal.Token.Errors (annotate) import Text.Gigaparsec.Internal.Token.Generic (mkGeneric) import Text.Gigaparsec.Internal.Token.Symbol (Symbol, mkSym, mkSymbol) import Text.Gigaparsec.Internal.Token.Symbol qualified as Symbol (lexeme)@@ -31,8 +35,8 @@     IntegerParsers, mkSigned, mkUnsigned,     --FloatingParsers, mkSignedFloating, mkUnsignedFloating,     --CombinedParsers, mkSignedCombined, mkUnsignedCombined,-    CanHoldSigned, CanHoldUnsigned   )+import Text.Gigaparsec.Internal.Token.BitBounds (CanHoldSigned, CanHoldUnsigned) import Text.Gigaparsec.Internal.Token.Numeric qualified as Numeric (lexemeInteger, {-lexemeFloating, lexemeCombined-}) import Text.Gigaparsec.Internal.Token.Text (     TextParsers,@@ -57,9 +61,12 @@                    }  mkLexer :: Desc.LexicalDesc -> Lexer-mkLexer Desc.LexicalDesc{..} = Lexer {..}+mkLexer !desc = mkLexerWithErrorConfig desc defaultErrorConfig++mkLexerWithErrorConfig :: Desc.LexicalDesc -> ErrorConfig -> Lexer+mkLexerWithErrorConfig Desc.LexicalDesc{..} !errConfig = Lexer {..}   where apply p = p <* whiteSpace space-        gen = mkGeneric+        gen = mkGeneric errConfig         lexeme = Lexeme { apply = apply                         , sym = apply . sym nonlexeme                         , symbol = Symbol.lexeme apply (symbol nonlexeme)@@ -77,32 +84,32 @@                         , rawMultiStringLiteral = Text.lexeme apply (rawMultiStringLiteral nonlexeme)                         , charLiteral = Text.lexeme apply (charLiteral nonlexeme)                         }-        nonlexeme = NonLexeme { sym = mkSym symbolDesc (symbol nonlexeme)-                              , symbol = mkSymbol symbolDesc nameDesc-                              , names = mkNames nameDesc symbolDesc-                              , natural = mkUnsigned numericDesc gen-                              , integer = mkSigned numericDesc (natural nonlexeme)+        nonlexeme = NonLexeme { sym = mkSym symbolDesc (symbol nonlexeme) errConfig+                              , symbol = mkSymbol symbolDesc nameDesc errConfig+                              , names = mkNames nameDesc symbolDesc errConfig+                              , natural = mkUnsigned numericDesc gen errConfig+                              , integer = mkSigned numericDesc (natural nonlexeme) errConfig                               {-, floating = mkSignedFloating numericDesc positiveFloating                               , unsignedCombined = mkUnsignedCombined numericDesc (natural nonlexeme) positiveFloating                               , signedCombined = mkSignedCombined numericDesc (unsignedCombined nonlexeme)-}-                              , stringLiteral = mkStringParsers stringEnds escapeChar graphicCharacter False-                              , rawStringLiteral = mkStringParsers stringEnds rawChar graphicCharacter False-                              , multiStringLiteral = mkStringParsers multiStringEnds escapeChar graphicCharacter True-                              , rawMultiStringLiteral = mkStringParsers multiStringEnds rawChar graphicCharacter True-                              , charLiteral = mkCharacterParsers textDesc escape+                              , stringLiteral = mkStringParsers stringEnds escapeChar graphicCharacter False errConfig+                              , rawStringLiteral = mkStringParsers stringEnds rawChar graphicCharacter False errConfig+                              , multiStringLiteral = mkStringParsers multiStringEnds escapeChar graphicCharacter True errConfig+                              , rawMultiStringLiteral = mkStringParsers multiStringEnds rawChar graphicCharacter True errConfig+                              , charLiteral = mkCharacterParsers textDesc escape errConfig                               }         --positiveFloating = mkUnsignedFloating numericDesc (natural nonlexeme) gen-        !escape = mkEscape (Desc.escapeSequences textDesc) mkGeneric -- this is mkGeneric because of errors+        !escape = mkEscape (Desc.escapeSequences textDesc) gen errConfig         graphicCharacter = Desc.graphicCharacter textDesc         stringEnds = Desc.stringEnds textDesc         multiStringEnds = Desc.multiStringEnds textDesc         rawChar = RawChar-        escapeChar = mkEscapeChar (Desc.escapeSequences textDesc) escape (whiteSpace space)+        escapeChar = mkEscapeChar (Desc.escapeSequences textDesc) escape (whiteSpace space) errConfig         fully' p = whiteSpace space *> p <* eof         fully p           | Desc.whitespaceIsContextDependent spaceDesc = initSpace space *> fully' p           | otherwise                                   = fully' p-        space = mkSpace spaceDesc+        space = mkSpace spaceDesc errConfig  --TODO: better name for this, I guess? type Lexeme :: *@@ -147,20 +154,20 @@                    , initSpace :: Parsec ()                    } -mkSpace :: Desc.SpaceDesc -> Space-mkSpace desc@Desc.SpaceDesc{..} = Space {..}+mkSpace :: Desc.SpaceDesc -> ErrorConfig -> Space+mkSpace desc@Desc.SpaceDesc{..} !errConfig = Space {..}   where -- don't think we can trust doing initialisation here, it'll happen in some random order         {-# NOINLINE wsImpl #-}         !wsImpl = fromIORef (unsafePerformIO (newIORef (error "uninitialised space")))         comment = commentParser desc -- do not make this strict         implOf-          | supportsComments desc = hide . maybe skipComments (skipMany . (<|> comment) . void . satisfy)+          | supportsComments desc = hide . maybe skipComments (skipMany . (<|> comment errConfig) . void . satisfy)           | otherwise             = hide . maybe empty (skipMany . satisfy)         !configuredWhitespace = implOf space         !whiteSpace           | whitespaceIsContextDependent = join (get wsImpl)           | otherwise                    = configuredWhitespace-        !skipComments = skipMany comment+        !skipComments = skipMany (comment errConfig)         alter p           | whitespaceIsContextDependent = rollback wsImpl . localWith wsImpl (implOf p)           | otherwise                    = throw (UnsupportedOperation badAlter)@@ -178,15 +185,15 @@ -- TODO: needs error messages put in (is the hide correct) -- TODO: remove guard, configure properly -}-commentParser :: Desc.SpaceDesc -> Parsec ()-commentParser Desc.SpaceDesc{..} =+commentParser :: Desc.SpaceDesc -> ErrorConfig -> Parsec ()+commentParser Desc.SpaceDesc{..} !errConfig =   require (multiEnabled || singleEnabled) "skipComments" noComments $     require (not (multiEnabled && isPrefixOf multiLineCommentStart lineCommentStart)) "skipComments" noOverlap $       hide (multiLine <|> singleLine)   where     -- can't make these strict until guard is gone     openComment = atomic (string multiLineCommentStart)-    closeComment = atomic (string multiLineCommentEnd) <?> ["end of comment"]+    closeComment = annotate (labelSpaceEndOfMultiComment errConfig) (atomic (string multiLineCommentEnd))     multiLine = guard multiEnabled *> openComment *> wellNested 1     wellNested :: Int -> Parsec ()     wellNested 0 = unit@@ -195,7 +202,7 @@                <|> item *> wellNested n     singleLine = guard singleEnabled               *> atomic (string lineCommentStart)-              *> skipManyTill item (endOfLineComment <?> ["end of comment"])+              *> skipManyTill item (annotate (labelSpaceEndOfLineComment errConfig) endOfLineComment)      endOfLineComment       | lineCommentAllowsEOF = void endOfLine <|> eof
src/Text/Gigaparsec/Internal/Token/Names.hs view
@@ -21,6 +21,10 @@     CharPredicate   ) import Data.Char (toLower)+import Text.Gigaparsec.Token.Errors (+    ErrorConfig (labelNameIdentifier, unexpectedNameIllegalIdentifier, labelNameOperator, unexpectedNameIllegalOperator, filterNameIllFormedIdentifier, filterNameIllFormedOperator)+  )+import Text.Gigaparsec.Internal.Token.Errors (filterS)  -- TODO: primes are gross, better way? type Names :: *@@ -30,21 +34,16 @@                    , userDefinedOperator' :: !(CharPredicate -> Parsec String)                    } -mkNames :: NameDesc -> SymbolDesc -> Names-mkNames NameDesc{..} symbolDesc@SymbolDesc{..} = Names {..}+mkNames :: NameDesc -> SymbolDesc -> ErrorConfig -> Names+mkNames NameDesc{..} symbolDesc@SymbolDesc{..} err = Names {..}   where-    -- TODO: error transformers     !isReserved = isReservedName symbolDesc     !identifier =-      keyOrOp identifierStart identifierLetter isReserved "identifier" ("keyword " ++)-    identifier' start =-      unexpectedWhen (\v -> if startsWith start v then Nothing else Just ("identifier " ++ v))-                     identifier+      keyOrOp identifierStart identifierLetter isReserved (labelNameIdentifier err) (unexpectedNameIllegalIdentifier err)+    identifier' start = filterS (filterNameIllFormedIdentifier err) (startsWith start) identifier     !userDefinedOperator =-      keyOrOp operatorStart operatorLetter (flip Set.member hardOperators) "operator" ("reserved operator " ++)-    userDefinedOperator' start =-      unexpectedWhen (\v -> if startsWith start v then Nothing else Just ("operator " ++ v))-                     userDefinedOperator+      keyOrOp operatorStart operatorLetter (flip Set.member hardOperators) (labelNameOperator err) (unexpectedNameIllegalOperator err)+    userDefinedOperator' start = filterS (filterNameIllFormedOperator err) (startsWith start) userDefinedOperator      keyOrOp :: CharPredicate -> CharPredicate -> (String -> Bool) -> String -> (String -> String) -> Parsec String     keyOrOp start letter illegal name unexpectedIllegal =
src/Text/Gigaparsec/Internal/Token/Numeric.hs view
@@ -1,5 +1,5 @@ {-# LANGUAGE Safe #-}-{-# LANGUAGE DataKinds, ConstraintKinds, MultiParamTypeClasses, AllowAmbiguousTypes, FlexibleInstances, FlexibleContexts, UndecidableInstances, ApplicativeDo, TypeFamilies, TypeOperators, CPP #-}+{-# LANGUAGE DataKinds, ConstraintKinds, AllowAmbiguousTypes, KindSignatures, MonoLocalBinds #-} {-# OPTIONS_GHC -Wno-incomplete-record-updates #-} {-# OPTIONS_HADDOCK hide #-} module Text.Gigaparsec.Internal.Token.Numeric (module Text.Gigaparsec.Internal.Token.Numeric) where@@ -7,8 +7,6 @@ import Text.Gigaparsec (Parsec, unit, void, atomic, (<|>), ($>)) import Text.Gigaparsec.Char (char, oneOf) import Text.Gigaparsec.Combinator (optional, optionalAs)-import Text.Gigaparsec.Errors.Combinator (mapMaybeSWith)-import Text.Gigaparsec.Errors.ErrorGen (specializedGen, messages) import Text.Gigaparsec.Token.Descriptions     ( BreakCharDesc(BreakCharSupported, NoBreakChar),       NumericDesc( NumericDesc, positiveSign, literalBreakChar@@ -17,150 +15,66 @@                  , hexadecimalLeads, octalLeads, binaryLeads                  ),       PlusSignPresence(PlusIllegal, PlusRequired, PlusOptional) )-import Text.Gigaparsec.Internal.Token.Generic (GenericNumeric(plainDecimal, plainHexadecimal, plainOctal, plainBinary))-import Data.Char (intToDigit)+import Text.Gigaparsec.Internal.Token.Generic (+    GenericNumeric(plainDecimal, plainHexadecimal, plainOctal, plainBinary)+  )+import Text.Gigaparsec.Internal.Token.BitBounds (+    CanHoldUnsigned, CanHoldSigned,+    BitBounds(upperSigned, upperUnsigned, lowerSigned),+    Bits(B8, B16, B32, B64), bits+  )+import Text.Gigaparsec.Token.Errors (+    ErrorConfig (filterIntegerOutOfBounds, labelIntegerSignedDecimal, labelIntegerUnsignedDecimal,+                 labelIntegerSignedHexadecimal, labelIntegerUnsignedHexadecimal,+                 labelIntegerSignedOctal, labelIntegerUnsignedOctal, labelIntegerSignedBinary,+                 labelIntegerUnsignedBinary, labelIntegerSignedNumber, labelIntegerUnsignedNumber,+                 labelIntegerDecimalEnd, labelIntegerHexadecimalEnd, labelIntegerOctalEnd,+                 labelIntegerBinaryEnd, labelIntegerNumberEnd)+  ) import Data.Kind (Constraint)-import Data.Int (Int8, Int16, Int32, Int64)-import Data.Word (Word8, Word16, Word32, Word64)-import Numeric.Natural (Natural) import Data.Proxy (Proxy(Proxy)) import Control.Monad (when, unless)-import Numeric (showIntAtBase)--#if __GLASGOW_HASKELL__ >= 904--import GHC.TypeLits (type (<=?), Nat)-import GHC.TypeError (TypeError, ErrorMessage(Text, (:<>:), ShowType), Assert)--#else--import GHC.TypeLits (type (<=?), Nat, TypeError, ErrorMessage(Text, (:<>:), ShowType))--type Assert :: Bool -> Constraint -> Constraint-type family Assert b c where-  Assert 'True  _ = ()-  Assert 'False c = c--#endif--type Bits :: *-data Bits = B8 | B16 | B32 | B64--type BitWidth :: * -> Bits-type family BitWidth t where-  BitWidth Integer = 'B64-  BitWidth Int     = 'B64-  BitWidth Word    = 'B64-  BitWidth Word64  = 'B64-  BitWidth Natural = 'B64-  BitWidth Int32   = 'B32-  BitWidth Word32  = 'B32-  BitWidth Int16   = 'B16-  BitWidth Word16  = 'B16-  BitWidth Int8    = 'B8-  BitWidth Word8   = 'B8-  BitWidth t       = TypeError ('Text "The type '" ' :<>: 'ShowType t-                          ':<>: 'Text "' is not a numeric type supported by Gigaparsec")--type SignednessK :: *-data SignednessK = Signed | Unsigned--type Signedness :: * -> SignednessK -> Constraint-type family Signedness t s where-  Signedness Integer _         = () -- integers are allowed to serve as both unsigned and signed-  Signedness Int     'Signed   = ()-  Signedness Word    'Unsigned = ()-  Signedness Word64  'Unsigned = ()-  Signedness Natural 'Unsigned = ()-  Signedness Int32   'Signed   = ()-  Signedness Word32  'Unsigned = ()-  Signedness Int16   'Signed   = ()-  Signedness Word16  'Unsigned = ()-  Signedness Int8    'Signed   = ()-  Signedness Word8   'Unsigned = ()-  Signedness t       'Signed   = TypeError ('Text "The type '" ':<>: 'ShowType t-                                      ':<>: 'Text "' does not hold signed numbers")-  Signedness t       'Unsigned = TypeError ('Text "The type '" ' :<>: 'ShowType t-                                      ':<>: 'Text "' does not hold unsigned numbers")--type ShowBits :: Bits -> ErrorMessage-type ShowBits b = 'ShowType (BitsNat b)---- This is intentionally not a type alias. On GHC versions < 9.4.1 it appears that TypeErrors are--- reported slightly more eagerly and we get an error on this definition because--- > BitsNat b <=? BitsNat (BitWidth t)--- cannot be solved-type HasWidthFor :: Bits -> * -> Constraint-type family HasWidthFor bits t where-  HasWidthFor bits t = Assert (BitsNat bits <=? BitsNat (BitWidth t))-                              (TypeError ('Text "The type '"-                                    ':<>: 'ShowType t  ' :<>: 'Text "' cannot store a "-                                    ':<>: ShowBits bits ' :<>: 'Text " bit number (only supports up to "-                                    ':<>: ShowBits (BitWidth t) ' :<>: 'Text " bits)."))--type BitBounds :: Bits -> Constraint-class BitBounds b where-  upperSigned :: Integer-  lowerSigned :: Integer-  upperUnsigned :: Integer-  bits :: Int-  type BitsNat b :: Nat-instance BitBounds 'B8 where-  upperSigned = fromIntegral (maxBound @Int8)-  lowerSigned = fromIntegral (minBound @Int8)-  upperUnsigned = fromIntegral (maxBound @Word8)-  bits = 8-  type BitsNat 'B8 = 8-instance BitBounds 'B16 where-  upperSigned = fromIntegral (maxBound @Int16)-  lowerSigned = fromIntegral (minBound @Int16)-  upperUnsigned = fromIntegral (maxBound @Word16)-  bits = 16-  type BitsNat 'B16 = 16-instance BitBounds 'B32 where-  upperSigned = fromIntegral (maxBound @Int32)-  lowerSigned = fromIntegral (minBound @Int32)-  upperUnsigned = fromIntegral (maxBound @Word32)-  bits = 32-  type BitsNat 'B32 = 32-instance BitBounds 'B64 where-  upperSigned = fromIntegral (maxBound @Int64)-  lowerSigned = fromIntegral (minBound @Int64)-  upperUnsigned = fromIntegral (maxBound @Word64)-  bits = 64-  type BitsNat 'B64 = 64--type CanHoldSigned :: Bits -> * -> Constraint-class (BitBounds bits, Num t) => CanHoldSigned bits t where-instance (BitBounds bits, Num t, Signedness t 'Signed, HasWidthFor bits t) => CanHoldSigned bits t--type CanHoldUnsigned :: Bits -> * -> Constraint-class (BitBounds bits, Num t) => CanHoldUnsigned bits t where-instance (BitBounds bits, Num t, Signedness t 'Unsigned, HasWidthFor bits t) => CanHoldUnsigned bits t+import Text.Gigaparsec.Internal.Token.Errors (mapMaybeS, LabelWithExplainConfig, annotate) +-- TODO: switch to private versions in future type IntegerParsers :: (Bits -> * -> Constraint) -> * data IntegerParsers canHold = IntegerParsers { decimal :: Parsec Integer                                              , hexadecimal :: Parsec Integer                                              , octal :: Parsec Integer                                              , binary :: Parsec Integer                                              , number :: Parsec Integer-                                             , _bounded :: forall (bits :: Bits) t. canHold bits t => Proxy bits -> Parsec Integer -> Int -> Parsec t+                                             , _bounded :: forall (bits :: Bits) t. canHold bits t+                                                        => Proxy bits+                                                        -> Parsec Integer+                                                        -> Int+                                                        -> (ErrorConfig -> Bool -> Maybe Bits -> LabelWithExplainConfig)+                                                        -> Parsec t                                              }  decimalBounded :: forall (bits :: Bits) canHold t. canHold bits t => IntegerParsers canHold -> Parsec t-decimalBounded IntegerParsers{..} = _bounded (Proxy @bits) decimal 10+decimalBounded IntegerParsers{..} = _bounded (Proxy @bits) decimal 10 label+  where label !err True = labelIntegerSignedDecimal err+        label err False = labelIntegerUnsignedDecimal err  hexadecimalBounded :: forall (bits :: Bits) canHold t. canHold bits t => IntegerParsers canHold -> Parsec t-hexadecimalBounded IntegerParsers{..} = _bounded (Proxy @bits) hexadecimal 16+hexadecimalBounded IntegerParsers{..} = _bounded (Proxy @bits) hexadecimal 16 label+  where label !err True = labelIntegerSignedHexadecimal err+        label err False = labelIntegerUnsignedHexadecimal err  octalBounded :: forall (bits :: Bits) canHold t. canHold bits t => IntegerParsers canHold -> Parsec t-octalBounded IntegerParsers{..} = _bounded (Proxy @bits) octal 8+octalBounded IntegerParsers{..} = _bounded (Proxy @bits) octal 8 label+  where label !err True  = labelIntegerSignedOctal err+        label err False = labelIntegerUnsignedOctal err  binaryBounded :: forall (bits :: Bits) canHold t. canHold bits t => IntegerParsers canHold -> Parsec t-binaryBounded IntegerParsers{..} = _bounded (Proxy @bits) binary 2+binaryBounded IntegerParsers{..} = _bounded (Proxy @bits) binary 2 label+  where label !err True = labelIntegerSignedBinary err+        label err False = labelIntegerUnsignedBinary err  numberBounded :: forall (bits :: Bits) canHold t. canHold bits t => IntegerParsers canHold -> Parsec t-numberBounded IntegerParsers{..} = _bounded (Proxy @bits) number 10+numberBounded IntegerParsers{..} = _bounded (Proxy @bits) number 10 label+  where label !err True = labelIntegerSignedNumber err+        label err False = labelIntegerUnsignedNumber err  decimal8 :: forall a canHold. canHold 'B8 a => IntegerParsers canHold -> Parsec a decimal8 = decimalBounded @'B8@@ -206,22 +120,16 @@ number64 :: forall a canHold. canHold 'B64 a => IntegerParsers canHold -> Parsec a number64 = numberBounded @'B64 -outOfBounds :: Integer -> Integer -> Int -> Integer -> [String]-outOfBounds small big radix _n = [-    "literal is not within the range " ++ resign small (" to " ++ resign big "")-  ]-  where resign n-          | n < 0 = ('-' :) . showIntAtBase (toInteger radix) intToDigit (abs n)-          | otherwise = showIntAtBase (toInteger radix) intToDigit n--mkUnsigned :: NumericDesc -> GenericNumeric -> IntegerParsers CanHoldUnsigned-mkUnsigned desc@NumericDesc{..} gen = IntegerParsers {..}-  where _bounded :: forall (bits :: Bits) t. CanHoldUnsigned bits t-                 => Proxy bits -> Parsec Integer -> Int -> Parsec t-        _bounded _ num radix = mapMaybeSWith-          (specializedGen { messages = outOfBounds 0 (upperUnsigned @bits) radix })-          (\n -> if n >= 0 && n <= upperUnsigned @bits then Just (fromInteger n) else Nothing)-          num+mkUnsigned :: NumericDesc -> GenericNumeric -> ErrorConfig -> IntegerParsers CanHoldUnsigned+mkUnsigned desc@NumericDesc{..} !gen !err = IntegerParsers {..}+  where _bounded :: forall (b :: Bits) t. CanHoldUnsigned b t+                 => Proxy b -> Parsec Integer -> Int+                 -> (ErrorConfig -> Bool -> Maybe Bits -> LabelWithExplainConfig)+                 -> Parsec t+        _bounded _ num radix label = annotate (label err False (Just (bits @b))) $+          mapMaybeS (filterIntegerOutOfBounds err 0 (upperUnsigned @b) radix)+                    (\n -> if n >= 0 && n <= upperUnsigned @b then Just (fromInteger n) else Nothing)+                    num          leadingBreakChar = case literalBreakChar of           NoBreakChar -> unit@@ -231,27 +139,28 @@         noZeroHexadecimal = do           unless (null hexadecimalLeads) (void (oneOf hexadecimalLeads))           leadingBreakChar-          plainHexadecimal gen desc+          annotate (labelIntegerHexadecimalEnd err) (plainHexadecimal gen desc (labelIntegerHexadecimalEnd err))          noZeroOctal = do           unless (null octalLeads) (void (oneOf octalLeads))           leadingBreakChar-          plainOctal gen desc+          annotate (labelIntegerOctalEnd err) (plainOctal gen desc (labelIntegerOctalEnd err))          noZeroBinary = do           unless (null binaryLeads) (void (oneOf binaryLeads))           leadingBreakChar-          plainBinary gen desc+          annotate (labelIntegerBinaryEnd err) (plainBinary gen desc (labelIntegerBinaryEnd err)) -        decimal = plainDecimal gen desc-        hexadecimal = atomic (char '0' *> noZeroHexadecimal)-        octal = atomic (char '0' *> noZeroOctal)-        binary = atomic (char '0' *> noZeroBinary)+        decimal = annotate (labelIntegerUnsignedDecimal err Nothing) $ plainDecimal gen desc (labelIntegerDecimalEnd err)+        hexadecimal = annotate (labelIntegerUnsignedHexadecimal err Nothing) $ atomic (char '0' *> noZeroHexadecimal)+        octal = annotate (labelIntegerUnsignedOctal err Nothing) $ atomic (char '0' *> noZeroOctal)+        binary = annotate (labelIntegerUnsignedBinary err Nothing) $ atomic (char '0' *> noZeroBinary)+        -- FIXME: numberEnd label is not applied here!         number           | not integerNumbersCanBeBinary           , not integerNumbersCanBeHexadecimal-          , not integerNumbersCanBeOctal = decimal-          | otherwise = atomic (zeroLead <|> decimal)+          , not integerNumbersCanBeOctal = annotate (labelIntegerUnsignedNumber err Nothing) decimal+          | otherwise = annotate (labelIntegerUnsignedNumber err Nothing) $ atomic (zeroLead <|> decimal)           where zeroLead = char '0' *> addHex (addOct (addBin (decimal <|> pure 0)))                 addHex                   | integerNumbersCanBeHexadecimal = (noZeroHexadecimal <|>)@@ -263,8 +172,8 @@                   | integerNumbersCanBeBinary = (noZeroBinary <|>)                   | otherwise = id -mkSigned :: NumericDesc -> IntegerParsers c -> IntegerParsers CanHoldSigned-mkSigned NumericDesc{..} unsigned = IntegerParsers {+mkSigned :: NumericDesc -> IntegerParsers c -> ErrorConfig -> IntegerParsers CanHoldSigned+mkSigned NumericDesc{..} !unsigned !err = IntegerParsers {     decimal = _decimal,     hexadecimal = _hexadecimal,     octal = _octal,@@ -272,25 +181,32 @@     number = _number,     ..   }-  where _bounded :: forall (bits :: Bits) t. CanHoldSigned bits t-                 => Proxy bits -> Parsec Integer -> Int -> Parsec t-        _bounded _ num radix = mapMaybeSWith-          (specializedGen { messages = outOfBounds (lowerSigned @bits) (upperSigned @bits) radix })-          (\n -> if n >= lowerSigned @bits && n <= upperSigned @bits-                 then Just (fromInteger n)-                 else Nothing)-          num+  where _bounded :: forall (b :: Bits) t. CanHoldSigned b t+                 => Proxy b -> Parsec Integer -> Int+                 -> (ErrorConfig -> Bool -> Maybe Bits -> LabelWithExplainConfig)+                 -> Parsec t+        _bounded _ num radix label = annotate (label err True (Just (bits @b))) $+          mapMaybeS (filterIntegerOutOfBounds err (lowerSigned @b) (upperSigned @b) radix)+                    (\n -> if n >= lowerSigned @b && n <= upperSigned @b+                           then Just (fromInteger n)+                           else Nothing)+                    num          sign :: Parsec (Integer -> Integer)         sign = case positiveSign of           PlusRequired -> char '+' $> id <|> char '-' $> negate           PlusOptional -> char '-' $> negate <|> optionalAs id (char '+')           PlusIllegal  -> pure id-        _decimal = atomic (sign <*> decimal unsigned)-        _hexadecimal = atomic (sign <*> hexadecimal unsigned)-        _octal = atomic (sign <*> octal unsigned)-        _binary = atomic (sign <*> binary unsigned)-        _number = atomic (sign <*> number unsigned)+        _decimal = annotate (labelIntegerSignedDecimal err Nothing) $+          atomic (sign <*> annotate (labelIntegerDecimalEnd err) (decimal unsigned))+        _hexadecimal = annotate (labelIntegerSignedHexadecimal err Nothing) $+          atomic (sign <*> annotate (labelIntegerHexadecimalEnd err) (hexadecimal unsigned))+        _octal = annotate (labelIntegerSignedOctal err Nothing) $+          atomic (sign <*> annotate (labelIntegerOctalEnd err) (octal unsigned))+        _binary = annotate (labelIntegerSignedBinary err Nothing) $+          atomic (sign <*> annotate (labelIntegerBinaryEnd err) (binary unsigned))+        _number = annotate (labelIntegerSignedNumber err Nothing) $+          atomic (sign <*> annotate (labelIntegerNumberEnd err) (number unsigned))  {-type FloatingParsers :: * data FloatingParsers = FloatingParsers {}@@ -317,7 +233,7 @@     octal = lexe octal,     binary = lexe binary,     number = lexe number,-    _bounded = \n b radix -> lexe (_bounded n b radix)+    _bounded = \n b radix label -> lexe (_bounded n b radix label)   }  {-lexemeFloating :: (forall a. Parsec a -> Parsec a) -> FloatingParsers -> FloatingParsers
src/Text/Gigaparsec/Internal/Token/Symbol.hs view
@@ -14,40 +14,44 @@  import Data.Set qualified as Set (member, toList, fromList, null) import Data.Char (toUpper, toLower, isLetter)-import Text.Gigaparsec.Errors.Combinator (amend, emptyWide, (<?>))+import Text.Gigaparsec.Errors.Combinator (amend, emptyWide, (<?>), label) import Data.Set (Set)+import Data.Map qualified as Map (findWithDefault) import Data.Maybe (mapMaybe) import Text.Gigaparsec.Internal.Require (require)+import Text.Gigaparsec.Token.Errors (ErrorConfig (labelSymbolEndOfKeyword, labelSymbolEndOfOperator, labelSymbol), notConfigured)+import Text.Gigaparsec.Internal.Token.Errors (annotate)  type Symbol :: * data Symbol = Symbol { softKeyword :: !(String -> Parsec ())                      , softOperator :: !(String -> Parsec ())                      } -mkSymbol :: SymbolDesc -> NameDesc -> Symbol-mkSymbol SymbolDesc{..} NameDesc{..} = Symbol {..}+mkSymbol :: SymbolDesc -> NameDesc -> ErrorConfig -> Symbol+mkSymbol SymbolDesc{..} NameDesc{..} err = Symbol {..}   where softKeyword name = require (not (null name)) "softKeyword" "keywords may not be empty"-          (_softKeyword caseSensitive identifierLetter name <?> [name])+          (_softKeyword caseSensitive identifierLetter name err <?> [name])         softOperator name = require (not (null name)) "softOperator" "operators may not be empty"-          (_softOperator hardOperators operatorLetter name <?> [name])+          (_softOperator hardOperators operatorLetter name err <?> [name]) -mkSym :: SymbolDesc -> Symbol -> (String -> Parsec ())-mkSym SymbolDesc{..} Symbol{..} str-  | Set.member str hardKeywords  = softKeyword str-  | Set.member str hardOperators = softOperator str-  | otherwise                    = void (atomic (string str))+mkSym :: SymbolDesc -> Symbol -> ErrorConfig -> (String -> Parsec ())+mkSym SymbolDesc{..} Symbol{..} err str =+  annotate (Map.findWithDefault notConfigured str (labelSymbol err)) $+    if | Set.member str hardKeywords  -> softKeyword str+       | Set.member str hardOperators -> softOperator str+       | otherwise                    -> void (atomic (string str))  lexeme :: (forall a. Parsec a -> Parsec a) -> Symbol -> Symbol lexeme lexe Symbol{..} = Symbol { softKeyword = lexe . softKeyword                                 , softOperator = lexe . softOperator                                 } -_softKeyword :: Bool -> CharPredicate -> String -> Parsec ()-_softKeyword caseSensitive letter kw-  | not caseSensitive = atomic (nfb letter caseString)-  | otherwise         = atomic (nfb letter (string kw))+_softKeyword :: Bool -> CharPredicate -> String -> ErrorConfig -> Parsec ()+_softKeyword caseSensitive letter kw err+  | not caseSensitive = atomic (nfb letter caseString) <?> [kw]+  | otherwise         = atomic (nfb letter (string kw)) <?> [kw]   where nfb Nothing p = void p-        nfb (Just c) p = p *> (notFollowedBy (satisfy c) <?> ["end of " ++ kw])+        nfb (Just c) p = p *> (notFollowedBy (satisfy c) <?> [labelSymbolEndOfKeyword err kw])         n = length kw         caseChar c           | isLetter c = char (toUpper c) <|> char (toLower c)@@ -56,10 +60,10 @@                  <|> emptyWide (fromIntegral n)  -- TODO: trie-based implementation-_softOperator :: Set String -> CharPredicate -> String -> Parsec ()-_softOperator hardOperators letter op =+_softOperator :: Set String -> CharPredicate -> String -> ErrorConfig -> Parsec ()+_softOperator hardOperators letter op err = label [op] $   if Set.null ends then atomic (string op *> notFollowedBy letter')-  else atomic (string op *> (notFollowedBy (void letter' <|> void (strings ends)) <?> ["end of " ++ op]))+  else atomic (string op *> (notFollowedBy (void letter' <|> void (strings ends)) <?> [labelSymbolEndOfOperator err op]))   where ends = Set.fromList (mapMaybe (flip strip op) (Set.toList hardOperators))         letter' = maybe empty satisfy letter         strip []      str@(:){}          = Just str
src/Text/Gigaparsec/Internal/Token/Text.hs view
@@ -14,21 +14,36 @@     CharPredicate,     NumberOfDigits(Exactly, AtMost, Unbounded)   )-import Text.Gigaparsec.Internal.Token.Generic (GenericNumeric(zeroAllowedDecimal, zeroAllowedHexadecimal, zeroAllowedOctal, zeroAllowedBinary))-import Data.Char (isSpace, chr, ord, digitToInt, isAscii, isLatin1, intToDigit)+import Text.Gigaparsec.Token.Errors (+    ErrorConfig(verifiedCharBadCharsUsedInLiteral, verifiedStringBadCharsUsedInLiteral,+                filterCharNonAscii, filterCharNonLatin1,+                labelCharAscii, labelCharAsciiEnd, labelCharLatin1, labelCharLatin1End,+                labelCharUnicodeEnd, labelCharUnicode,+                labelGraphicCharacter, labelStringCharacter,+                filterStringNonAscii, filterStringNonLatin1,+                labelEscapeEnd, labelEscapeSequence, filterEscapeCharNumericSequenceIllegal,+                filterEscapeCharRequiresExactDigits, labelEscapeNumericEnd, labelEscapeNumeric,+                labelStringEscapeGap, labelStringEscapeGapEnd, labelStringEscapeEmpty,+                labelStringAscii, labelStringAsciiEnd, labelStringLatin1, labelStringLatin1End,+                labelStringUnicode, labelStringUnicodeEnd),+    NotConfigurable (notConfigured)+  )+import Text.Gigaparsec.Internal.Token.Errors (+    checkBadChar, filterS, annotate, mapMaybeS, mapMaybeS',+    LabelWithExplainConfig, LabelConfig+  )+import Text.Gigaparsec.Internal.Token.Generic (+    GenericNumeric(zeroAllowedDecimal, zeroAllowedHexadecimal, zeroAllowedOctal, zeroAllowedBinary)+  )+import Data.Char (isSpace, chr, ord, digitToInt, isAscii, isLatin1) import Data.Map qualified as Map (insert, map) import Data.Set (Set) import Data.Set qualified as Set (toList) import Data.List.NonEmpty (NonEmpty((:|)), sort)-import Data.List.NonEmpty qualified as NonEmpty (toList) import Text.Gigaparsec.Registers (Reg, make, unsafeMake, gets, modify, put, get) import Text.Gigaparsec.Combinator (guardS, choice, manyTill)-import Text.Gigaparsec.Errors.Combinator (filterOut, (<?>), label, explain, mapMaybeSWith) import Control.Applicative (liftA3) import Data.Maybe (catMaybes)-import Text.Gigaparsec.Errors.ErrorGen (specializedGen, messages)-import Text.Gigaparsec.Errors.DefaultErrorBuilder (disjunct, toString, from)-import Numeric (showIntAtBase)  -- TODO: is it possible to /actually/ support Text/Bytestring in future? -- Perhaps something like the Numeric stuff?@@ -45,67 +60,72 @@ type CharacterParsers :: * type CharacterParsers = TextParsers Char -mkCharacterParsers :: TextDesc -> Escape -> CharacterParsers-mkCharacterParsers TextDesc{..} escape = TextParsers {..}-  where unicode = lit uncheckedUniLetter-        ascii = lit (filterOut (\c -> if c > '\x7f' then Just "non-ascii character" else Nothing) uncheckedUniLetter)-        latin1 = lit (filterOut (\c -> if c > '\xff' then Just "non-latin1 character" else Nothing) uncheckedUniLetter)+mkCharacterParsers :: TextDesc -> Escape -> ErrorConfig -> CharacterParsers+mkCharacterParsers TextDesc{..} escape !err = TextParsers {..}+  where unicode = lit (labelCharUnicode err) (labelCharUnicodeEnd err) uncheckedUniLetter+        ascii = lit (labelCharAscii err) (labelCharAsciiEnd err) (filterS (filterCharNonAscii err) (> '\x7f') uncheckedUniLetter)+        latin1 = lit (labelCharLatin1 err) (labelCharLatin1End err) (filterS (filterCharNonLatin1 err) (> '\xff') uncheckedUniLetter)          quote = char characterLiteralEnd-        lit c = quote *> c <* quote-        uncheckedUniLetter = escapeChar escape <|> graphic+        lit label endLabel c = annotate label quote *> c <* annotate endLabel quote+        uncheckedUniLetter = escapeChar escape <|> graphic <|> checkBadChar (verifiedCharBadCharsUsedInLiteral err) -        graphic = maybe empty satisfy (letter characterLiteralEnd False graphicCharacter) <?> ["graphic character"]+        graphic = annotate (labelGraphicCharacter err) $ maybe empty satisfy (letter characterLiteralEnd False graphicCharacter)  type StringChar :: * data StringChar = RawChar                 | EscapeChar {-# UNPACK #-} !Char (Parsec (Maybe Char)) -mkEscapeChar :: EscapeDesc -> Escape -> Parsec () -> StringChar-mkEscapeChar !desc !esc !space = EscapeChar (escBegin desc) stringEsc+mkEscapeChar :: EscapeDesc -> Escape -> Parsec () -> ErrorConfig -> StringChar+mkEscapeChar !desc !esc !space !err = EscapeChar (escBegin desc) stringEsc   where stringEsc = escapeBegin esc *> (escapeGap $> Nothing <|>                                         escapeEmpty $> Nothing <|>                                         Just <$> escapeCode esc)-        escapeEmpty = maybe empty char (emptyEscape desc)+        escapeEmpty = maybe empty (annotate (labelStringEscapeEmpty err) . char) (emptyEscape desc)         escapeGap-          | gapsSupported desc = some (space <?> ["string gap"]) *> (escapeBegin esc <?> ["end of string gap"])+          | gapsSupported desc = some (annotate (labelStringEscapeGap err) space)+                              *> annotate (labelStringEscapeGapEnd err) (escapeBegin esc)           | otherwise = empty -mkChar :: StringChar -> CharPredicate -> Parsec (Maybe Char)-mkChar RawChar = maybe empty (fmap Just . label ["string character"] . satisfy)-mkChar (EscapeChar escBegin stringEsc) =-  foldr (\p -> label ["string character"] . (<|> fmap Just (satisfy (\c -> p c && c /= escBegin) <?> ["graphic character"])))+mkChar :: StringChar -> ErrorConfig -> CharPredicate -> Parsec (Maybe Char)+mkChar RawChar !err = maybe empty ((<|> checkBadChar (verifiedStringBadCharsUsedInLiteral err)) . fmap Just . annotate (labelStringCharacter err) . satisfy)+mkChar (EscapeChar escBegin stringEsc) err =+  foldr (\p -> annotate (labelStringCharacter err) . (<|> checkBadChar (verifiedStringBadCharsUsedInLiteral err)) . (<|> fmap Just (annotate (labelGraphicCharacter err) (satisfy (\c -> p c && c /= escBegin)))))         stringEsc  isRawChar :: StringChar -> Bool isRawChar RawChar = True isRawChar EscapeChar{} = False -ensureAscii :: Parsec String -> Parsec String-ensureAscii = filterOut $ \s ->-  if not (all isAscii s) then Just "non-ascii characters in string literal, this is not allowed"-  else Nothing+ensureAscii :: ErrorConfig -> Parsec String -> Parsec String+ensureAscii !err = filterS (filterStringNonAscii err) (not . all isAscii) -ensureLatin1 :: Parsec String -> Parsec String-ensureLatin1 = filterOut $ \s ->-  if not (all isLatin1 s) then Just "non-latin1 characters in string literal, this is not allowed"-  else Nothing+ensureLatin1 :: ErrorConfig -> Parsec String -> Parsec String+ensureLatin1 !err = filterS (filterStringNonLatin1 err) (not . all isLatin1) -mkStringParsers :: Set (String, String) -> StringChar -> CharPredicate -> Bool -> StringParsers-mkStringParsers !ends !stringChar !isGraphic !allowsAllSpace = TextParsers {..}-  where ascii = stringLiteral ensureAscii-        latin1 = stringLiteral ensureLatin1-        unicode = stringLiteral id+mkStringParsers :: Set (String, String) -> StringChar -> CharPredicate -> Bool -> ErrorConfig -> StringParsers+mkStringParsers !ends !stringChar !isGraphic !allowsAllSpace !err = TextParsers {..}+  where ascii = stringLiteral (ensureAscii err) (labelStringAscii err) (labelStringAsciiEnd err)+        latin1 = stringLiteral (ensureLatin1 err) (labelStringLatin1 err) (labelStringLatin1End err)+        unicode = stringLiteral id (labelStringUnicode err) (labelStringUnicodeEnd err) -        stringLiteral :: (Parsec String -> Parsec String) -> Parsec String-        stringLiteral valid = choice (map (uncurry (makeStringParser valid)) (Set.toList ends))+        stringLiteral :: (Parsec String -> Parsec String)+                      -> (Bool -> Bool -> LabelWithExplainConfig)+                      -> (Bool -> Bool -> LabelConfig)+                      -> Parsec String+        stringLiteral valid openLabel closeLabel =+          choice (map (uncurry (makeStringParser valid openLabel closeLabel)) (Set.toList ends)) -        makeStringParser :: (Parsec String -> Parsec String) -> String -> String -> Parsec String-        makeStringParser valid begin end@(terminalInit : _) =-          let strChar = mkChar stringChar (letter terminalInit allowsAllSpace isGraphic)-          in (string begin *>) . valid $-               catMaybes <$> manyTill (Just <$> char terminalInit <|> strChar) (atomic (string end))-        makeStringParser _ _ [] = error "string terminals cannot be empty"+        makeStringParser :: (Parsec String -> Parsec String)+                         -> (Bool -> Bool -> LabelWithExplainConfig)+                         -> (Bool -> Bool -> LabelConfig)+                         -> String -> String -> Parsec String+        makeStringParser valid openLabel closeLabel begin end@(terminalInit : _) =+          let strChar = mkChar stringChar err (letter terminalInit allowsAllSpace isGraphic)+          in (annotate (openLabel allowsAllSpace (isRawChar stringChar)) (string begin) *>) . valid $+               catMaybes <$> manyTill (Just <$> char terminalInit <|> strChar)+                                      (annotate (closeLabel allowsAllSpace (isRawChar stringChar)) (atomic (string end)))+        makeStringParser _ _ _ _ [] = error "string terminals cannot be empty"  letter :: Char -> Bool -> CharPredicate -> CharPredicate letter !terminalLead !allowsAllSpace (Just g)@@ -119,11 +139,11 @@                      , escapeChar :: !(Parsec Char)                      } -mkEscape :: EscapeDesc -> GenericNumeric -> Escape-mkEscape EscapeDesc{..} gen = Escape {..}+mkEscape :: EscapeDesc -> GenericNumeric -> ErrorConfig -> Escape+mkEscape EscapeDesc{..} gen !err = Escape {..}   where-    escapeBegin = void (char escBegin) <?> ["escape sequence"]-    escapeCode = explain "invalid escape sequence" $ label ["end of escape sequence"] $+    escapeBegin = annotate (labelEscapeSequence err) $ void (char escBegin)+    escapeCode = annotate (labelEscapeEnd err) $       escMapped <|> numericEscape     escapeChar = escapeBegin *> escapeCode @@ -132,27 +152,21 @@      numericEscape = decimalEsc <|> hexadecimalEsc <|> octalEsc <|> binaryEsc -    decimalEsc = fromDesc 10 decimalEscape (zeroAllowedDecimal gen) digit-    hexadecimalEsc = fromDesc 16 hexadecimalEscape (zeroAllowedHexadecimal gen) hexDigit-    octalEsc = fromDesc 8 octalEscape (zeroAllowedOctal gen) octDigit-    binaryEsc = fromDesc 2 binaryEscape (zeroAllowedBinary gen) bit+    decimalEsc = fromDesc 10 decimalEscape (zeroAllowedDecimal gen notConfigured) digit+    hexadecimalEsc = fromDesc 16 hexadecimalEscape (zeroAllowedHexadecimal gen notConfigured) hexDigit+    octalEsc = fromDesc 8 octalEscape (zeroAllowedOctal gen notConfigured) octDigit+    binaryEsc = fromDesc 2 binaryEscape (zeroAllowedBinary gen notConfigured) bit      boundedChar :: Parsec Integer -> Char -> Maybe Char -> Int -> Parsec Char-    boundedChar p maxValue prefix radix = foldr (\c t -> char c *> t) (mapMaybeSWith err f p) prefix-      where f c+    boundedChar p maxValue prefix radix = annotate (labelEscapeNumeric err radix) $+      foldr (\c t -> char c *> annotate (labelEscapeNumericEnd err c radix) t)+            (mapMaybeS config f p)+            prefix+      where config = filterEscapeCharNumericSequenceIllegal err maxValue radix+            f c              | c < toInteger (ord maxValue) = Just (chr (fromInteger c))              | otherwise = Nothing-            err = specializedGen { messages = messages }-            messages :: Integer -> [String]-            messages c-              | c > toInteger (ord maxValue) =-                  [showIntAtBase (toInteger radix) intToDigit c-                    (" is greater than the maximum character value of "-                    ++ showIntAtBase (toInteger radix) intToDigit (toInteger (ord maxValue)) "")]-              | otherwise = ["illegal unicode character: "-                          ++ showIntAtBase (toInteger radix) intToDigit c ""] -     atMost' :: Int -> Parsec Char -> Reg r Word -> Parsec Integer     atMost' radix dig atMostR =       -- FIXME: surely this is an inefficient mess with the translations?@@ -164,13 +178,9 @@      exactly :: Word -> Word -> Int -> Parsec Char -> NonEmpty Word -> Parsec Integer     exactly n full radix dig reqDigits = make n $ \atMostR ->-      mapMaybeSWith (specializedGen {messages = messages})-                    (\(num, m) -> if m == full then Just num else Nothing)-                    (atMost' radix dig atMostR <~> gets atMostR (full -))-      where messages :: (Integer, Word) -> [String]-            messages (_, got) =-              [toString ("numeric escape requires " <> formatted <> "digits, but only got" <> from got)]-            ~(Just formatted) = disjunct True (map show (NonEmpty.toList reqDigits))+      mapMaybeS' snd (filterEscapeCharRequiresExactDigits err radix reqDigits)+                 (\(num, m) -> if m == full then Just num else Nothing)+                 (atMost' radix dig atMostR <~> gets atMostR (full -))      oneOfExactly' :: NonEmpty Word -> Word -> Word -> [Word] -> Int -> Parsec Char -> Reg r Word -> Parsec Integer     oneOfExactly' reqDigits digits m [] radix dig digitsParsed =
src/Text/Gigaparsec/Token/Descriptions.hs view
@@ -1,6 +1,9 @@ {-# LANGUAGE Safe #-} {-# LANGUAGE OverloadedLists #-} {-# OPTIONS_GHC -Wno-partial-fields #-}+-- TODO: In next major, don't expose the constructors of the descriptions,+-- we want them built up by record copy for forwards compatible evolution+-- We can move this into an internal module to accommodate that if we want module Text.Gigaparsec.Token.Descriptions (module Text.Gigaparsec.Token.Descriptions) where  import Data.Char (isSpace)
+ src/Text/Gigaparsec/Token/Errors.hs view
@@ -0,0 +1,292 @@+{-# LANGUAGE Safe #-}+{-# LANGUAGE NoMonomorphismRestriction, BlockArguments, OverloadedLists, OverloadedStrings #-}+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}+module Text.Gigaparsec.Token.Errors (+    ErrorConfig(+      labelNumericBreakChar, labelIntegerUnsignedDecimal,+      labelIntegerUnsignedHexadecimal, labelIntegerUnsignedOctal,+      labelIntegerUnsignedBinary, labelIntegerUnsignedNumber,+      labelIntegerSignedDecimal,+      labelIntegerSignedHexadecimal, labelIntegerSignedOctal,+      labelIntegerSignedBinary, labelIntegerSignedNumber,+      labelIntegerDecimalEnd,+      labelIntegerHexadecimalEnd, labelIntegerOctalEnd,+      labelIntegerBinaryEnd, labelIntegerNumberEnd,+      filterIntegerOutOfBounds,+      labelNameIdentifier, labelNameOperator,+      unexpectedNameIllegalIdentifier, unexpectedNameIllegalOperator,+      filterNameIllFormedIdentifier, filterNameIllFormedOperator,+      labelCharAscii, labelCharLatin1, labelCharUnicode,+      labelCharAsciiEnd, labelCharLatin1End, labelCharUnicodeEnd,+      labelStringAscii, labelStringLatin1, labelStringUnicode,+      labelStringAsciiEnd, labelStringLatin1End, labelStringUnicodeEnd,+      labelStringCharacter, labelGraphicCharacter, labelEscapeSequence,+      labelEscapeNumeric, labelEscapeNumericEnd, labelEscapeEnd,+      labelStringEscapeEmpty, labelStringEscapeGap, labelStringEscapeGapEnd,+      filterCharNonAscii, filterCharNonLatin1, filterStringNonAscii, filterStringNonLatin1,+      filterEscapeCharRequiresExactDigits, filterEscapeCharNumericSequenceIllegal,+      verifiedCharBadCharsUsedInLiteral, verifiedStringBadCharsUsedInLiteral,+      labelSymbol, labelSymbolEndOfKeyword, labelSymbolEndOfOperator,+      labelSpaceEndOfLineComment, labelSpaceEndOfMultiComment+    ),+    defaultErrorConfig,+    LabelWithExplainConfig, LabelWithExplainConfigurable(..),+    LabelConfig, LabelConfigurable(..),+    ExplainConfig, ExplainConfigurable(..),+    NotConfigurable(..),+    FilterConfig,+    VanillaFilterConfig, VanillaFilterConfigurable(..),+    SpecializedFilterConfig, SpecializedFilterConfigurable(..),+    BasicFilterConfigurable(..),+    VerifiedBadChars, badCharsFail, badCharsReason,+    Unverified(..),+    Bits(B8, B16, B32, B64)+  ) where++import Data.Set (Set)+import Data.Map (Map)+import Data.Map qualified as Map (empty)+import Data.List.NonEmpty (NonEmpty((:|)))+import Data.List.NonEmpty qualified as NonEmpty (toList)+import Data.Kind (Constraint)+import Text.Gigaparsec.Internal.Token.BitBounds (Bits(B8, B16, B32, B64))+import Numeric (showIntAtBase)+import Data.Char (intToDigit, ord)+import Text.Gigaparsec.Errors.DefaultErrorBuilder (from, disjunct, toString)+import Text.Gigaparsec.Internal.Token.Errors (+    LabelWithExplainConfig(LELabelAndReason, LELabel, LEHidden, LEReason, LENotConfigured),+    LabelConfig(LLabel, LHidden, LNotConfigured), ExplainConfig(EReason, ENotConfigured),+    FilterConfig(VSBecause, VSUnexpected, VSUnexpectedBecause, VSBasicFilter, VSSpecializedFilter),+    SpecializedFilterConfig(SSpecializedFilter, SBasicFilter),+    VanillaFilterConfig(VBecause, VUnexpected, VUnexpectedBecause, VBasicFilter),+    VerifiedBadChars(BadCharsUnverified, BadCharsFail, BadCharsReason)+  )++type ErrorConfig :: *+data ErrorConfig =+  ErrorConfig { labelNumericBreakChar :: !LabelWithExplainConfig+              , labelIntegerUnsignedDecimal :: Maybe Bits -> LabelWithExplainConfig+              , labelIntegerUnsignedHexadecimal :: Maybe Bits -> LabelWithExplainConfig+              , labelIntegerUnsignedOctal :: Maybe Bits -> LabelWithExplainConfig+              , labelIntegerUnsignedBinary :: Maybe Bits -> LabelWithExplainConfig+              , labelIntegerUnsignedNumber :: Maybe Bits -> LabelWithExplainConfig+              , labelIntegerSignedDecimal :: Maybe Bits -> LabelWithExplainConfig+              , labelIntegerSignedHexadecimal :: Maybe Bits -> LabelWithExplainConfig+              , labelIntegerSignedOctal :: Maybe Bits -> LabelWithExplainConfig+              , labelIntegerSignedBinary :: Maybe Bits -> LabelWithExplainConfig+              , labelIntegerSignedNumber :: Maybe Bits -> LabelWithExplainConfig+              , labelIntegerDecimalEnd :: LabelConfig+              , labelIntegerHexadecimalEnd :: LabelConfig+              , labelIntegerOctalEnd :: LabelConfig+              , labelIntegerBinaryEnd :: LabelConfig+              , labelIntegerNumberEnd :: LabelConfig+              , filterIntegerOutOfBounds :: Integer -> Integer -> Int -> FilterConfig Integer+              , labelNameIdentifier :: String+              , labelNameOperator :: String+              , unexpectedNameIllegalIdentifier :: String -> String+              , unexpectedNameIllegalOperator :: String -> String+              , filterNameIllFormedIdentifier :: FilterConfig String+              , filterNameIllFormedOperator :: FilterConfig String+              , labelCharAscii :: LabelWithExplainConfig+              , labelCharLatin1 :: LabelWithExplainConfig+              , labelCharUnicode :: LabelWithExplainConfig+              , labelCharAsciiEnd :: LabelConfig+              , labelCharLatin1End :: LabelConfig+              , labelCharUnicodeEnd :: LabelConfig+              , labelStringAscii :: Bool -> Bool -> LabelWithExplainConfig+              , labelStringLatin1 :: Bool -> Bool -> LabelWithExplainConfig+              , labelStringUnicode :: Bool -> Bool -> LabelWithExplainConfig+              , labelStringAsciiEnd :: Bool -> Bool -> LabelConfig+              , labelStringLatin1End :: Bool -> Bool -> LabelConfig+              , labelStringUnicodeEnd :: Bool -> Bool -> LabelConfig+              , labelStringCharacter :: LabelConfig+              , labelGraphicCharacter :: LabelWithExplainConfig+              , labelEscapeSequence :: LabelWithExplainConfig+              , labelEscapeNumeric :: Int -> LabelWithExplainConfig+              , labelEscapeNumericEnd :: Char -> Int -> LabelWithExplainConfig+              , labelEscapeEnd :: LabelWithExplainConfig+              , labelStringEscapeEmpty :: LabelConfig+              , labelStringEscapeGap :: LabelConfig+              , labelStringEscapeGapEnd :: LabelConfig+              , filterCharNonAscii :: VanillaFilterConfig Char+              , filterCharNonLatin1 :: VanillaFilterConfig Char+              , filterStringNonAscii :: SpecializedFilterConfig String+              , filterStringNonLatin1 :: SpecializedFilterConfig String+              , filterEscapeCharRequiresExactDigits :: Int -> NonEmpty Word -> SpecializedFilterConfig Word+              , filterEscapeCharNumericSequenceIllegal :: Char -> Int -> SpecializedFilterConfig Integer+              , verifiedCharBadCharsUsedInLiteral :: VerifiedBadChars+              , verifiedStringBadCharsUsedInLiteral :: VerifiedBadChars+              , labelSymbol :: Map String LabelWithExplainConfig+              -- don't bother with these until parsley standardises+              --, defaultSymbolKeyword :: Labeller+              --, defaultSymbolOperator :: Labeller+              --, defaultSymbolPunctuaton :: Labeller+              , labelSymbolEndOfKeyword :: String -> String+              , labelSymbolEndOfOperator :: String -> String+              , labelSpaceEndOfLineComment :: LabelWithExplainConfig+              , labelSpaceEndOfMultiComment :: LabelWithExplainConfig+              }++defaultErrorConfig :: ErrorConfig+defaultErrorConfig = ErrorConfig {..}+  where labelNumericBreakChar = notConfigured+        labelIntegerUnsignedDecimal = const notConfigured+        labelIntegerUnsignedHexadecimal = const notConfigured+        labelIntegerUnsignedOctal = const notConfigured+        labelIntegerUnsignedBinary = const notConfigured+        labelIntegerUnsignedNumber = const notConfigured+        labelIntegerSignedDecimal = const notConfigured+        labelIntegerSignedHexadecimal = const notConfigured+        labelIntegerSignedOctal = const notConfigured+        labelIntegerSignedBinary = const notConfigured+        labelIntegerSignedNumber = const notConfigured+        labelIntegerDecimalEnd = notConfigured+        labelIntegerHexadecimalEnd = notConfigured+        labelIntegerOctalEnd = notConfigured+        labelIntegerBinaryEnd = notConfigured+        labelIntegerNumberEnd = notConfigured+        filterIntegerOutOfBounds small big nativeRadix = specializedFilter+          (outOfBounds small big nativeRadix)+        labelNameIdentifier = "identifier"+        labelNameOperator = "operator"+        unexpectedNameIllegalIdentifier = ("keyword " ++)+        unexpectedNameIllegalOperator = ("reserved operator " ++)+        filterNameIllFormedIdentifier = unexpected ("identifier " ++)+        filterNameIllFormedOperator = unexpected ("operator " ++)+        labelCharAscii = notConfigured+        labelCharLatin1 = notConfigured+        labelCharUnicode = notConfigured+        labelCharAsciiEnd = notConfigured+        labelCharLatin1End = notConfigured+        labelCharUnicodeEnd = notConfigured+        labelStringAscii _ _ = notConfigured+        labelStringLatin1 _ _ = notConfigured+        labelStringUnicode _ _ = notConfigured+        labelStringAsciiEnd _ _ = notConfigured+        labelStringLatin1End _ _ = notConfigured+        labelStringUnicodeEnd _ _ = notConfigured+        labelStringCharacter = label ["string character"]+        labelGraphicCharacter = label ["graphic character"]+        labelEscapeSequence = label ["escape sequence"]+        labelEscapeNumeric _ = notConfigured+        labelEscapeNumericEnd _ _ = notConfigured+        labelEscapeEnd = labelAndReason ["end of escape sequence"] "invalid escape sequence"+        labelStringEscapeEmpty = notConfigured+        labelStringEscapeGap = label ["string gap"]+        labelStringEscapeGapEnd = label ["end of string gap"]+        filterCharNonAscii = because (const "non-ascii character")+        filterCharNonLatin1 = because (const "non-latin1 character")+        filterStringNonAscii =+          specializedFilter (const ["non-ascii characters in string literal, this is not allowed"])+        filterStringNonLatin1 =+          specializedFilter (const ["non-latin1 characters in string literal, this is not allowed"])+        filterEscapeCharRequiresExactDigits _ needed = specializedFilter \got ->+          let ~(Just formatted) = disjunct True (map show (NonEmpty.toList needed))+          in [toString ("numeric escape requires " <> formatted <> "digits, but only got" <> from got)]+        filterEscapeCharNumericSequenceIllegal maxEscape radix =+          let messages :: Integer -> NonEmpty String+              messages c+                | c > toInteger (ord maxEscape) = singleton $+                    showIntAtBase (toInteger radix) intToDigit c+                      (" is greater than the maximum character value of "+                      ++ showIntAtBase (toInteger radix) intToDigit (toInteger (ord maxEscape)) "")+                | otherwise = singleton $ "illegal unicode character: "+                                        ++ showIntAtBase (toInteger radix) intToDigit c ""+          in specializedFilter messages+        verifiedCharBadCharsUsedInLiteral = unverified+        verifiedStringBadCharsUsedInLiteral = unverified+        labelSymbol = Map.empty+        -- defaultSymbolKeyword = Label+        -- defaultSymbolOperator = Label+        -- defaultSymbolOperator = NotConfigured+        labelSymbolEndOfKeyword = ("end of " ++)+        labelSymbolEndOfOperator = ("end of " ++)+        labelSpaceEndOfLineComment = label ["end of comment"]+        labelSpaceEndOfMultiComment = label ["end of comment"]++outOfBounds :: Integer -> Integer -> Int -> Integer -> NonEmpty String+outOfBounds small big radix _n = singleton $+    "literal is not within the range " ++ resign small (" to " ++ resign big "")+  where resign n+          | n < 0 = ('-' :) . showIntAtBase (toInteger radix) intToDigit (abs n)+          | otherwise = showIntAtBase (toInteger radix) intToDigit n++type LabelConfigurable :: * -> Constraint+class LabelConfigurable config where+  label :: Set String -> config+  hidden :: config++instance LabelConfigurable LabelConfig where+  label = LLabel+  hidden = LHidden+instance LabelConfigurable LabelWithExplainConfig where+  label = LELabel+  hidden = LEHidden++type ExplainConfigurable :: * -> Constraint+class ExplainConfigurable config where+  reason :: String -> config++instance ExplainConfigurable ExplainConfig where reason = EReason+instance ExplainConfigurable LabelWithExplainConfig where reason = LEReason++type LabelWithExplainConfigurable :: * -> Constraint+class LabelWithExplainConfigurable config where+  labelAndReason :: Set String -> String -> config++instance LabelWithExplainConfigurable LabelWithExplainConfig where labelAndReason = LELabelAndReason++type NotConfigurable :: * -> Constraint+class NotConfigurable config where+  notConfigured :: config++instance NotConfigurable LabelWithExplainConfig where notConfigured = LENotConfigured+instance NotConfigurable LabelConfig where notConfigured = LNotConfigured+instance NotConfigurable ExplainConfig where notConfigured = ENotConfigured++type VanillaFilterConfigurable :: (* -> *) -> Constraint+class VanillaFilterConfigurable config where+  unexpected :: (a -> String) -> config a+  because :: (a -> String) -> config a+  unexpectedBecause :: (a -> String) -> (a -> String) -> config a++instance VanillaFilterConfigurable FilterConfig where+  unexpected = VSUnexpected+  because = VSBecause+  unexpectedBecause = VSUnexpectedBecause++instance VanillaFilterConfigurable VanillaFilterConfig where+  unexpected = VUnexpected+  because = VBecause+  unexpectedBecause = VUnexpectedBecause++type SpecializedFilterConfigurable :: (* -> *) -> Constraint+class SpecializedFilterConfigurable config where+  specializedFilter :: (a -> NonEmpty String) -> config a++instance SpecializedFilterConfigurable FilterConfig where+  specializedFilter = VSSpecializedFilter+instance SpecializedFilterConfigurable SpecializedFilterConfig where+  specializedFilter = SSpecializedFilter++type BasicFilterConfigurable :: (* -> *) -> Constraint+class BasicFilterConfigurable config where+  basicFilter :: config a++instance BasicFilterConfigurable FilterConfig where basicFilter = VSBasicFilter+instance BasicFilterConfigurable VanillaFilterConfig where basicFilter = VBasicFilter+instance BasicFilterConfigurable SpecializedFilterConfig where basicFilter = SBasicFilter++badCharsFail :: Map Char (NonEmpty String) -> VerifiedBadChars+badCharsFail = BadCharsFail+badCharsReason :: Map Char String -> VerifiedBadChars+badCharsReason = BadCharsReason++type Unverified :: * -> Constraint+class Unverified config where+  unverified :: config++instance Unverified VerifiedBadChars where unverified = BadCharsUnverified++singleton :: a -> NonEmpty a+singleton x = x :| []
src/Text/Gigaparsec/Token/Lexer.hs view
@@ -3,7 +3,7 @@ -- Ideally, we should probably expose all the functionally via this one file -- for ergonomics module Text.Gigaparsec.Token.Lexer (-    Lexer, mkLexer,+    Lexer, mkLexer, mkLexerWithErrorConfig,     Lexeme, lexeme, nonlexeme, fully, space,     apply, sym, symbol, names,     -- Symbol@@ -27,7 +27,7 @@   ) where  import Text.Gigaparsec.Internal.Token.Lexer (-    Lexer, mkLexer,+    Lexer, mkLexer, mkLexerWithErrorConfig,     Lexeme (rawMultiStringLiteral), lexeme, nonlexeme, fully, space,     apply, sym, symbol, names,     integer, natural,@@ -46,7 +46,7 @@     octal8, octal16, octal32, octal64,     binary8, binary16, binary32, binary64   )-import Text.Gigaparsec.Internal.Token.Numeric qualified as Internal+import Text.Gigaparsec.Internal.Token.BitBounds qualified as Internal import Text.Gigaparsec.Internal.Token.Text (     TextParsers, ascii, unicode, latin1   )
test/Text/Gigaparsec/Token/NamesTests.hs view
@@ -14,6 +14,7 @@ import Control.Monad (forM_) import Data.Char (isLetter, isAlphaNum) import Text.Gigaparsec.Internal.TestError+import Text.Gigaparsec.Token.Errors (defaultErrorConfig)  tests :: TestTree tests = testGroup "Names"@@ -96,6 +97,7 @@                        , hardKeywords = ["keyword", "HARD"]                        , hardOperators = ["+", "<", "<="]                        })+          defaultErrorConfig  basicNames :: Names basicNames = namesFor (Just isLetter) (Just isAlphaNum) True