functor Symtab(H: HASHTABLE): SYMTAB = struct type 'token t = ((string * 'token option * 'token option) option Array.array * int H.t) ref type 'token auxInfo = 'token option * 'token option exception UnknownId fun init () = let val log = 20 val h = H.createLog log in ref $ (Array.array (H.size h, NONE), h) end fun insert symtab idStr cl = let val (array, table) = !symtab val id = H.taken table val prev = H.insertIfNew table idStr id fun update id cl arg = let val (ppc, kw) = cl arg in Array.update (array, id, SOME (idStr, ppc, kw)) end in case prev of NONE => (update id cl (NONE, NONE); id) | SOME id => case Array.sub (array, id) of NONE => raise Unreachable | SOME (_, ppc, kw) => (update id cl (ppc, kw); id) end fun getId symtab idStr = let val (array, table) = !symtab val id = H.taken table val prev = H.insertIfNew table idStr id in case prev of NONE => (Array.update (array, id, SOME (idStr, NONE, NONE)); id) | SOME id => id end fun getAuxInfo symtab id = let val (array, _) = !symtab in case Array.sub (array, id) of NONE => raise UnknownId | SOME (_, ppc, kw) => (ppc, kw) end fun getStr symtab id = let val (array, _) = !symtab in case Array.sub (array, id) of NONE => raise UnknownId | SOME (str, _, _) => str end fun isPpcDir symtab id = case getAuxInfo symtab id of (SOME ppc, _) => SOME ppc | _ => NONE fun isKw symtab id = case getAuxInfo symtab id of (_, SOME kw) => SOME kw | _ => NONE fun print symtab = let val (array, _) = !symtab fun print idx = case Array.sub (array, idx) of NONE => printf `"\n" % | SOME (str, _, _) => (printf I idx `": " `str `"\n" %; print (idx + 1)) in printf `"Symbol table:\n" %; print 0 end end