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 (args !! 0 ++ args !! 1)
+ args <- getLine
+ putStrLn (readExpr args)
+ main