parsec:将一个解析器的输出提供给另一个解析器

时间:2017-10-19 18:19:43

标签: parsing haskell parsec

我使用(滥用)解析器进行一些字符串转换,例如normalizeWS :: Parser String删除重复的空格,normalizeCase将特定字符串映射为小写。我使用解析器,因为输入数据有一些结构,例如有文化的字符串必须保持不变形。是否有一种优雅的方式将一个解析器的输出作为输入提供给下一个,从而形成转换管道? normalizeWS . normalizeCase的某些东西(当然不起作用)?

非常感谢提前!

2 个答案:

答案 0 :(得分:1)

我使用这种方法解决了问题...也许有更优雅的方式

preprocessor :: Parser String
preprocessor = normalizeCase `feeds` expandKettensatz `feeds` normalizeWs

feeds :: Parser String -> Parser String -> Parser String
feeds p1 p2 = do
  s <- p1
  setInput s
  p2

答案 1 :(得分:0)

如果你有像

这样的功能
normalizeWhitespace :: Stream s m Char => ParsecT s u m String
normalizeCase :: Stream s m Char => Set String -> Parsec s u m String

您可以使用runParser>>=

将它们链接在一起
runBoth :: Stream s Identity Char => Set String -> SourceName -> s -> Either ParseError String
runBoth wordSet src input = do
  input <- runParser normalizeWhitespace () src input
  runParser (normalizeCase wordSet) () src input

但是这并没有为您提供一个可以与其他解析器链接在一起的解析器。

这并不奇怪,因为Parsec中的解析器组合就是全部 组成在同一个流上运行的解析器,而这些解析器依次运行 不同的流。

拥有多个不同的流也很常见 - 使用a tokenization or lexing pass as input to parsing的输出可以使过程更容易 理解,但Parsec is a little easier to use out of the box as a direct parser (without lexing/tokenization)