(*
*) exception Error of string; fun error s = (print s; raise (Error s)); datatype Re = empty of int | simple of string * int | concat of Re * Re | closure of Re | union of Re * Re; datatype token = Done | Bar | Star | Hash | Leftparen | Rightparen | Single of string; fun tok2str Done = "Done" | tok2str Bar = "|" | tok2str Star = "*" | tok2str Hash = "#" | tok2str Leftparen = "(" | tok2str Rightparen = ")" | tok2str (Single c) = c; val lookahead = ref Done; val input = ref [Done]; val location = ref 0; fun nextloc () = (location := (!location) + 1; !location) (* simple lexical analyser *) fun lexan s = let fun help [] = [] | help (#"|" :: xs) = Bar :: help xs | help (#"*" :: xs) = Star :: help xs | help (#"#" :: xs) = Hash :: help xs | help (#"(" :: xs) = Leftparen :: help xs | help (#")" :: xs) = Rightparen :: help xs | help (x :: xs) = Single (String.implode [x]) :: help xs in help (String.explode s) end; fun init s = (location := 0; input := lexan s; lookahead := hd(!input); input := tl(!input)); fun match t = if (!lookahead) = t then (if null(!input) then lookahead := Done else (lookahead := hd(!input) ; input := tl(!input))) else error ("looking for: "^(tok2str t)^ " found: "^(tok2str (!lookahead))); fun Alt () = let val x = Concat () val y = moreAlt () in case y of NONE => x | SOME z => union(x,z) end and moreAlt () = case (!lookahead) of Bar => let val _ = match Bar val x = Alt() val y = moreAlt () in case y of NONE => SOME x | (SOME z) => SOME(union(x,z)) end | _ => NONE and Concat () = let val x = Closure () val y = moreConcat () in case y of NONE => x | SOME z => concat(x,z) end and Closure () = let val x = Simple() in case !lookahead of Star => (match Star; closure x) | other => x end and moreConcat () = case (!lookahead) of (Single _ | Leftparen | Hash) => let val x = Closure() val y = moreConcat() in case y of NONE => SOME x | SOME z => SOME(concat(x,z)) end | _ => NONE and Simple () = case !lookahead of Single c => let val _ = match (Single c) val n = nextloc() in simple(c,n) end | Leftparen => let val _ = match Leftparen val x = Alt(); val _ = match Rightparen in x end | Hash => let val _ = match Hash val n = nextloc() in empty n end | x => error ("In Simple no match: "^(tok2str x)); fun parse s = let val _ = init s val ans = Alt() val _ = match Done in ans end; (**)