import RegexDeriv.Std.Linter.DetectClassical import RegexDeriv.Std.Decidable import RegexDeriv.Regex.Language namespace IndexedRegex open List inductive Regex (α: Type): (List α -> Prop) -> Type where | emptyset : Regex α Language.emptyset | emptystr : Regex α Language.emptystr | pred : {p: α -> Prop} → (dp: DecidablePred p) → Regex α (Language.pred p) | or : Regex α x → Regex α y → Regex α (Language.or x y) | concat : Regex α x → Regex α y → Regex α (Language.concat x y) | star : Regex α x → Regex α (Language.star x) def null (r: Regex α l): Decidable (Language.null l) := match r with | Regex.emptyset => Decidable.isFalse (Language.not_null_if_emptyset) | Regex.emptystr => Decidable.isTrue (Language.null_if_emptystr) | Regex.pred _ => Decidable.isFalse (Language.not_null_if_pred) | Regex.or x y => Decidable.map (symm Language.null_iff_or) (Decidable.or (null x) (null y)) | Regex.concat x y => Decidable.map (symm Language.null_iff_concat) (Decidable.and (null x) (null y)) | Regex.star _ => Decidable.isTrue (Language.null_if_star) def iso {P Q: Language.Lang α} (ifflang: Q = P) (r: @Regex α P): @Regex α Q := by rw [ifflang] exact r def onlyif {cond: Prop} (dcond: Decidable cond) (r: Regex α l): Regex α (Language.onlyif cond l) := match dcond with | isTrue h => iso (Language.onlyif_true h) r | isFalse h => iso (Language.onlyif_false h) Regex.emptyset def derive (r: Regex α l) (a: α): Regex α (Language.derive l a) := match r with | Regex.emptyset => Regex.emptyset | Regex.emptystr => iso Language.derive_emptystr Regex.emptyset | Regex.pred p => iso Language.derive_pred (onlyif (p a) Regex.emptystr) | Regex.or x y => iso Language.derive_or (Regex.or (derive x a) (derive y a)) | Regex.concat x y => iso Language.derive_concat (Regex.or (Regex.concat (derive x a) y) (onlyif (null x) (derive y a)) ) | Regex.star x => iso Language.derive_star (Regex.concat (derive x a) (Regex.star x)) def denote (_: @Regex α l): Language.Lang α := l -- decidableDenote shows that the derivative algorithm is decidable def decidableDenote (r: @Regex α l): DecidablePred l := fun w => match w with | [] => null r | (a :: w) => decidableDenote (derive r a) w