{- Haskell version of ... ! Lisp-like functions which allow easy hand translation from Lisp to Hope+ ! Started by Tony Kitto on 30th March 1988 ! Changes Log ! 18-05-88 added LUT functions and regularized assoc ! 25-05-88 added Lisptochar and DisplayLUT Haskell version:: 23-06-93 JSM initial version -} module Lisplikefns ( Token, Lisplist(..), LUT, mkLisplist, strToToken, tv, atom, car, cdr, cadr, caddr, cadddr, assoc, newLUT, addtoLUT, getLUT ) where type Token = String -- "(" or ")" or "Lisp Symbol" data Lisplist = Nil | Atom Token | Cons (Lisplist, Lisplist) deriving (Eq,Show{-was:Text-}) -- These functions create a Lisplist from a list of characters mkLisplist :: [Token] -> Lisplist mkLisplist ("(":t) = if r /= [] then Nil else l where (r, l) = sublist t mkLisplist _ = Nil sublist :: [Token] -> ([Token], Lisplist) sublist [] = ([], Nil) sublist ("(":t) = (r2, Cons (l1, l2)) where (r1, l1) = sublist t (r2, l2) = sublist r1 sublist (")":t) = (t, Nil) sublist (h:t) = (r, Cons (Atom h, l)) where (r, l) = sublist t strToToken :: String -> [Token] strToToken "" = [] strToToken s = a : strToToken b where (a, b) = getToken s getToken :: String -> (Token, String) getToken "" = ([], "") getToken (h:t) | h == ' ' = getToken t | h == '(' || h == ')' = ([h], t) | otherwise = (h:a, b) where (a, b) = restOfToken t restOfToken :: String -> (Token, String) restOfToken "" = ([], "") restOfToken (h:t) | h == '(' || h == ')' || h == ' ' = ([], h:t) | otherwise = (h:a, b) where (a, b) = restOfToken t tv :: Lisplist -> Token tv (Atom x) = x tv _ = error "Not an atom" -- These functions provide simple Lisplist operations atom :: Lisplist -> Bool atom (Atom x) = True atom _ = False car :: Lisplist -> Lisplist car (Cons (x, y)) = x car _ = Nil cdr :: Lisplist -> Lisplist cdr (Cons (x, y)) = y cdr _ = Nil cadr :: Lisplist -> Lisplist cadr = car . cdr caddr :: Lisplist -> Lisplist caddr = car . cdr . cdr cadddr :: Lisplist -> Lisplist cadddr = car . cdr . cdr . cdr assoc :: (Lisplist, Lisplist) -> Lisplist assoc (term, Cons (x, y)) = case x of Cons (head@(Atom key), rest) | term == head -> x | otherwise -> assoc (term, y) _ -> Nil assoc (_, _) = Nil {- These functions provide more complex operations based on a Lisp-like functionality, they do not exactly match the equivalent Lisp functions -} type LUTentry = (Token, [Lisplist] ) data LUT = Empty | Node (LUT, LUTentry, LUT) deriving (Show{-was:Text-}) newLUT :: LUT newLUT = Empty addtoLUT :: (Token, Lisplist, LUT) -> LUT addtoLUT (k, l, Empty) = Node (Empty, (k, [l]), Empty) addtoLUT (k, l, Node (left, (k1, kl), right)) | k == k1 = Node (left, (k1, l:kl), right) | k < k1 = Node (addtoLUT (k, l, left), (k1, kl), right) | otherwise = Node (left, (k1, kl), addtoLUT (k, l, right)) getLUT :: (Token, LUT) -> [Lisplist] getLUT (t, Empty) = [] getLUT (t, Node (left, (k, kl), right)) | t == k = kl | t < k = getLUT (t, left) | otherwise = getLUT (t, right)