diff --git a/examples/regex_matcher.mil b/examples/regex_matcher.mil new file mode 100644 index 0000000..372d3b5 --- /dev/null +++ b/examples/regex_matcher.mil @@ -0,0 +1,58 @@ +datatype regex { + Empty, + Lit of string, + Cat of (regex, regex), + Alt of (regex, regex), + Star of regex +} + +datatype 'a list { + Empty, + Cons of ('a, 'a list) +} + +# Check if a regex matches the null string +typecheck nullable? : regex -> bool +def nullable? = false + | nullable? = string_null? s + | nullable? = logical_and (nullable? l) (nullable? r) + | nullable? = logical_or (nullable? l) (nullable? r) + | nullable? = true + +# Check if a regex represents the empty language +typecheck unsatisfiable? : regex -> bool +def unsatisfiable? = true + | unsatisfiable? = false + | unsatisfiable? = logical_or (unsatisfiable? l) (unsatisfiable? r) + | unsatisfiable? = logical_and (unsatisfiable? l) (unsatisfiable? r) + | unsatisfiable? = false + +# Regex derivative with respect to a character +typecheck derive : char -> regex -> regex +def derive c = Empty + | derive c = + match string_null? s { + case true -> Empty + case false -> + match equal (string_head s) c { + case true -> Lit (string_tail s) + case false -> Empty + } + } + + | derive c = Alt (derive c l) (derive c r) + | derive c = Cat (derive c r) (Star r) + | derive c = + match nullable? l { + case true -> Alt (Cat (derive c l) r) (derive c r) + case false -> Cat (derive c l) r + } + +# Let us leverage the regex derivative algorithm to define a regex matcher +typecheck match_regex : string -> regex -> bool +def match_regex str regex = + let + def match_regex1 r = nullable? regex + | match_regex1 r = match_regex1 cs (derive c cs) + in + match_regex1 (string_to_list str) regex