使解析器忽略所有冗余空格

时间:2013-12-02 22:20:51

标签: parsing haskell parsec

假设我在Parsec中有Parser p并且我想指定我想忽略p中的所有多余/冗余空格。例如,假设我将列表定义为以“[”开头,以“]”结尾,并且在列表中是由空格分隔的整数。但是如果在“[”之后的“[”之前,在“[”和第一个整数之间有空格,那么我不想要任何错误,等等。

在我的情况下,我希望这适用于我的解析器,用于玩具编程语言。

如果需要/必要,我会用代码更新。

2 个答案:

答案 0 :(得分:3)

space围绕所有内容:

parseIntList :: Parsec String u [Int]
parseIntList = do
    spaces
    char '['
    spaces
    first <- many1 digit
    rest <- many $ try $ do
        spaces
        char ','
        spaces
        many1 digit
    spaces
    char ']'
    return $ map read $ first : rest

这是一个非常基本的问题,有些情况会失败(例如空列表),但这是开始工作的良好开端。

@ Joehillen的建议也可行,但它需要更多类型魔法来使用Parsec的令牌功能。 spaces的定义匹配满足Data.Char.isSpace的0个或更多字符,这是所有标准ASCII空格字符。

答案 1 :(得分:2)

使用组合器说出你的意思:

import Control.Applicative
import Text.Parsec
import Text.Parsec.String

program :: Parser [[Int]]
program = spaces *> many1 term <* eof

term :: Parser [Int]
term = list

list :: Parser [Int]
list = between listBegin listEnd (number `sepBy` listSeparator)

listBegin, listEnd, listSeparator :: Parser Char
listBegin = lexeme (char '[')
listEnd = lexeme (char ']')
listSeparator = lexeme (char ',')

lexeme :: Parser a -> Parser a
lexeme parser = parser <* spaces

number :: Parser Int
number = lexeme $ do
  digits <- many1 digit
  return (read digits :: Int)

尝试一下:

λ :l Parse.hs
Ok, modules loaded: Main.
λ parseTest program " [1, 2, 3] [4, 5, 6] "
[[1,2,3],[4,5,6]]

这个lexeme组合子接受一个解析器,并在它之后允许任意空格。然后,您只需在{* 1}}和lexeme语言的原始令牌周围使用listSeparator

或者,您可以将字符流解析为令牌流,然后将令牌流解析为解析树。这样,词法分析器和解析器都可以大大简化。但是,对于较大的语法来说,这是值得做的,因为可维护性是一个问题;并且您必须使用一些较低级别的Parsec API,例如number