packages feed

symparsec-1.0.0: src/Symparsec/Parser/Then/VoidRight.hs

{-# LANGUAGE UndecidableInstances #-}

module Symparsec.Parser.Then.VoidRight where

import Symparsec.Parser.Common
import Singleraeh.Either ( SEither(..) )
import Singleraeh.Tuple ( STuple2(..) )
import DeFun.Core

type SPThenVR ssl srl ssr srr plCh plEnd s0l prCh prEnd s0r =
    SParser
        (SEither ssl (STuple2 srl ssr))
        srl
        (ThenVR' plCh plEnd s0l prCh prEnd s0r)

sThenVR
    :: SParser  ssl srl ('PParser plCh plEnd s0l)
    -> SParser  ssr srr ('PParser prCh prEnd s0r)
    -> SPThenVR ssl srl ssr srr plCh plEnd s0l prCh prEnd s0r
sThenVR (SParser plCh plEnd s0l) (SParser prCh prEnd s0r) =
    SParser (sThenVRChSym plCh prCh s0r) (sThenVREndSym plEnd prEnd s0r) (SLeft s0l)

instance
  -- Shame I can't use pl, pr in associated type synonyms! :(
  ( pl ~ 'PParser plCh plEnd s0l
  , pr ~ 'PParser prCh prEnd s0r
  , SingParser pl
  , SingParser pr
  ) => SingParser (ThenVR' plCh plEnd s0l prCh prEnd s0r) where
    type PS (ThenVR' plCh plEnd s0l prCh prEnd s0r) =
        SEither
            (PS ('PParser plCh plEnd s0l))
            (STuple2
                (PR ('PParser plCh plEnd s0l))
                (PS ('PParser prCh prEnd s0r)))
    type PR (ThenVR' plCh plEnd s0l prCh prEnd s0r) =
        PR ('PParser plCh plEnd s0l)
    singParser' = sThenVR (singParser @pl) (singParser @pr)

-- | Sequence two parsers, running left then right, and discard the return value
--   of the right parser.
infixl 4 :<*:
type (:<*:)
    :: PParser sl rl
    -> PParser sr rr
    -> PParser (Either sl (rl, sr)) rl
type family pl :<*: pr where
    'PParser plCh plEnd s0l :<*: 'PParser prCh prEnd s0r =
        ThenVR' plCh plEnd s0l prCh prEnd s0r

type ThenVR'
    :: ParserChSym  sl rl
    -> ParserEndSym sl rl
    -> sl
    -> ParserChSym  sr rr
    -> ParserEndSym sr rr
    -> sr
    -> PParser (Either sl (rl, sr)) rl
type ThenVR' plCh plEnd s0l prCh prEnd s0r =
    'PParser (ThenVRChSym plCh prCh s0r) (ThenVREndSym plEnd prEnd s0r) (Left s0l)

type ThenVRCh
    :: ParserChSym sl rl
    -> ParserChSym sr rr
    -> sr
    -> PParserCh (Either sl (rl, sr)) rl
type family ThenVRCh plCh prCh s0r ch s where
    ThenVRCh plCh prCh s0r ch (Left  sl) =
        ThenVRChL prCh s0r ch (plCh @@ ch @@ sl)
    ThenVRCh plCh prCh s0r ch (Right '(rl, sr)) =
        ThenVRChR rl (prCh @@ ch @@ sr)

type family ThenVRChL prCh s0r ch resl where
    ThenVRChL prCh s0r ch (Cont sl) = Cont (Left  sl)
    ThenVRChL prCh s0r ch (Done rl) =
        -- 'Done' doesn't consume, so re-parse with the R parser.
        ThenVRChR rl (prCh @@ ch @@ s0r)
    ThenVRChL prCh s0r ch (Err  el) = Err  (EThenVRChL el)

type EThenVRChL el = EIn "ThenVR(L)" el
eThenVRChL :: SE el -> SE (EThenVRChL el)
eThenVRChL el = withSingE el $ singE

type family ThenVRChR rl resr where
    ThenVRChR rl (Cont sr) = Cont (Right '(rl, sr))
    ThenVRChR rl (Done rr) = Done rl
    ThenVRChR rl (Err  er) = Err  (EThenVRChR er)

type EThenVRChR er = EIn "ThenVR(R)" er
eThenVRChR :: SE er -> SE (EThenVRChR er)
eThenVRChR er = withSingE er $ singE

sThenVRChR
    :: srl rl
    -> SResult ssr srr resr
    -> SResult (SEither ssl (STuple2 srl ssr)) srl (ThenVRChR rl resr)
sThenVRChR rl = \case
  SCont  sr -> SCont $ SRight $ STuple2 rl sr
  SDone _rr -> SDone rl
  SErr   er -> SErr  $ eThenVRChR er

sThenVRChSym
    :: SParserChSym ssl srl plCh
    -> SParserChSym ssr srr prCh
    -> ssr sr
    -> SParserChSym (SEither ssl (STuple2 srl ssr)) srl
        (ThenVRChSym plCh prCh sr)
sThenVRChSym plCh prCh s0r = Lam2 $ \ch -> \case
  SLeft sl ->
    case plCh @@ ch @@ sl of
      SCont sl' -> SCont $ SLeft sl'
      SDone rl  -> sThenVRChR rl (prCh @@ ch @@ s0r)
      SErr  el  -> SErr  $ eThenVRChL el
  SRight (STuple2 rl sr) -> sThenVRChR rl (prCh @@ ch @@ sr)

type ThenVRChSym
    :: ParserChSym sl rl
    -> ParserChSym sr rr
    -> sr
    -> ParserChSym (Either sl (rl, sr)) rl
data ThenVRChSym plCh prCh s0r f
type instance App (ThenVRChSym plCh prCh s0r) f = ThenVRChSym1 plCh prCh s0r f

type ThenVRChSym1
    :: ParserChSym sl rl
    -> ParserChSym sr rr
    -> sr
    -> ParserChSym1 (Either sl (rl, sr)) rl
data ThenVRChSym1 plCh prCh s0r ch s
type instance App (ThenVRChSym1 plCh prCh s0r ch) s = ThenVRCh plCh prCh s0r ch s

type family ThenVREnd plEnd prEnd s0r s where
    -- | EOT during R: call R end
    ThenVREnd plEnd prEnd s0r (Right '(rl, sr)) = ThenVREndR rl    (prEnd @@ sr)
    -- | EOT during L: call L end, pass R end
    ThenVREnd plEnd prEnd s0r (Left sl)         = ThenVREndL prEnd s0r (plEnd @@ sl)

type family ThenVREndR rl res where
    -- | EOT during R, R end succeeds: success
    ThenVREndR rl (Right rr) = Right rl
    -- | EOT during R, R end fails: error
    ThenVREndR rl (Left  er) = Left  (EThenVREndR er)

type EThenVREndR er = EIn "ThenVR(R) end" er
eThenVREndR :: SE er -> SE (EThenVREndR er)
eThenVREndR er = withSingE er $ singE

sThenVREndR
    :: srl rl
    -> SResultEnd srr res
    -> SResultEnd srl (ThenVREndR rl res)
sThenVREndR rl = \case
  SRight _rr -> SRight rl
  SLeft   er -> SLeft  $ eThenVREndR er

type family ThenVREndL prEnd s0r res where
    -- | EOT during L, L end succeeds: call R end on initial R state
    ThenVREndL prEnd s0r (Right rl) = ThenVREndR rl (prEnd @@ s0r)
    -- | EOT during L, L end fails: error
    ThenVREndL prEnd s0r (Left  el) = Left (EThenVREndL el)

type EThenVREndL er = EIn "ThenVR(L) end" er
eThenVREndL :: SE er -> SE (EThenVREndL er)
eThenVREndL er = withSingE er $ singE

sThenVREndSym
    :: SParserEndSym ssl srl plEnd
    -> SParserEndSym ssr srr prEnd
    -> ssr s0r
    -> SParserEndSym (SEither ssl (STuple2 srl ssr)) srl
        (ThenVREndSym plEnd prEnd s0r)
sThenVREndSym plEnd prEnd s0r = Lam $ \case
  SRight (STuple2 rl sr) -> sThenVREndR rl (prEnd @@ sr)
  SLeft  sl ->
    case plEnd @@ sl of
      SRight rl -> sThenVREndR rl (prEnd @@ s0r)
      SLeft  el -> SLeft $ eThenVREndL el

type ThenVREndSym
    :: ParserEndSym sl rl
    -> ParserEndSym sr rr
    -> sr
    -> ParserEndSym (Either sl (rl, sr)) rl
data ThenVREndSym plEnd prEnd s0r s
type instance App (ThenVREndSym plEnd prEnd s0r) s = ThenVREnd plEnd prEnd s0r s