(*
*)
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;
(* *)