(*
 *)



(* **************** Sets as lists ****************** *)
(* represent a set of strings  as an ordered list    *)
(* of strings without without duplicates             *)

fun mem (x:string) [] = false
  | mem x (y::ys) =
     if x=y then true
            else mem x ys;

fun setAdd x [] = [x]
  | setAdd x (y::ys) =
      case String.compare (x,y) of
        EQUAL => (y::ys)
      | LESS => x::y::ys
      | GREATER => y :: setAdd x ys;

fun setUnion [] [] = []
  | setUnion [] ys = ys
  | setUnion xs [] = xs
  | setUnion (x::xs) (y::ys) =
     case String.compare (x,y) of
        EQUAL => setUnion xs (y::ys)
      | LESS =>  x:: setUnion xs (y::ys)
      | GREATER => y :: setUnion (x::xs) ys;

fun setConcat [] = []
  | setConcat (x::xs) = setUnion x (setConcat xs);

(* Turn a list into a set, sort and remove duplicates. *)
fun sort [] = []
  | sort (x::xs) = setAdd x (sort xs);

fun remDupFromOrdered [] = []
  | remDupFromOrdered [x:string] = [x]
  | remDupFromOrdered (x::y::zs) =
      if x=y then remDupFromOrdered (y::zs)
             else x:: remDupFromOrdered (y::zs);

fun norm xs = remDupFromOrdered(sort xs);

fun setToString xs =
  let fun help [] = "]\n"
        | help [x] = x ^ "]\n"
        | help (x::xs) = x ^ "," ^ help xs
  in "[" ^ help xs end

(* ********************************************* *)
(* cross product operator *)

fun innerWhile x [] ans = ans
  | innerWhile x (y::ys) ans = innerWhile x ys ((x,y)::ans);

fun outerWhile ys [] ans = ans
  | outerWhile ys (x::xs) ans = outerWhile ys xs (innerWhile x ys ans);

fun cross xs ys = outerWhile ys xs [];


(* ********************************************** *)

datatype RE
  = Empty
  | Union of RE * RE
  | Concat of RE * RE
  | Star of RE
  | C of char;


(* 
*)