无法让parsec解析“。”

时间:2015-03-25 13:33:21

标签: parsing haskell parsec

我跟着自己写了一个方案,并且即将完成它,直到我遇到一个我无法加载文件的错误。

=> (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]

1 个答案:

答案 0 :(得分:1)

感谢dfeuer(在上面的评论中)我发现了问题。这是stdlib.shm文件中的语法错误:

(define (list . lst) lst)