packages feed

symparsec 1.0.0 → 1.0.1

raw patch · 12 files changed

+443/−79 lines, 12 files

Files

CHANGELOG.md view
@@ -1,3 +1,7 @@+## 1.0.1 (2024-05-27)+* add `TakeRest` combinator+* re-add `:<|>:` combinator with more accurate behaviour clarification+ ## 1.0.0 (2024-05-25) * small rewrite, changing how `Done` works (now non-consuming) * single all parsers
README.md view
@@ -1,80 +1,72 @@ # Symparsec-Type level string (`Symbol`) parser combinators. Reify to runtime parsers with-guaranteed identical behaviour.+[hackage-parsec]: https://hackage.haskell.org/package/parsec -It's a Parsec-like for `Symbol`s; thus, Symparsec.+Type level string (`Symbol`) parser combinators. A [Parsec][hackage-parsec]-like+for `Symbol`s; thus, Symparsec! With all the features you'd expect: -Previously named symbol-parser.+* define parsers compositionally, largely as you would on the term level+* pretty, detailed parse errors+* decent performance (for simple parsers) -Requires GHC 9.6 for singling parsers.+Parsers may also be reified and used at runtime with _guaranteed identical+behaviour_ via a healthy dose of singletons. -## Features-* Define parsers compositionally, largely as you would on the term level.-* Pretty parse errors.-* Hopefully decent performance.-* Reify parsers to term level with guaranteed identical behaviour via a-  healthy dose of singletons.+Requires GHC >= 9.6.  ## Examples+Define a type-level parser:+ ```haskell-ghci> import Symparsec-ghci> :k! Run (Drop 3 :*>: Isolate 2 NatDec :<*>: (Drop 3 :*>: NatHex)) "___10___FF"-...-= Right '( '(10, 255), "")+import Symparsec+type PExample = Skip 1 :*>: Isolate 2 NatHex :<*>: (Literal "_" :*>: TakeRest) ``` +Use it to parse a type-level string (in a GHCi session):++```haskell+ghci> :k! Run PExample "xFF_"+Run ...+= Right '( '(255, "etc"), "")+```++Use it to parse a different, term-level string:++```haskell+ghci> import Singleraeh.Demote ( demote )+ghci> run' @PExample demote "abc_123"+Right ((188,"123"),"")+```+ ## Why? Via `GHC.Generics`, we may inspect Haskell data types on the type level. Constructor names are `Symbols`. Ever reify these, then perform some sort of checking or parsing on the term level? Symparsec does the parsing on the type level instead. Catch bugs earlier, get faster runtime. +Also type-level Haskell authors deserve fun libraries too!!+ ## Design ### The parser-A parser is a 4-tuple of:+A parser is a 3-tuple of: -* a consuming character parser; given a character and a state, returns+* a character parser; given a character and a state, returns   * `Cont s`: keep going, here's the next state `s`-  * `Done r`: parse successful with value `r`+  * `Done r`: parse successful with value `r`, _do not consume character_   * `Err  E`: parse error, details in the `E` (a structured error) * an end handler, which takes only a state, and can only return `Done` or `Err`-* an initial "raw" state-* a state initializer, which turns the initial "raw" state into the first state-  value (the indirection here assists singling)+* an initial state -Running a parser is simple:+Running such a parser is very simple:  * initialize state * parse character by character until end of input, or `Done`/`Err`  Parsers may not communicate with the runner any other way. This means no backtracking, chunking etc. This is a conscious decision, made for simplicity.--Note that due to character parsers being consuming, we often need to do a bit of-"internal lookahead", where we check if we expect to consume any more-characters, and if not then emit a `Done`. It also means that non-consuming-parsers such as `Take 0` are invalid for non-empty strings. The state-initializer should be used to catch such cases.--This is a rough overview of parser design. See the code and/or Haddock-documentation for precise details.--### Pitfall: Character parsers always consume-There is no backtracking or lookahead, that you do not implement yourself. This-keeps the parser execution extremely simple, but breaks null parsers such as-`Drop 0`, so these must be handled specially (unless you don't getting mind-stuck type families on misuse).--For concrete examples, see the implementation of `Drop` and `Literal`.--### Pitfall: Not all parsers are definable-* No changing parser state. Thus, parsers such as `Try :: Parser s r -> Parser-  (s, [Char]) r` are not definable. _Parsers may not backtrack._-  * Combinators such as `<|>` can emulate backtracking, but they are complex and-    hard to reason about (they may have bugs!).+We're still able to implement a good handful of parser combinators regardless,+including a limited form of backtracking. -### Feature: Parsers may be reified to use at runtime, with guaranteed same behaviour-TODO+This is a rough overview. See the code & Haddocks for precise details.  ## Contributing I would gladly accept further combinators or other suggestions. Please add an
− src/Symparsec/Internal/List.hs
@@ -1,9 +0,0 @@-{-# LANGUAGE UndecidableInstances #-}--module Symparsec.Internal.List where---- | Reverse a type level list.-type Reverse as = Reverse' as '[]-type family Reverse' (as :: [k]) (acc :: [k]) :: [k] where-  Reverse' '[]      acc = acc-  Reverse' (a : as) acc = Reverse' as (a : acc)
src/Symparsec/Parser.hs view
@@ -77,11 +77,6 @@         -> SParser ss sr ('PParser pCh pEnd s0)  -- | Parse a 'Char' with the given state.------ The action is always consuming. For this reason, you may need to look ahead--- for the final case, so as to not consume an extra 'Char'. This prevents many--- zero-length parsers. It's a bit weird. See--- 'Data.Type.Symbol.Parser.Parser.Drop' for an example. type  ParserCh str s r = Char -> s -> Result str s r type PParserCh     s r = ParserCh Symbol s r 
src/Symparsec/Parser/Common.hs view
@@ -20,13 +20,15 @@ import Singleraeh.Either  -- | Fail with the given message when given any character to parse.+type FailCh name e = Err (EBase name e)+ type FailChSym :: Symbol -> PDoc -> ParserChSym s r data FailChSym name e f type instance App (FailChSym name e) f = FailChSym1 name e f  type FailChSym1 :: Symbol -> PDoc -> ParserChSym1 s r data FailChSym1 name e ch s-type instance App (FailChSym1 name e ch) s = Err (EBase name e)+type instance App (FailChSym1 name e ch) s = FailCh name e  failChSym     :: SSymbol name -> SDoc e -> SParserChSym ss sr (FailChSym name e)
src/Symparsec/Parser/End.hs view
@@ -1,24 +1,32 @@ module Symparsec.Parser.End where  import Symparsec.Parser.Common-import DeFun.Core ( Con1, con1 )+import DeFun.Core import Singleraeh.Tuple ( SUnit(..) ) import Singleraeh.Either ( SEither(..) )-import GHC.TypeLits ( symbolSing )-import TypeLevelShow.Doc ( singDoc )  -- | Assert end of symbol, or fail. type End :: PParser () ()-type End = 'PParser-    (FailChSym "End" (Text "expected end of string"))-    (Con1 Right)-    '()+type End = 'PParser EndChSym (Con1 Right) '()  sEnd :: SParser SUnit SUnit End-sEnd = SParser (failChSym symbolSing singDoc) (con1 SRight) SUnit+sEnd = SParser sEndChSym (con1 SRight) SUnit --- TODO orphan instance. if I need to, make some dumb type family idk. instance SingParser End where     type PS  End = SUnit     type PR  End = SUnit     singParser' = sEnd++-- it'd be nice to just reuse FailChSym here but we get told off for writing an+-- orphan instance. fair enough, write this instead+type EndChSym :: ParserChSym s r+data EndChSym f+type instance App EndChSym f = EndChSym1 f++type EndChSym1 :: ParserChSym1 s r+data EndChSym1 ch s+type instance App (EndChSym1 ch) s =+    Err (EBase "End" (Text "expected end of string"))++sEndChSym :: SParserChSym ss rr EndChSym+sEndChSym = Lam2 $ \_ch _s -> SErr singE
+ src/Symparsec/Parser/Or.hs view
@@ -0,0 +1,330 @@+{-# LANGUAGE UndecidableInstances #-}++module Symparsec.Parser.Or where++import Symparsec.Parser+import TypeLevelShow.Doc+import GHC.TypeLits hiding ( ErrorMessage(..) )+import DeFun.Core+import Singleraeh.Tuple+import Singleraeh.Either+import Singleraeh.List++{- | Limited parser choice. Try left; if it fails, backtrack and try right.+     However, _the right choice must consume at least as much as the left+     choice._ If it doesn't, then even if the right parser succeeds, it+     will emit an error.++This behaviour is due to the parser runner not supporting backtracking. We can+emulate it by storing a record of the characters parsed so far, and "replaying"+these on the right parser if the left parser fails. If the right parser ends+before we finish replaying, we will have consumed extra characters that we can't+ask the runner to revert.++For example, @Literal "abcd" :<|>: Literal "ab"@ is bad. An input of @abcX@ will+trigger the consumption error.++I can't think of another way to implement this with the current parser design. I+think it's the best we have. A more complex parser design may permit changing+internal running state, so we could save and load state (this would permit a+@Try p@ parser). But that's scary. And you're better off designing your+type-level string schemas to permit non-backtracking parsing anyway...++Also problematic is that we never emit a left parser error, so errors can+degrade. Perhaps your string was one character off a successful left parse; but+if it fails, you won't see that error.+-}+infixl 3 :<|>:+type (:<|>:)+    :: PParser sl rl+    -> PParser sr rr+    -> PParser (OrS sl sr) (Either rl rr)+type family pl :<|>: pr where+    'PParser plCh plEnd s0l :<|>: 'PParser prCh prEnd s0r =+        Or' plCh plEnd s0l prCh prEnd s0r++type Or' plCh plEnd s0l prCh prEnd s0r = 'PParser+    (OrChSym plCh prCh s0r)+    (OrEndSym plEnd prCh prEnd s0r)+    (Left '(s0l, '[]))++type SOrS ssl ssr = SEither (STuple2 ssl (SList SChar)) ssr+type OrS  sl  sr  = Either (sl, [Char]) sr+type SPOr ssl srl ssr srr plCh plEnd s0l prCh prEnd s0r =+    SParser (SOrS ssl ssr) (SEither srl srr) (Or' plCh plEnd s0l prCh prEnd s0r)++sOr+    :: SParser ssl srl ('PParser plCh plEnd s0l)+    -> SParser ssr srr ('PParser prCh prEnd s0r)+    -> SPOr    ssl srl ssr srr plCh plEnd s0l prCh prEnd s0r+sOr (SParser plCh plEnd s0l) (SParser prCh prEnd s0r) = SParser+    (sOrChSym plCh prCh s0r)+    (sOrEndSym plEnd prCh prEnd s0r)+    (SLeft (STuple2 s0l SNil))++instance+  ( pl ~ 'PParser plCh plEnd s0l+  , pr ~ 'PParser prCh prEnd s0r+  , SingParser pl+  , SingParser pr+  ) => SingParser (Or' plCh plEnd s0l prCh prEnd s0r) where+    type PS (Or' plCh plEnd s0l prCh prEnd s0r) = SOrS+        (PS ('PParser plCh plEnd s0l))+        (PS ('PParser prCh prEnd s0r))+    type PR (Or' plCh plEnd s0l prCh prEnd s0r) = SEither+        (PR ('PParser plCh plEnd s0l))+        (PR ('PParser prCh prEnd s0r))+    singParser' = sOr (singParser @pl) (singParser @pr)++type OrCh+    :: ParserChSym sl rl+    -> ParserChSym sr rr+    -> sr+    -> PParserCh (OrS sl sr) (Either rl rr)+type family OrCh plCh prCh sr ch s where+    -- | parsing left+    OrCh plCh prCh s0r ch (Left  '(sl, chs)) =+        OrChL prCh s0r ch chs (plCh @@ ch @@ sl)++    -- | parsing right (after left failed and was successfully replayed)+    OrCh plCh prCh _  ch (Right sr) =+        OrChR (prCh @@ ch @@ sr)++type OrChL+    :: ParserChSym sr rr+    -> sr+    -> Char+    -> [Char]+    -> PResult sl rl+    -> PResult (Either (sl, [Char]) sr) (Either rl rr)+type family OrChL prCh s0r chLast chs resl where+    -- | left parser OK, continue+    OrChL _    _   chLast chs (Cont sl) = Cont (Left  '(sl, chLast : chs))++    -- | left parser OK, done+    OrChL _    _   _      _   (Done rl) = Done (Left  rl)++    -- | left parser failed: ignore, replay consumed characters on right parser+    OrChL prCh s0r chLast chs (Err  _ ) =+        OrChLReplay prCh chLast (Reverse chs) (Cont s0r)++type OrChLReplay+    :: ParserChSym sr rr+    -> Char+    -> [Char]+    -> PResult sr rr+    -> PResult (Either (sl, [Char]) sr) (Either rl rr)+type family OrChLReplay prCh chLast chs resr where+    -- | right parser OK, keep replaying+    OrChLReplay prCh chLast (ch : chs) (Cont sr) =+        OrChLReplay prCh chLast chs (prCh @@ ch @@ sr)+    --+    -- | right parser OK, final replay char+    OrChLReplay prCh chLast '[]        (Cont sr) = OrChR (prCh @@ chLast @@ sr)++    -- | right parser fail: wrap error+    OrChLReplay prCh chLast chs        (Err  er) = Err (EOrR er)++    -- | right parser done but still replaying! no choice but to error out+    OrChLReplay prCh chLast chs        (Done rr) = Err EOrStillReplaying+        -- Done (Right rr) -- TODO++sOrChLReplay+    :: SParserChSym ssr srr prCh+    -> SChar chLast+    -> SList SChar chs+    -> SResult ssr srr resr+    -> SResult (SOrS ssl ssr) (SEither srl srr)+        (OrChLReplay prCh chLast chs resr)+sOrChLReplay prCh chLast chs resr =+    case chs of+      SCons ch chs' ->+        case resr of+          SCont  sr ->+            sOrChLReplay prCh chLast chs' (prCh @@ ch @@ sr)+          SDone _rr -> SErr eOrStillReplaying+          SErr   er -> SErr $ eOrR er+      SNil ->+        case resr of+          SCont  sr -> sOrChR (prCh @@ chLast @@ sr)+          SDone _rr -> SErr eOrStillReplaying+          SErr   er -> SErr $ eOrR er++type EOrR er = EIn "Or(R)" er+eOrR :: SE er -> SE (EOrR er)+eOrR er = SEIn symbolSing er++type EOrStillReplaying = EBase "Or"+    (Text "right parser much consume at least as much as the failed left parser")+eOrStillReplaying :: SE EOrStillReplaying+eOrStillReplaying = singE++type family OrChR resr where+    OrChR (Cont sr) = Cont (Right sr)+    OrChR (Done rr) = Done (Right rr)+    OrChR (Err  er) = Err (EOrR er)++sOrChR+    :: SResult ssr srr resr+    -> SResult (SOrS ssl ssr) (SEither srl srr) (OrChR resr)+sOrChR = \case+  SCont sr -> SCont $ SRight sr+  SDone rr -> SDone $ SRight rr+  SErr  er -> SErr  $ eOrR er++type OrEnd+    :: ParserEndSym sl rl+    -> ParserChSym  sr rr+    -> ParserEndSym sr rr+    -> sr+    -> PParserEnd (Either (sl, [Char]) sr) (Either rl rr)+type family OrEnd plEnd prCh prEnd sr res where+    -- | input ended during left parser+    OrEnd plEnd prCh prEnd s0r (Left  '(sl, chs)) =+        OrEndL prCh prEnd s0r chs (plEnd @@ sl)++    -- | input ended during right parser: call right end+    OrEnd plEnd prCh prEnd _   (Right sr)         = OrEndR (prEnd @@ sr)++type OrEndR :: PResultEnd rr -> PResultEnd (Either rl rr)+type family OrEndR resr where+    OrEndR (Right rr) = Right (Right rr)+    OrEndR (Left  er) = Left  (EOrR er)++sOrEndR+    :: SResultEnd srr resr+    -> SResultEnd (SEither srl srr) (OrEndR resr)+sOrEndR = \case+  SRight rr -> SRight $ SRight rr+  SLeft  er -> SLeft  $ eOrR er++type OrEndL+    :: ParserChSym  sr rr+    -> ParserEndSym sr rr+    -> sr+    -> [Char]+    -> Either PE rl+    -> Either PE (Either rl rr)+type family OrEndL prCh prEnd s0r chs resl where+    -- | input ended during left parser and left end succeeeded: phew+    OrEndL prCh prEnd s0r chs (Right rl) = Right (Left rl)++    -- | input ended during left parser and left end failed. replay on right,+    --   then eventually call right end+    OrEndL prCh prEnd s0r chs (Left  el) =+        OrEndLReplay prCh prEnd (Reverse chs) (Cont s0r)++sOrEndL+    :: SParserChSym  ssr srr prCh+    -> SParserEndSym ssr srr prEnd+    -> ssr s0r+    -> SList SChar chs+    -> SResultEnd srl resl+    -> SResultEnd (SEither srl srr) (OrEndL prCh prEnd s0r chs resl)+sOrEndL prCh prEnd s0r chs = \case+  SRight  rl -> SRight $ SLeft rl+  SLeft  _el -> sOrEndLReplay prCh prEnd (sReverse chs) (SCont s0r)++type OrEndLReplay+    :: ParserChSym  sr rr+    -> ParserEndSym sr rr+    -> [Char]+    -> PResult sr rr+    -> Either PE (Either rl rr)+type family OrEndLReplay prCh prEnd chs resr where+    -- | right parser OK, keep replaying+    OrEndLReplay prCh prEnd (ch : chs) (Cont sr) =+        OrEndLReplay prCh prEnd chs (prCh @@ ch @@ sr)++    -- | replay complete+    OrEndLReplay prCh prEnd '[]        resr      = OrEndLReplay' prEnd resr++    -- | right parser fail: wrap error+    OrEndLReplay prCh prEnd chs        (Err  er) = Left (EOrR er)++    -- | right parser done but still replaying! no choice but to error out+    OrEndLReplay prCh prEnd chs        (Done rr) = Left EOrStillReplaying+        -- Right (Right rr) TODO++sOrEndLReplay+    :: SParserChSym  ssr srr prCh+    -> SParserEndSym ssr srr prEnd+    -> SList SChar chs+    -> SResult ssr srr resr+    -> SResultEnd (SEither srl srr) (OrEndLReplay prCh prEnd chs resr)+sOrEndLReplay prCh prEnd chs resr =+    case chs of+      SCons ch chs' ->+        case resr of+          SCont  sr ->+            sOrEndLReplay prCh prEnd chs' (prCh @@ ch @@ sr)+          SErr   er -> SLeft $ eOrR er+          SDone _rr -> SLeft eOrStillReplaying+      SNil ->+        case resr of+          SCont sr -> sOrEndR $ prEnd @@ sr+          SDone rr -> SRight  $ SRight rr+          SErr  er -> SLeft   $ eOrR er++type family OrEndLReplay' prEnd resr where+    OrEndLReplay' prEnd (Cont sr) = OrEndR (prEnd @@ sr)+    OrEndLReplay' prEnd (Done rr) = Right  (Right rr)+    OrEndLReplay' prEnd (Err  er) = Left   (EOrR er)++type OrChSym+    :: ParserChSym sl rl+    -> ParserChSym sr rr+    -> sr+    -> ParserChSym (OrS sl sr) (Either rl rr)+data OrChSym plCh prCh s0r f+type instance App (OrChSym plCh prCh s0r) f = OrChSym1 plCh prCh s0r f++type OrChSym1+    :: ParserChSym sl rl+    -> ParserChSym sr rr+    -> sr+    -> ParserChSym1 (OrS sl sr) (Either rl rr)+data OrChSym1 plCh prCh sr ch s+type instance App (OrChSym1 plCh prCh sr ch) s = OrCh plCh prCh sr ch s++sOrChSym+    :: SParserChSym ssl srl plCh+    -> SParserChSym ssr srr prCh+    -> ssr s0r+    -> SParserChSym (SOrS ssl ssr) (SEither srl srr) (OrChSym plCh prCh s0r)+sOrChSym plCh prCh s0r = Lam2 $ \ch -> \case+  SLeft  (STuple2 sl chs) -> sOrChL prCh s0r ch chs (plCh @@ ch @@ sl)+  SRight sr -> sOrChR (prCh @@ ch @@ sr)++sOrChL+    :: SParserChSym ssr srr prCh+    -> ssr s0r+    -> SChar chLast+    -> SList SChar chs+    -> SResult ssl srl resl+    -> SResult (SOrS ssl ssr) (SEither srl srr) (OrChL prCh s0r chLast chs resl)+sOrChL prCh s0r chLast chs = \case+  SCont  sl -> SCont $ SLeft $ STuple2 sl $ SCons chLast chs+  SDone  rl -> SDone $ SLeft rl+  SErr  _el -> sOrChLReplay prCh chLast (sReverse chs) (SCont s0r)++type OrEndSym+    :: ParserEndSym sl rl+    -> ParserChSym  sr rr+    -> ParserEndSym sr rr+    -> sr+    -> ParserEndSym (Either (sl, [Char]) sr) (Either rl rr)+data OrEndSym plEnd prCh prEnd s0r s+type instance App (OrEndSym plEnd prCh prEnd s0r) s =+    OrEnd plEnd prCh prEnd s0r s++sOrEndSym+    :: SParserEndSym ssl srl plEnd+    -> SParserChSym  ssr srr prCh+    -> SParserEndSym ssr srr prEnd+    -> ssr s0r+    -> SParserEndSym (SOrS ssl ssr) (SEither srl srr)+        (OrEndSym plEnd prCh prEnd s0r)+sOrEndSym plEnd prCh prEnd s0r = Lam $ \case+  SLeft (STuple2 sl chs) -> sOrEndL prCh prEnd s0r chs (plEnd @@ sl)+  SRight sr -> sOrEndR $ prEnd @@ sr
src/Symparsec/Parser/Skip.hs view
@@ -50,7 +50,7 @@     SkipEnd n = Left (ESkipPastEnd n)  type ESkipPastEnd n = EBase "Skip"-    (      Text "tried to drop "+    (      Text "tried to skip "       :<>: Text (ShowNatDec n) :<>: Text " chars from empty string") eSkipPastEnd :: SNat n -> SE (ESkipPastEnd n) eSkipPastEnd n = withKnownSymbol (sShowNatDec n) singE
src/Symparsec/Parser/Take.hs view
@@ -21,7 +21,7 @@ type  TakeS = (Natural, [Char])  sTake :: SNat n -> SParser STakeS SSymbol (Take n)-sTake n = SParser takeChSym takeEndSym (STuple2 n SNil)+sTake n = SParser sTakeChSym sTakeEndSym (STuple2 n SNil)  instance KnownNat n => SingParser (Take n) where     type PS (Take n) = STakeS@@ -37,8 +37,8 @@ data TakeChSym f type instance App TakeChSym f = TakeChSym1 f -takeChSym :: SParserChSym STakeS SSymbol TakeChSym-takeChSym = Lam2 $ \ch (STuple2 n chs) ->+sTakeChSym :: SParserChSym STakeS SSymbol TakeChSym+sTakeChSym = Lam2 $ \ch (STuple2 n chs) ->     case testEquality n (SNat @0) of       Just Refl -> SDone $ revCharsToSymbol chs       Nothing   ->@@ -64,8 +64,8 @@ data TakeEndSym s type instance App TakeEndSym s = TakeEnd s -takeEndSym :: SParserEndSym STakeS SSymbol TakeEndSym-takeEndSym = Lam $ \(STuple2 n chs) ->+sTakeEndSym :: SParserEndSym STakeS SSymbol TakeEndSym+sTakeEndSym = Lam $ \(STuple2 n chs) ->     case testEquality n (SNat @0) of       Just Refl -> SRight $ revCharsToSymbol chs       Nothing   -> unsafeCoerce $ SLeft $ eTakeEnd n
+ src/Symparsec/Parser/TakeRest.hs view
@@ -0,0 +1,39 @@+{-# LANGUAGE UndecidableInstances #-}++module Symparsec.Parser.TakeRest where++import Symparsec.Parser.Common+import Singleraeh.Symbol ( RevCharsToSymbol, revCharsToSymbol )+import Singleraeh.List ( SList(..) )+import Singleraeh.Either ( SEither(..) )+import GHC.TypeLits hiding ( ErrorMessage(..) )+import DeFun.Core++-- | Return the remaining input string.+type TakeRest = 'PParser TakeRestChSym TakeRestEndSym '[]++sTakeRest :: SParser (SList SChar) SSymbol TakeRest+sTakeRest = SParser sTakeRestChSym sTakeRestEndSym SNil++instance SingParser TakeRest where+    type PS TakeRest = SList SChar+    type PR TakeRest = SSymbol+    singParser' = sTakeRest++type TakeRestChSym :: ParserChSym [Char] Symbol+data TakeRestChSym f+type instance App TakeRestChSym f = TakeRestChSym1 f++type TakeRestChSym1 :: ParserChSym1 [Char] Symbol+data TakeRestChSym1 ch chs+type instance App (TakeRestChSym1 ch) chs = Cont (ch : chs)++sTakeRestChSym :: SParserChSym (SList SChar) SSymbol TakeRestChSym+sTakeRestChSym = Lam2 $ \ch chs -> SCont $ SCons ch chs++type TakeRestEndSym :: ParserEndSym [Char] Symbol+data TakeRestEndSym chs+type instance App TakeRestEndSym chs = Right (RevCharsToSymbol chs)++sTakeRestEndSym :: SParserEndSym (SList SChar) SSymbol TakeRestEndSym+sTakeRestEndSym = Lam $ \chs -> SRight $ revCharsToSymbol chs
src/Symparsec/Parsers.hs view
@@ -15,6 +15,7 @@   -- * Positional   -- $positional   , Take+  , TakeRest   , Skip   , End   , Isolate@@ -40,6 +41,7 @@ import Symparsec.Parser.Literal import Symparsec.Parser.End import Symparsec.Parser.Take+import Symparsec.Parser.TakeRest --import Symparsec.Parser.Or  -- $binary-combinators
symparsec.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           symparsec-version:        1.0.0+version:        1.0.1 synopsis:       Type level string parser combinators description:    Please see README.md. category:       Types, Data@@ -30,7 +30,6 @@ library   exposed-modules:       Symparsec-      Symparsec.Internal.List       Symparsec.Parser       Symparsec.Parser.Common       Symparsec.Parser.End@@ -38,8 +37,10 @@       Symparsec.Parser.Literal       Symparsec.Parser.Natural       Symparsec.Parser.Natural.Digits+      Symparsec.Parser.Or       Symparsec.Parser.Skip       Symparsec.Parser.Take+      Symparsec.Parser.TakeRest       Symparsec.Parser.Then       Symparsec.Parser.Then.VoidLeft       Symparsec.Parser.Then.VoidRight