>-- | regular expression patterns>dataPat=PVarInt[Range]Pat-- ^ variable pattern >|PERE-- ^ pattern without binder>|PPairPatPat-- ^ pair pattern>|PChoicePatPatGFlag-- ^ choice pattern >|PStarPatGFlag-- ^ star pattern >|PPlusPatPat-- ^ plus pattern, it is used internally to indicate that it is unrolled from a PStar>|PEmptyPat-- ^ empty pattern, it is used intermally to indicate that mkEmpty function has been applied.

>{-| The Eq instance for Pat data type
> NOTE: We ignore the 'consumed word' when comparing patterns
> (ie we only compare the pattern structure).
> Essential for later comparisons among patterns. -}

>instanceEqPatwhere>(==)(PVarx1_p1)(PVarx2_p2)=(x1==x2)&&(p1==p2)>(==)(PPairp1p2)(PPairp1'p2')=(p1==p1')&&(p2==p2')>(==)(PChoicep1p2g1)(PChoicep1'p2'g2)=(g1==g2)&&(p2==p2')&&(p1==p1')-- more efficient, because choices are constructed in left-nested>(==)(PPlusp1p2)(PPlusp1'p2')=(p1==p1')&&(p2==p2')>(==)(PStarp1g1)(PStarp2g2)=(g1==g2)&&(p1==p2)>(==)(PEr1)(PEr2)=r1==r2>(==)__=False>

>{-| function 'pdPat' computes the partial derivatives of a pattern w.r.t. a letter.
> Integrating non-greedy operator with PStar
> For p*, we need to unroll it into a special construct
> say PPlus p' p* where p' \in p/l.
> When we push another label, say l' to PPlus p' p*, and
> p' is emptiable, naively, we would do
> [ PPlus p'' p* | p'' <- p' / l ] ++ [ PPlus (mkE p') (PPlus p''' p*) | (PPlus p''' p*) <- p*/l ]
> Now the problem here is the shape of the pdpat are infinite, which
> breaks the requirement of getting a compilation scheme.
> The fix here is to simplify the second component, by combining the binding, of (mkE p') and p'''
> since they share the same set of variables.
> [ PPlus p'' p* | p'' <- p' / l ] ++ [ PPlus p4 p* | (PPlus p''' p*) <- p*/l ]
> where p4 = combineBinding (mkE p') p'''
> For pdPat0 approach, we do not need to do this explicitly, we simply drop
> (mkE p') even in the PPair case. see the definitely of pdPat0 below
> -}>pdPat::Pat->Letter->[Pat]>pdPat(PVarxwp)(l,idx)=>letpds=pdPatp(l,idx)>inifnullpdsthen[]>elsecasewof>[]->[PVarx[(rangeidxidx)]pd|pd<-pds]>(rs_@((Rangebe):rs))-- ranges are stored in the reversed manner, the first pair the right most segment>|idx==(e+1)->-- it is consecutive>[PVarx((rangebidx):rs)pd|pd<-pds]>|otherwise->-- it is NOT consecutive>[PVarx((rangeidxidx):rs_)pd|pd<-pds]>pdPat(PEr)(l,idx)=letpds=partDerivrl>inifnullpdsthen[]>else[PE$resToREpds]>{-| The non-greedy operator has impact to a sequence pattern if the
> first sub pattern is non-greedy. We simply swap the order of the
> 'choices' in the resulting pds. -}>pdPat(PPairp1p2)l=>if(posEpsilon(stripp1))>thenifisGreedyp1>thennub([PPairp1'p2|p1'<-pdPatp1l]++>[PPair(mkEmpPatp1)p2'|p2'<-pdPatp2l])>elsenub([PPair(mkEmpPatp1)p2'|p2'<-pdPatp2l]++[PPairp1'p2|p1'<-pdPatp1l])>else[PPairp1'p2|p1'<-pdPatp1l]>{-| Integrating non-greedy operator with pstar requires more cares.
> We have two questions to consider.
> 1) When we unfold p*, do we need to take the non-greediness in p into consideration?
> The answer is no.
> What happens is that when we unfold p* into p and p*, if we were considering p is non-greedy and apply pdpat to p*
> again, i.e. mkE(p),p*/l we will run into non-terminating problem. This seems to be bug with python re library. -}>pdPat(PStarpg)l=letpds=pdPatpl>in[PPluspd(PStarpg)|pd<-pds]>{-| 2) After we unfold p* and 'advance' to (PPlus p' p*) say p' \in p / l for some l
> we are in the position of 'pushing' another label l' into (PPlus p' p*).
> Shall we swap the order of the alternatives when p' is non-greedy?
> Why not? This seems harmless since we have already made some progress by pushing l into p*. -}>pdPat(PPlusp1p2@(PStar__))l-- p2 must be pStar>|posEpsilon(stripp1)=>ifisGreedyp1>then[PPlusp3p2|p3<-pdPatp1l]++[PPlusp3p2'|(PPlusp1'p2')<-pdPatp2l,letp3=p1'`getBindingsFrom`p1]>else[PPlusp3p2'|(PPlusp1'p2')<-pdPatp2l,letp3=p1'`getBindingsFrom`p1]++[PPlusp3p2|p3<-pdPatp1l]>|otherwise=[PPlusp3p2|p3<-pdPatp1l]>pdPat(PChoicep1p2g)l=>nub((pdPatp1l)++(pdPatp2l))-- nub doesn't seem to be essential>pdPatpl=error((showp)++(showl))

>-- | function 'getBindingsFrom' transfer bindings from p2 to p1>getBindingsFrom::Pat-- ^ the source of the >->Pat->Pat>getBindingsFromp1p2=letb=toBinderp2>inassignp1b>whereassign::Pat->Binder->Pat>assign(PVarxwp)b=>caseIM.lookupxbof>Nothing->letp'=assignpbinPVarxwp'>Justrs->let>p'=assignpb>inPVarx(w++rs)p'>assign(PEr)_=PEr>assign(PPlusp1p2)b=PPlus(assignp1b)p2-- we don't need to care about p2 since it is a p*>assign(PPairp1p2)b=PPair(assignp1b)(assignp2b)>assign(PChoicep1p2g)b=PChoice(assignp1b)(assignp2b)g