X-Git-Url: https://git.rmz.io/my-scheme.git/blobdiff_plain/369fde6e9fc7f5ddd28d83e34da21624cb4c2c7c..fabc3d8bdaef310b2f18bc53735ad7ee53518822:/app/Main.hs?ds=inline diff --git a/app/Main.hs b/app/Main.hs index c71126b..1495605 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -9,6 +9,7 @@ data LispVal = Atom String | DottedList [LispVal] LispVal | Number Integer | String String + | Character Char | Bool Bool deriving Show @@ -18,21 +19,29 @@ 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 ['\\', '\"'] <|> escapeChar - escapeChar = do char '\\' - c <- oneOf ['\"', '\\', 'n', 'r', 't', 'f'] - return $ case c of - '\"' -> '\"' - '\\' -> '\\' - 'n' -> '\n' - 'r' -> '\r' - 't' -> '\t' - 'f' -> '\f' + where innerChar = noneOf ['\\', '"'] <|> try doubleQuote <|> try nonPrintableChar + doubleQuote = char '\\' >> char '"' parseAtom :: Parser LispVal parseAtom = do @@ -56,15 +65,44 @@ parseNumber = do toNum <- radix '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: " ++ show val + 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