theory RegExp imports Main begin datatype 'a rexp = Empty ("<>") | Atom 'a ("\_\" 65) | Alt "('a rexp)" "('a rexp)" (infixr "||" 55) | Conc "('a rexp)" "('a rexp)" (infixr "~~" 60) | Star "('a rexp)" ("\(_)\\<^sup>*" [0]100) definition rep1 :: "'a rexp \ 'a rexp" ("\(_)\\<^sup>+") where "\A\\<^sup>+ \ A ~~ \A\\<^sup>*" definition opt :: "'a rexp \ 'a rexp" ("\(_)\") where "\A\ \ A || <>" value "Star (Conc(Alt (Atom(CHR ''a'')) (Atom(CHR ''b''))) (Atom(CHR ''c'')))" text{* or better equivalently: *} value "\(\CHR ''a''\ || \CHR ''b''\) ~~ \CHR ''c''\\\<^sup>*" section{* Definition of a semantic function: the ``language'' of the regular expression *} text{* In the following, we give a semantics for our regular expressions, which so far have just been a term language (i.e. abstract syntax). The semantics is a ``denotational semantics'', i.e. we give a direct meaning for regular expressions in some universe of ``denotations''. This universe of denotations is in our concrete case: *} type_synonym 'a lang = "'a list set" inductive_set star :: "'a lang \ 'a lang" for A:: "'a lang" where NilI : "[] \ star A" | ConsI : "[| a\A; as \ star A |] ==> a@as \ star A" lemma NilI : "[] \ star A" by(rule NilI) lemma ConsI : "a\A \ as \ star A \ a@as \ star A" apply(rule ConsI) apply(assumption) by(assumption) lemma epsilonExists: "star {[]} = {[]}" apply(rule Set.set_eqI) apply(rule iffI) apply(erule star.induct) apply(auto intro: NilI ) done lemma epsilonAlt: "star {} = {[]}" apply(rule Set.set_eqI) apply(rule iffI) apply(erule star.induct, simp,simp) apply(auto intro: NilI ) done text{* ... and of course, we have the consequence : *} lemma epsilon': "star (star {[]}) = {[]}" by(simp add: epsilonExists) lemma epsilon'': "star (star ((star {[]}))) = {[]}" by(simp add: epsilonExists) text{* Now the denotational semantics for regular expression can be defined on a post-card: *} fun L :: "'a rexp => 'a lang" where L_Emp : "L Empty = {}" |L_Atom: "L (\a\) = {[a]}" |L_Un: "L (el || er) = (L el) \ (L er)" |L_Conc: "L (el ~~ er) = {xs@ys | xs ys. xs \ L el \ ys \ L er}" |L_Star: "L (Star e) = star(L e)" fun L\<^sub>s\<^sub>u\<^sub>b :: "'a::order rexp => 'a lang" where L\<^sub>s\<^sub>u\<^sub>b_Emp : "L\<^sub>s\<^sub>u\<^sub>b Empty = {}" |L\<^sub>s\<^sub>u\<^sub>b_Atom: "L\<^sub>s\<^sub>u\<^sub>b (\a\) = {z . \x. x \ a \ z=[x]}" |L\<^sub>s\<^sub>u\<^sub>b_Un: "L\<^sub>s\<^sub>u\<^sub>b (el || er) = (L\<^sub>s\<^sub>u\<^sub>b el) \ (L\<^sub>s\<^sub>u\<^sub>b er)" |L\<^sub>s\<^sub>u\<^sub>b_Conc: "L\<^sub>s\<^sub>u\<^sub>b (el ~~ er) = {xs@ys | xs ys. xs \ L\<^sub>s\<^sub>u\<^sub>b el \ ys \ L\<^sub>s\<^sub>u\<^sub>b er}" |L\<^sub>s\<^sub>u\<^sub>b_Star: "L\<^sub>s\<^sub>u\<^sub>b (Star e) = star(L\<^sub>s\<^sub>u\<^sub>b e)" schematic_goal WeCompute: "L(Star ((\CHR ''a''\ || \CHR ''b''\) ~~ \CHR ''c''\)) = ?X" by simp thm WeCompute text{* Well, an attempt to evaluate this turns out not to work too well ... *} text{* Now let's reconsider our `obvious lemma' from above, this time by stating that the alternative-operator produces \emph{semantically} equivalent ewpressions. *} lemma alt_commute' : "L((A::'a rexp) || B) = L(B || A)" by auto lemma mt_seq' : "L(Empty ~~ Empty) = {}" by simp lemma eps : "L (Star Empty) = {[]}" by (simp add: epsilonAlt) no_notation Atom ("\_\") end