-----------------------------------------------------------------------------
-- |
-- Module : SymTab
-- Copyright : 2000-2004 Malcolm Wallace
-- Licence : LGPL
--
-- Maintainer : Malcolm Wallace <[email protected]>
-- Stability : Stable
-- Portability : All
--
-- Symbol Table, based on index trees using a hash on the key.
-- Keys are always Strings. Stored values can be any type.
-----------------------------------------------------------------------------
module Language.Preprocessor.Cpphs.SymTab
( SymTab
, emptyST
, insertST
, deleteST
, lookupST
, definedST
, IndTree
) where
-- | Symbol Table. Stored values are polymorphic, but the keys are
-- always strings.
type SymTab v = IndTree [(String,v)]
emptyST :: SymTab v
insertST :: (String,v) -> SymTab v -> SymTab v
deleteST :: String -> SymTab v -> SymTab v
lookupST :: String -> SymTab v -> Maybe v
definedST :: String -> SymTab v -> Bool
emptyST = itgen maxHash []
insertST (s,v) ss = itiap (hash s) ((s,v):) ss id
deleteST s ss = itiap (hash s) (filter ((/=s).fst)) ss id
lookupST s ss = let vs = filter ((==s).fst) ((itind (hash s)) ss)
in if null vs then Nothing
else (Just . snd . head) vs
definedST s ss = let vs = filter ((==s).fst) ((itind (hash s)) ss)
in (not . null) vs
----
-- | Index Trees (storing indexes at nodes).
data IndTree t = Leaf t | Fork Int (IndTree t) (IndTree t)
deriving Show
itgen :: Int -> a -> IndTree a
itgen 1 x = Leaf x
itgen n x =
let n' = n `div` 2
in Fork n' (itgen n' x) (itgen (n-n') x)
itiap :: --Eval a =>
Int -> (a->a) -> IndTree a -> (IndTree a -> b) -> b
itiap _ f (Leaf x) k = let fx = f x in {-seq fx-} (k (Leaf fx))
itiap i f (Fork n lt rt) k =
if i<n then
itiap i f lt $ \lt' -> k (Fork n lt' rt)
else itiap (i-n) f rt $ \rt' -> k (Fork n lt rt')
itind :: Int -> IndTree a -> a
itind _ (Leaf x) = x
itind i (Fork n lt rt) = if i<n then itind i lt else itind (i-n) rt
----
-- Hash values
maxHash :: Int -- should be prime
maxHash = 101
class Hashable a where
hashWithMax :: Int -> a -> Int
hash :: a -> Int
hash = hashWithMax maxHash
instance Enum a => Hashable [a] where
hashWithMax m = h 0
where h a [] = a
h a (c:cs) = h ((17*(fromEnum c)+19*a)`rem`m) cs
----
|