Haskell Parsec Parser遇到[...]

时间:2012-07-17 15:27:17

标签: parsing haskell parsec

我正在尝试使用Parsec在Haskell中编写解析器。目前我有一个可以解析的程序

test x [1,2,3] end

执行此操作的代码如下所示

testParser = do { 
  reserved "test"; 
  v <- identifier; 
  symbol "["; 
  l <- sepBy natural commaSep;
  symbol "]";
  p <- pParser;
  return $ Test v (List l) p
 } <?> "end"

其中commaSep定义为

commaSep        = skipMany1 (space <|> char ',')

现在有一些方法让我解析一个类似的陈述,具体来说:

test x [1...3] end

对Haskell和Parsec来说是新手,我确信有一些非常简洁的方法可以做到这一点,我只是不知道。任何帮助将不胜感激。

再次感谢。

1 个答案:

答案 0 :(得分:14)

我将Control.Applicative使用(*>)中的某些功能。如果你想避免使用Parsec的monadic接口并且更喜欢应用程序接口,这些函数很有用,因为在我看来解析器变得更容易阅读。

如果您不熟悉基本的应用功能,请发表评论,我将对其进行解释。如果您不确定,可以在Hoogle查找它们。


由于我已经理解了您的问题,您需要一个解析器来处理这样的数据结构:

data Test = Test String Numbers
data Numbers = List [Int] | Range Int Int

可以解析这样一个数据结构的解析器看起来像这样(我没有编译代码,但它应该工作):

-- parses "test <identifier> [<numbers>] end"
testParser :: Parser Test
testParser =
  Test <$> reserved "test" *> identifier
       <*> symbol "[" *> numbersParser <* symbol "]"
       <*  reserved "end"
       <?> "test"

numbersParser :: Parser Numbers
numbersParser = try listParser <|> rangeParser

-- parses "<natural>, <natural>, <natural>" etc
listParser :: Parser Numbers
listParser =
  List <$> sepBy natural (symbol ",")
       <?> "list"

-- parses "<natural> ... <natural>"
rangeParser :: Parser Numbers
rangeParser =
  Range <$> natural <* symbol "..."
        <*> natural
        <?> "range"