(* File: GRSCN.ML *) (* Project: GR *) datatype token = Key of string | Name of string ; exception ScanError of string; fun is_uppercase c = c >= "A" andalso c <= "Z"; fun is_lowercase c = c >= "a" andalso c <= "z"; fun is_letter c = is_uppercase c orelse is_lowercase c; fun is_digit c = c >= "0" andalso c <= "9"; fun read_line s = let fun loop cs = let val c = input(s,1) in if end_of_stream s then rev cs else if c = "\n" then rev ("\n"::cs) else loop (c::cs) end in loop [] end; fun is_blank c = c = " " orelse c = "\n" orelse c = "\t"; fun read_and_scan file_name = let val s = open_in file_name fun scan_token [] = if end_of_stream s then (Key "eof", []) else scan_token (read_line s) | scan_token ("/"::"*"::rest) = scan_comment rest | scan_token ("%"::"%"::rest) = (Key "%%", rest) | scan_token ("%"::"t"::"o"::"k"::"e"::"n"::rest) = (Key "%token", rest) | scan_token (c::rest) = if is_blank c then scan_token rest else if is_letter c then scan_id_rest (c, rest) else (Key c, rest) and scan_comment ("*"::"/"::rest) = scan_token rest | scan_comment [] = if end_of_stream s then raise ScanError "EOF in a comment" else scan_comment (read_line s) | scan_comment (c::rest) = scan_comment rest and scan_id_rest (ide, rest as c::rest') = if (is_letter c) orelse (is_digit c) orelse (c = "_") then scan_id_rest (ide^c, rest') else (Name ide, rest) fun loop (line, tks) = let val (tk, line') = scan_token line in case tk of Key "eof" => rev (tk::tks) | _ => loop (line', tk::tks) end val tks = loop ([], []) val () = close_in s in tks end;