Skip to content

Instantly share code, notes, and snippets.

@zehnpaard
Created April 8, 2018 19:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zehnpaard/de0c4071b49d4c850641c48c67289bea to your computer and use it in GitHub Desktop.
Save zehnpaard/de0c4071b49d4c850641c48c67289bea to your computer and use it in GitHub Desktop.
Ultra-Minimal Lisp REPL written in Haskell - Atom only
module Main where
import Text.ParserCombinators.Parsec
import System.Environment
import System.IO
import Control.Monad
-- Lisp Value Data Type
data LispVal = Atom String
instance Show LispVal where show = showVal
showVal :: LispVal -> String
showVal (Atom name) = name
-- Parsers
readExpr :: String -> LispVal
readExpr input = case (parse parseExpr "lisp" input) of
Left err -> Atom $ "No match: " ++ show err
Right val -> val
parseExpr :: Parser LispVal
parseExpr = parseAtom
symbol :: Parser Char
symbol = oneOf "!#$%&|*+-/:<=>?@^_~"
parseAtom :: Parser LispVal
parseAtom = do {
first <- (letter <|> symbol);
rest <- many (letter <|> digit <|> symbol);
return $ Atom (first:rest);
}
-- Evaluator
eval :: LispVal -> LispVal
eval lispVal = lispVal
-- Repl
readPrompt :: String -> IO String
readPrompt prompt = putStr prompt >> hFlush stdout >> getLine
readEvalPrint :: String -> IO()
readEvalPrint = putStrLn . show . eval . readExpr
loopUntil :: (a -> Bool) -> IO a -> (a -> IO ()) -> IO ()
loopUntil pred prompt action = do {
x <- prompt;
if pred x
then return ()
else (action x >> loopUntil pred prompt action)
}
-- main
main :: IO ()
main = loopUntil (== "quit") (readPrompt ">> ") readEvalPrint
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment