diff --git a/gigaparsec.cabal b/gigaparsec.cabal index 93b5205..de41a90 100644 --- a/gigaparsec.cabal +++ b/gigaparsec.cabal @@ -24,7 +24,7 @@ source-repository head location: https://github.com/noughtmare/gigaparsec common common - build-depends: base >= 4.14 && <5, containers + build-depends: base >= 4.14 && <5, containers, free ghc-options: -Wall default-language: GHC2021 diff --git a/src/Gigaparsec/Core.hs b/src/Gigaparsec/Core.hs index fe68590..0966aa4 100644 --- a/src/Gigaparsec/Core.hs +++ b/src/Gigaparsec/Core.hs @@ -6,6 +6,9 @@ {-# LANGUAGE RankNTypes #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE DerivingVia #-} +{-# LANGUAGE QuantifiedConstraints #-} +{-# LANGUAGE DataKinds #-} +{-# LANGUAGE LambdaCase #-} module Gigaparsec.Core where @@ -13,140 +16,248 @@ import qualified Data.Set as Set import Data.Set (Set) import qualified Data.Map as Map import Data.Map (Map) -import Unsafe.Coerce ( unsafeCoerce ) -import GHC.Exts (Any) import Data.Maybe (fromMaybe) -import Data.Kind -import Control.Applicative -import Data.Functor.Compose +import Control.Applicative ( asum, Alternative((<|>)) ) +import Data.Functor.Compose ( Compose(Compose) ) +import Control.Applicative.Free ( hoistAp, Ap(..) ) +import Data.Proxy ( Proxy(..) ) +import Data.Char (intToDigit) -data Action m a where - Match :: Char -> Action m () - Descend :: m a -> Action m a +data (f + g) a = L (f a) | R (g a) deriving Show + +type family Equal a b where + Equal a a = True + Equal a b = False + +class f < g where + inj :: f a -> g a + +instance In (Equal f g) f g h => f < (g + h) where + inj = injIn (Proxy :: Proxy (Equal f g)) + +class In b f g h where + injIn :: Proxy b -> f a -> (g + h) a + +instance (f ~ g) => In True f g h where + injIn Proxy = L +instance f < h => In False f g h where + injIn Proxy = R . inj + +instance (OrdF f, OrdF g) => OrdF (f + g) where + compareF (L x) (L y) = compareF x y + compareF (L _) (R _) = LT + compareF (R _) (L _) = GT + compareF (R x) (R y) = compareF x y + +data Match a where + Match :: Char -> Match () +deriving instance Show (Match a) + +instance OrdF Match where + compareF (Match x) (Match y) = compare x y + +send :: f < g => f a -> Alt g a +send x = Alt [Ap (inj x) (Pure id)] + +match :: Match < f => Char -> Alt f () +match c = send (Match c) -- Free alternative, see https://hackage.haskell.org/package/free-5.2/docs/Control-Alternative-Free.html --- But this one is higher order. +-- But this one also satisfies right distributivity: f <*> (x <|> y) = (f <*> x) <|> (f <*> y) + +newtype Alt f a = Alt { alternatives :: [Ap f a] } + deriving (Functor, Applicative, Alternative) via Compose [] (Ap f) + +hoistAlt :: (forall x. f x -> g x) -> Alt f a -> Alt g a +hoistAlt f (Alt xs) = Alt (fmap (hoistAp f) xs) -type Alt :: (Type -> Type) -> ((Type -> Type) -> Type -> Type) -> Type -> Type -newtype Alt m f a = Alt [AltF m f a] - deriving (Functor, Applicative, Alternative) via Compose [] (AltF m f) -type AltF :: (Type -> Type) -> ((Type -> Type) -> Type -> Type) -> Type -> Type -data AltF m f a = Pure a | forall b. Ap (f m b) (AltF m f (b -> a)) -deriving instance Functor (AltF m f) -instance Applicative (AltF m f) where - pure = Pure - Pure f <*> q = fmap f q - Ap x p <*> q = Ap x (flip <$> p <*> q) +data Pa f a b where + Erup :: Pa f a a + Pa :: Pa f a b -> f c -> Pa f (c -> a) b +deriving instance (forall c. Show (f c)) => Show (Pa f a b) -type Name :: Type -> Type -> Type -newtype Name n a = Name n deriving Show +comparePa :: OrdF f => Pa f a b -> Pa f c d -> Ordering +comparePa Erup Erup = EQ +comparePa Erup _ = LT +comparePa _ Erup = GT +comparePa (Pa xs x) (Pa ys y) = compareF x y <> comparePa xs ys -newtype G n = G (Map n [AltF (Name n) Action Any]) +showAp :: (forall x. Show (f x)) => Ap f a -> String +showAp Pure{} = "Pure" +showAp (Ap x xs) = "(Ap (" ++ show x ++ ") (" ++ showAp xs ++ "))" -lookupG :: forall n a. Ord n => G n -> Name n a -> [AltF (Name n) Action a] -lookupG (G m) (Name n) = unsafeCoerce (m Map.! n) +compareAp :: OrdF f => Ap f a -> Ap f b -> Ordering +compareAp Pure{} Pure{} = EQ +compareAp Pure{} _ = LT +compareAp _ Pure{} = GT +compareAp (Ap x xs) (Ap y ys) = compareF x y <> compareAp xs ys -data Deps n a b where - Self :: Deps n a a - Dep :: !(Name n b) -> !Int -> !Int -> !(Deps n a c) -> Deps n a (b -> c) -deriving instance Show n => Show (Deps n a b) +newtype G f g = G { lookupG :: forall a. f a -> Alt (Match + g) a } -data Slot n a = forall b. +data Slot f a = forall b. Slot - !(Name n a) -- ^ The name of the current nonterminal - !Int -- ^ The number of the current alternative - !Int -- ^ The number of symbols that have already been processed - !(Deps n a b) -- ^ The dependencies, i.e. the (external) nonterminals that have been processed - (AltF (Name n) Action b) -- ^ The actions that still need to be done + !(f a) -- ^ The name of the current nonterminal + (Pa (Match + f) b a) -- ^ The processed dependencies + (Ap (Match + f) b) -- ^ The actions that still need to be done -data Descriptor n a = +instance (forall x. (Show (f x))) => Show (Slot f a) where + show (Slot x y z) = "(Slot (" ++ show x ++ ") (" ++ show y ++ ") (" ++ showAp z ++ "))" + +data Descriptor f a = Descriptor - !(Slot n a) + !(Slot f a) !Int -- ^ The left extent !Int -- ^ The pivot String -- ^ The remainder of the input (to the right of the pivot) +deriving instance (forall x. (Show (f x))) => Show (Descriptor f a) -data SomeDescriptor n = forall a. SomeDescriptor (Descriptor n a) -instance Ord n => Eq (SomeDescriptor n) where +data SomeDescriptor f = forall a. SomeDescriptor (Descriptor f a) +deriving instance (forall x. (Show (f x))) => Show (SomeDescriptor f) +instance (OrdF f) => Eq (SomeDescriptor f) where SomeDescriptor x == SomeDescriptor y = compareDescriptor x y == EQ -instance Ord n => Ord (SomeDescriptor n) where +instance (OrdF f) => Ord (SomeDescriptor f) where compare (SomeDescriptor x) (SomeDescriptor y) = compareDescriptor x y -compareName :: Ord n => Name n a -> Name n b -> Ordering -compareName (Name x) (Name y) = compare x y +class OrdF f where + compareF :: f a -> f b -> Ordering + +data SomeF f where + SomeF :: f a -> SomeF f +instance OrdF f => Eq (SomeF f) where + SomeF x == SomeF y = compareF x y == EQ +instance OrdF f => Ord (SomeF f) where + compare (SomeF x) (SomeF y) = compareF x y -compareSlot :: Ord n => Slot n a -> Slot n b -> Ordering -compareSlot (Slot x1 x2 x3 _ _) (Slot y1 y2 y3 _ _) = compareName x1 y1 <> compare x2 y2 <> compare x3 y3 +compareSlot :: OrdF f => Slot f a -> Slot f b -> Ordering +compareSlot (Slot x1 x2 x3) (Slot y1 y2 y3) = compareF x1 y1 <> comparePa x2 y2 <> compareAp x3 y3 -compareDescriptor :: Ord n => Descriptor n a -> Descriptor n b -> Ordering +compareDescriptor :: OrdF f => Descriptor f a -> Descriptor f b -> Ordering compareDescriptor (Descriptor x1 x2 x3 _) (Descriptor y1 y2 y3 _) = compareSlot x1 y1 <> compare x2 y2 <> compare x3 y3 -initialDescriptor :: Name n a -> String -> Int -> AltF (Name n) Action a -> SomeDescriptor n -initialDescriptor n xs i act = SomeDescriptor (Descriptor (Slot n i 0 Self act) 0 0 xs) +initialDescriptor :: f a -> String -> Ap (Match + f) a -> SomeDescriptor f +initialDescriptor nt xs act = SomeDescriptor (Descriptor (Slot nt Erup act) 0 0 xs) -newtype WaitForAscend n = WA (Map (n, Int) [Int -> String -> SomeDescriptor n]) +newtype WaitForAscend f = WA (Map (SomeF f, Int) [Int -> String -> SomeDescriptor f]) emptyWA :: WaitForAscend n emptyWA = WA Map.empty -lookupWA :: forall a n. Ord n => WaitForAscend n -> Name n a -> Int -> [Int -> String -> SomeDescriptor n] -lookupWA (WA m) (Name n) k = fromMaybe [] (m Map.!? (n, k)) +lookupWA :: forall a f. OrdF f => WaitForAscend f -> f a -> Int -> [Int -> String -> SomeDescriptor f] +lookupWA (WA m) nt k = fromMaybe [] (m Map.!? (SomeF nt, k)) -insertWA :: Ord n => Name n a -> Int -> (Int -> String -> SomeDescriptor n) -> WaitForAscend n -> WaitForAscend n -insertWA (Name n) k f (WA m) = WA (Map.insertWith (++) (n, k) [f] m) +insertWA :: OrdF f => f a -> Int -> (Int -> String -> SomeDescriptor f) -> WaitForAscend f -> WaitForAscend f +insertWA nt k f (WA m) = WA (Map.insertWith (++) (SomeF nt, k) [f] m) -newtype WaitForDescend n = WD (Map (n, Int) [(Int, String)]) +newtype WaitForDescend f = WD (Map (SomeF f, Int) [(Int, String)]) emptyWD :: WaitForDescend n emptyWD = WD Map.empty -lookupWD :: forall a n. Ord n => WaitForDescend n -> Name n a -> Int -> [(Int, String)] -lookupWD (WD m) (Name n) k = fromMaybe [] (m Map.!? (n, k)) +lookupWD :: forall a f. OrdF f => WaitForDescend f -> f a -> Int -> [(Int, String)] +lookupWD (WD m) nt k = fromMaybe [] (m Map.!? (SomeF nt, k)) -insertWD :: Ord n => Name n a -> Int -> (Int, String) -> WaitForDescend n -> WaitForDescend n -insertWD (Name n) k x (WD m) = WD (Map.insertWith (++) (n, k) [x] m) +insertWD :: OrdF f => f a -> Int -> (Int, String) -> WaitForDescend f -> WaitForDescend f +insertWD nt k x (WD m) = WD (Map.insertWith (++) (SomeF nt, k) [x] m) -parse :: forall n a. Ord n => (G n, Name n a) -> String -> Set (SomeDescriptor n) -parse (g, z) xs0 = go Set.empty emptyWA emptyWD (zipWith (initialDescriptor z xs0) [0..] (lookupG g z)) where - go :: Set (SomeDescriptor n) -> WaitForAscend n -> WaitForDescend n -> [SomeDescriptor n] -> Set (SomeDescriptor n) +parse :: forall a f g. (OrdF f, g < f) => Gram f -> g a -> String -> Set (SomeDescriptor f) +parse g z xs0 = go Set.empty emptyWA emptyWD (map (initialDescriptor (inj z) xs0) (alternatives (lookupG g (inj z)))) where + go :: Set (SomeDescriptor f) -> WaitForAscend f -> WaitForDescend f -> [SomeDescriptor f] -> Set (SomeDescriptor f) -- If we've already processed this descriptor then we can skip it go u wa wd (d : rs) | d `Set.member` u = go u wa wd rs -- If we're currently 'Match'ing a character and that character appears in the input text then we can continue - go u wa wd (d@(SomeDescriptor (Descriptor (Slot x a i ds (Ap (Match c) r)) l k xs)) : rs) - | c' : xs' <- xs, c == c' = go (Set.insert d u) wa wd (SomeDescriptor (Descriptor (Slot x a (i + 1) ds (($ ()) <$> r)) l (k + 1) xs') : rs) + go u wa wd (d@(SomeDescriptor (Descriptor (Slot x ds (Ap (L (Match c)) r)) l k xs)) : rs) + | c' : xs' <- xs, c == c' = go (Set.insert d u) wa wd (SomeDescriptor (Descriptor (Slot x (Pa ds (L (Match c))) r) l (k + 1) xs') : rs) -- otherwise we skip this descriptor | otherwise = go u wa wd rs -- If we're descending into a nonterminal then we check if something was already waiting for us to descend. - go u wa wd (d@(SomeDescriptor (Descriptor (Slot x a i ds (Ap (Descend n) next)) l k xs)) : rs) - = go (Set.insert d u) (insertWA n k (\r xs' -> SomeDescriptor (Descriptor (Slot x a (i + 1) (Dep n k r ds) next) l r xs')) wa) wd $ - case lookupWD wd n k of + go u wa wd (d@(SomeDescriptor (Descriptor (Slot x ds (Ap (R nt) next)) l k xs)) : rs) + = go (Set.insert d u) (insertWA nt k (\r xs' -> SomeDescriptor (Descriptor (Slot x (Pa ds (R nt)) next) l r xs')) wa) wd $ + case lookupWD wd nt k of -- If nothing was waiting for this then we start descending by adding initial descriptors the nonterminal we are descending into. - [] -> [ SomeDescriptor (Descriptor (Slot n a' 0 Self acts) k k xs) | (a', acts) <- zip [0..] (lookupG g n) ] ++ rs + [] -> [ SomeDescriptor (Descriptor (Slot nt Erup acts) k k xs) | acts <- alternatives (lookupG g nt) ] ++ rs -- If something was waiting for us then we can take over where they left off. - _ -> [ SomeDescriptor (Descriptor (Slot x a (i + 1) (Dep n k r ds) next) l r xs') | (r, xs') <- lookupWD wd n k ] ++ rs + _ -> [ SomeDescriptor (Descriptor (Slot x (Pa ds (R nt)) next) l r xs') | (r, xs') <- lookupWD wd nt k ] ++ rs -- If we have reached the end of a descriptor then we ascend. - go u wa wd (d@(SomeDescriptor (Descriptor (Slot x _ _ _ (Pure _)) k r xs)) : rs) + go u wa wd (d@(SomeDescriptor (Descriptor (Slot x _ (Pure _)) k r xs)) : rs) = go (Set.insert d u) wa (insertWD x k (r, xs) wd) ([ f r xs | f <- lookupWA wa x k ] ++ rs) -- If we have no more work then parsing is done! go u _ _ [] = u -decode :: forall n a. (Show n, Ord n) => Set (SomeDescriptor n) -> Name n a -> Int -> Int -> [a] -decode ds0 = lookupM where - m :: Map (n, Int, Int) [Any] - m = Map.fromListWith (++) - [ ((x, l, r), map unsafeCoerce (go ds [a])) - | SomeDescriptor (Descriptor (Slot (Name x) _ _ ds (Pure a)) l r _) <- Set.toList ds0 - ] - - lookupM :: forall c. Name n c -> Int -> Int -> [c] - lookupM (Name n) l r = maybe [] (map unsafeCoerce) (m Map.!? (n, l, r)) - - go :: forall b c. Deps n b c -> [c] -> [b] - go Self x = x - go (Dep n l r xs) fs = go xs $ fs <*> lookupM n l r \ No newline at end of file +-- decode :: forall a f. Set (SomeDescriptor f) -> f a -> Int -> Int -> [a] +-- decode ds0 = lookupM where +-- m :: Map (n, Int, Int) [Any] +-- m = Map.fromListWith (++) +-- [ ((x, l, r), map unsafeCoerce (go ds [a])) +-- | SomeDescriptor (Descriptor (Slot nt _ _ ds (Pure a)) l r _) <- Set.toList ds0 +-- ] +-- +-- lookupM :: forall c. f c -> Int -> Int -> [c] +-- lookupM nt l r = maybe [] (map unsafeCoerce) (m Map.!? (n, l, r)) +-- +-- go :: forall b c. Deps f b c -> [c] -> [b] +-- go Self x = x +-- go (Dep n l r xs) fs = go xs $ fs <*> lookupM n l r + +data End a deriving (Show) +instance OrdF End where + compareF x _ = case x of + +data Number a where + Number :: Number Int +deriving instance Show (Number a) +instance OrdF Number where + compareF Number Number = EQ + +number :: Number < f => Alt f Int +number = send Number + +data Digit a where + Digit :: Digit Int +deriving instance Show (Digit a) +instance OrdF Digit where + compareF Digit Digit = EQ + +digit :: Digit < f => Alt f Int +digit = send Digit + +data Expr a where + Expr :: Expr Int +deriving instance Show (Expr a) + +instance OrdF Expr where + compareF Expr Expr = EQ + +expr :: Expr < f => Alt f Int +expr = send Expr + +onR :: (g a -> h a) -> (f + g) a -> (f + h) a +onR f (R x) = R (f x) +onR _ (L x) = L x + +infixr + +infixr <||> + +(<||>) :: G f h -> G g h -> G (f + g) h +G f <||> G g = G $ \case + L y -> f y + R y -> g y + +type Gram f = G f f + +gram :: Gram (Expr + Number + Digit + End) +gram = G (\Expr -> (+) <$> expr <* match '+' <*> expr <|> number) + <||> G (\Number -> (\x y -> 10 * x + y) <$> number <*> digit <|> digit) + <||> G (\Digit -> asum [x <$ match (intToDigit x) | x <- [0..9]]) + <||> G (\case) + +ex1 :: Set (SomeDescriptor (Expr + Number + Digit + End)) +ex1 = parse gram Expr "123+456" + +-- >>> ex1 +-- fromList [SomeDescriptor (Descriptor (Slot (L Expr) (Erup) ((Ap (R (L Expr)) ((Ap (L (Match '+')) ((Ap (R (L Expr)) (Pure)))))))) 0 0 "123+456"),SomeDescriptor (Descriptor (Slot (L Expr) (Erup) ((Ap (R (L Expr)) ((Ap (L (Match '+')) ((Ap (R (L Expr)) (Pure)))))))) 4 4 "456"),SomeDescriptor (Descriptor (Slot (L Expr) (Erup) ((Ap (R (R (L Number))) (Pure)))) 0 0 "123+456"),SomeDescriptor (Descriptor (Slot (L Expr) (Erup) ((Ap (R (R (L Number))) (Pure)))) 4 4 "456"),SomeDescriptor (Descriptor (Slot (L Expr) (Pa (Pa Erup (R (L Expr))) (L (Match '+'))) ((Ap (R (L Expr)) (Pure)))) 0 4 "456"),SomeDescriptor (Descriptor (Slot (L Expr) (Pa Erup (R (L Expr))) ((Ap (L (Match '+')) ((Ap (R (L Expr)) (Pure)))))) 0 3 "+456"),SomeDescriptor (Descriptor (Slot (L Expr) (Pa (Pa (Pa Erup (R (L Expr))) (L (Match '+'))) (R (L Expr))) (Pure)) 0 5 "56"),SomeDescriptor (Descriptor (Slot (L Expr) (Pa (Pa (Pa Erup (R (L Expr))) (L (Match '+'))) (R (L Expr))) (Pure)) 0 6 "6"),SomeDescriptor (Descriptor (Slot (L Expr) (Pa (Pa (Pa Erup (R (L Expr))) (L (Match '+'))) (R (L Expr))) (Pure)) 0 7 ""),SomeDescriptor (Descriptor (Slot (L Expr) (Pa Erup (R (R (L Number)))) (Pure)) 0 1 "23+456"),SomeDescriptor (Descriptor (Slot (L Expr) (Pa Erup (R (R (L Number)))) (Pure)) 0 2 "3+456"),SomeDescriptor (Descriptor (Slot (L Expr) (Pa Erup (R (R (L Number)))) (Pure)) 0 3 "+456"),SomeDescriptor (Descriptor (Slot (L Expr) (Pa Erup (R (R (L Number)))) (Pure)) 4 5 "56"),SomeDescriptor (Descriptor (Slot (L Expr) (Pa Erup (R (R (L Number)))) (Pure)) 4 6 "6"),SomeDescriptor (Descriptor (Slot (L Expr) (Pa Erup (R (R (L Number)))) (Pure)) 4 7 ""),SomeDescriptor (Descriptor (Slot (R (L Number)) (Erup) ((Ap (R (R (L Number))) ((Ap (R (R (R (L Digit)))) (Pure)))))) 0 0 "123+456"),SomeDescriptor (Descriptor (Slot (R (L Number)) (Erup) ((Ap (R (R (L Number))) ((Ap (R (R (R (L Digit)))) (Pure)))))) 4 4 "456"),SomeDescriptor (Descriptor (Slot (R (L Number)) (Erup) ((Ap (R (R (R (L Digit)))) (Pure)))) 0 0 "123+456"),SomeDescriptor (Descriptor (Slot (R (L Number)) (Erup) ((Ap (R (R (R (L Digit)))) (Pure)))) 4 4 "456"),SomeDescriptor (Descriptor (Slot (R (L Number)) (Pa Erup (R (R (L Number)))) ((Ap (R (R (R (L Digit)))) (Pure)))) 0 1 "23+456"),SomeDescriptor (Descriptor (Slot (R (L Number)) (Pa Erup (R (R (L Number)))) ((Ap (R (R (R (L Digit)))) (Pure)))) 0 2 "3+456"),SomeDescriptor (Descriptor (Slot (R (L Number)) (Pa Erup (R (R (L Number)))) ((Ap (R (R (R (L Digit)))) (Pure)))) 0 3 "+456"),SomeDescriptor (Descriptor (Slot (R (L Number)) (Pa Erup (R (R (L Number)))) ((Ap (R (R (R (L Digit)))) (Pure)))) 4 5 "56"),SomeDescriptor (Descriptor (Slot (R (L Number)) (Pa Erup (R (R (L Number)))) ((Ap (R (R (R (L Digit)))) (Pure)))) 4 6 "6"),SomeDescriptor (Descriptor (Slot (R (L Number)) (Pa Erup (R (R (L Number)))) ((Ap (R (R (R (L Digit)))) (Pure)))) 4 7 ""),SomeDescriptor (Descriptor (Slot (R (L Number)) (Pa Erup (R (R (R (L Digit))))) (Pure)) 0 1 "23+456"),SomeDescriptor (Descriptor (Slot (R (L Number)) (Pa Erup (R (R (R (L Digit))))) (Pure)) 4 5 "56"),SomeDescriptor (Descriptor (Slot (R (L Number)) (Pa (Pa Erup (R (R (L Number)))) (R (R (R (L Digit))))) (Pure)) 0 2 "3+456"),SomeDescriptor (Descriptor (Slot (R (L Number)) (Pa (Pa Erup (R (R (L Number)))) (R (R (R (L Digit))))) (Pure)) 0 3 "+456"),SomeDescriptor (Descriptor (Slot (R (L Number)) (Pa (Pa Erup (R (R (L Number)))) (R (R (R (L Digit))))) (Pure)) 4 6 "6"),SomeDescriptor (Descriptor (Slot (R (L Number)) (Pa (Pa Erup (R (R (L Number)))) (R (R (R (L Digit))))) (Pure)) 4 7 ""),SomeDescriptor (Descriptor (Slot (R (R (L Digit))) (Erup) ((Ap (L (Match '1')) (Pure)))) 0 0 "123+456"),SomeDescriptor (Descriptor (Slot (R (R (L Digit))) (Erup) ((Ap (L (Match '2')) (Pure)))) 1 1 "23+456"),SomeDescriptor (Descriptor (Slot (R (R (L Digit))) (Erup) ((Ap (L (Match '3')) (Pure)))) 2 2 "3+456"),SomeDescriptor (Descriptor (Slot (R (R (L Digit))) (Erup) ((Ap (L (Match '4')) (Pure)))) 4 4 "456"),SomeDescriptor (Descriptor (Slot (R (R (L Digit))) (Erup) ((Ap (L (Match '5')) (Pure)))) 5 5 "56"),SomeDescriptor (Descriptor (Slot (R (R (L Digit))) (Erup) ((Ap (L (Match '6')) (Pure)))) 6 6 "6"),SomeDescriptor (Descriptor (Slot (R (R (L Digit))) (Pa Erup (L (Match '1'))) (Pure)) 0 1 "23+456"),SomeDescriptor (Descriptor (Slot (R (R (L Digit))) (Pa Erup (L (Match '2'))) (Pure)) 1 2 "3+456"),SomeDescriptor (Descriptor (Slot (R (R (L Digit))) (Pa Erup (L (Match '3'))) (Pure)) 2 3 "+456"),SomeDescriptor (Descriptor (Slot (R (R (L Digit))) (Pa Erup (L (Match '4'))) (Pure)) 4 5 "56"),SomeDescriptor (Descriptor (Slot (R (R (L Digit))) (Pa Erup (L (Match '5'))) (Pure)) 5 6 "6"),SomeDescriptor (Descriptor (Slot (R (R (L Digit))) (Pa Erup (L (Match '6'))) (Pure)) 6 7 "")]