我跟着自己写了一个方案,并且即将完成它,直到我遇到一个我无法加载文件的错误。
=> (load "stdlib.shm")
Parse error at "lisp" (line 33, column 15):
unexpected "."
expecting space, letter, "\"", "#", "'", "(", "#\\" or digit
我尝试过重做解析器,但似乎没什么用。 这是解析器的代码:
symbol :: Parser Char
symbol = oneOf "!$%&|*+-/:<=>?@^_~"
spaces :: Parser ()
spaces = skipMany1 space
escapedChars :: Parser Char
escapedChars = char '\\' >>
oneOf "\\\"nrt" >>=
\c -> return $ case c of
'\\' -> c
'"' -> c
'n' -> '\n'
'r' -> '\r'
't' -> '\t'
parseExpr :: Parser Lval
parseExpr = parseAtom
<|> parseString
<|> parseBool
<|> parseQuoted
<|> parseListStructure
<|> try parseCharacter
<|> try parseFloat
<|> try parseNumber
-- Parse String of syntax: "<chars | digits | symbols>"
parseString :: Parser Lval
parseString = do char '"'
s <- many (escapedChars <|> (noneOf ['\\', '"']))
char '"'
(return . String) s
-- Parse single character of syntax: '<char>'
parseCharacter :: Parser Lval
parseCharacter = string "#\\" >>
many1 letter >>=
\s -> return $ case (map toLower s) of
"space" -> Character ' '
"newline" -> Character '\n'
[x] -> Character x
-- Parse Atom (Symbol) may contain any one of chars in symbols
parseAtom :: Parser Lval
parseAtom = do first <- letter <|> symbol
rest <- many $ letter <|> digit <|> symbol
(return . Atom) $ first:rest
{- Parse any numerical form of these, where the prefix is sign of base.
(36674...,
#d36674...,
#x8F42...,
#o107502...,
#b1000111101000010...) -}
parseNumber :: Parser Lval
parseNumber = parsePlainNumber <|> parseRadixNumber
parsePlainNumber :: Parser Lval
parsePlainNumber = many1 digit >>= (return . Number . read)
parseRadixNumber :: Parser Lval
parseRadixNumber = char '#' >>
(parseDecimal
<|> parseHex
<|> parseOct
<|> parseBin)
parseDecimal :: Parser Lval
parseDecimal = do char 'd'
x <- many1 digit
(return . Number . read) x
parseHex :: Parser Lval
parseHex = char 'x' >> many1 hexDigit >>=
\x -> (return . Number) $ hex2Int x
parseOct :: Parser Lval
parseOct = char 'o' >> many1 octDigit >>=
\x -> (return . Number) $ oct2Int x
parseBin :: Parser Lval
parseBin = char 'b' >> (many1 $ oneOf "10") >>=
\x -> (return . Number) $ bin2Int x
hex2Int x = fst $ head $ readHex x
oct2Int x = fst $ head $ readOct x
bin2Int s = sum $ map (\(i,x) -> i*(2^x)) $ zip [0..] $ map p (reverse s)
where p '0' = 0
p '1' = 1
-- Parse floats of syntax: <digits>.<digits>
parseFloat :: Parser Lval
parseFloat = do x <- many1 digit
char '.'
y <- many1 digit
(return . Float . read) $ x ++ "." ++ y
-- Parse booleans syntax: (#t, #f)
parseBool :: Parser Lval
parseBool = char '#' >> oneOf "tf" >>=
\c -> return (case c of
't' -> Bool True
'f' -> Bool False)
-- Parsing anytype of list structure here
parseListStructure = do char '('
x <- parseList <|> parseDottedList
char ')'
return x
parseList :: Parser Lval
parseList = liftM List $ sepBy parseExpr spaces
parseDottedList :: Parser Lval
parseDottedList = do x <- endBy parseExpr spaces
xs <- char '.' >> spaces >> parseExpr
return $ DottedList x xs
-- Parsing quoted expressions
parseQuoted :: Parser Lval
parseQuoted = char '\'' >> parseExpr >>=
\x -> return $ List [Atom "quote", x]