module Text.GrammarCombinators.Transform.CombineEpsilons (
combineEpsilons,
combineEpsilonsE
) where
import Text.GrammarCombinators.Base
data CombineEpsilonsRule p (phi :: * -> *) (r :: * -> *) t v where
CERule :: (v' -> v) -> p v' -> CombineEpsilonsRule p phi r t v
CEEpsRule :: v -> CombineEpsilonsRule p phi r t v
instance (ProductionRule p, EpsProductionRule p) =>
ProductionRule (CombineEpsilonsRule p phi r t) where
endOfInput = CERule id endOfInput
(CEEpsRule va) >>> (CEEpsRule vb) = CEEpsRule $ va vb
(CEEpsRule va) >>> (CERule fb rb) = CERule (va . fb) rb
(CERule fa ra) >>> (CEEpsRule vb) = CERule (flip ($) vb . fa) ra
(CERule fa ra) >>> (CERule fb rb) = CERule (uncurry fa) ((\va vb -> (va, fb vb)) $>> ra >>> rb)
ra ||| rb = CERule id $ runCERule ra ||| runCERule rb
die = CERule id die
instance (EpsProductionRule p) => EpsProductionRule (CombineEpsilonsRule p phi r t) where
epsilon = CEEpsRule
instance (EpsProductionRule p) => LiftableProductionRule (CombineEpsilonsRule p phi r t) where
epsilonL v _ = CEEpsRule v
instance (TokenProductionRule p t) =>
TokenProductionRule (CombineEpsilonsRule p phi r t) t where
token = CERule id . token
anyToken = CERule id anyToken
instance (RecProductionRule p phi r) =>
RecProductionRule (CombineEpsilonsRule p phi r t) phi r where
ref = CERule id . ref
instance (EpsProductionRule p, LoopProductionRule p phi r) =>
LoopProductionRule (CombineEpsilonsRule p phi r t) phi r where
manyRef = CERule id . manyRef
many1Ref = CERule id . many1Ref
runCERule :: (ProductionRule p, EpsProductionRule p) =>
CombineEpsilonsRule p phi r t v -> p v
runCERule (CERule f r) = f $>> r
runCERule (CEEpsRule v) = epsilon v
combineEpsilons :: forall phi t r rr.
GContextFreeGrammar phi t r rr ->
GContextFreeGrammar phi t r rr
combineEpsilons gram idx = runCERule $ gram idx
combineEpsilonsE :: forall phi t r rr.
GExtendedContextFreeGrammar phi t r rr ->
GExtendedContextFreeGrammar phi t r rr
combineEpsilonsE gram idx = runCERule $ gram idx