X-Git-Url: https://git.rmz.io/my-scheme.git/blobdiff_plain/0742b9f77a6fe617f929e21e143e35cd6e3d3ed6..fabc3d8bdaef310b2f18bc53735ad7ee53518822:/app/Main.hs diff --git a/app/Main.hs b/app/Main.hs index 16e4939..1495605 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -1,7 +1,111 @@ module Main where +import Control.Monad +import Text.ParserCombinators.Parsec hiding (spaces) import System.Environment +import Numeric + +data LispVal = Atom String + | List [LispVal] + | DottedList [LispVal] LispVal + | Number Integer + | String String + | Character Char + | Bool Bool + deriving Show + +symbol :: Parser Char +symbol = oneOf "!#$%&|*+-/:<=>?@^_~" + +spaces :: Parser () +spaces = skipMany space + +nonPrintableChar :: Parser Char +nonPrintableChar = do c <- char '\\' >> oneOf "\\nrtf" + return $ case c of '\\' -> '\\' + 'n' -> '\n' + 'r' -> '\r' + 't' -> '\t' + 'f' -> '\f' + +parseCharacter :: Parser LispVal +parseCharacter = do char '\'' + c <- noneOf ['\\', '\''] <|> try singleQuote <|> try nonPrintableChar + char '\'' + return $ Character c + where + singleQuote = char '\\' >> char '\'' + +parseString :: Parser LispVal +parseString = do char '"' + x <- many innerChar + char '"' + return $ String x + where innerChar = noneOf ['\\', '"'] <|> try doubleQuote <|> try nonPrintableChar + doubleQuote = char '\\' >> char '"' + +parseAtom :: Parser LispVal +parseAtom = do + a <- letter <|> symbol + b <- many (letter <|> digit <|> symbol) + let atom = a:b + return $ case atom of + "#t" -> Bool True + "#f" -> Bool False + _ -> Atom atom + +parseNumber :: Parser LispVal +parseNumber = do toNum <- radix + ds <- many1 digit + let ((a,_):_) = toNum ds + return $ Number a + where radix = do r <- try (char '#' >> oneOf "bodx") <|> return 'd' + return $ case r of + 'd' -> readDec + 'x' -> readHex + 'o' -> readOct + 'b' -> readInt 2 (\x -> elem x "01") (read . (:[])) + +parseList :: Parser LispVal +parseList = liftM List $ sepBy parseExpr spaces + +parseDottedList :: Parser LispVal +parseDottedList = do + head <- endBy parseExpr spaces + tail <- char '.' >> spaces >> parseExpr + return $ DottedList head tail + +parseQuoted :: Parser LispVal +parseQuoted = do + char '\'' + x <- parseExpr + return $ List [Atom "quote", x] + +parseExpr :: Parser LispVal +parseExpr = parseString + <|> parseNumber + <|> parseAtom + <|> try parseCharacter + <|> parseQuoted + <|> do char '(' + x <- try parseList <|> parseDottedList + char ')' + return x + +readExpr :: String -> String +readExpr input = case parse parseExpr "lisp" input of + Left err -> "No match: " ++ show err + Right val -> "Found value: " ++ showVal val + +showVal :: LispVal -> String +showVal (Atom atom) = atom +showVal (Number n) = show n +showVal (String str) = "\"" ++ str ++ "\"" +showVal (Character c) = "'" ++ [c] ++ "'" +showVal (Bool True) = "#t" +showVal (Bool False) = "#f" main :: IO () main = do - args <- getArgs - putStrLn (show (read (args !! 0) + read (args !! 1))) + args <- getLine + putStrLn (readExpr args) + main