在Parsec之前或之前解析空格

时间:2016-12-29 12:53:18

标签: parsing haskell parsec

我在Haskell中使用Parsec模块来解析文件。这些文件的一个组成部分是颜色。我已经为这样的颜色创建了一个类型:

data Color = Yellow | Red | Blue | Green deriving (Show)

我最初尝试解析颜色的方法如下:

symbol :: String -> Parsec String () String
symbol s = spaces >> string s

colorP :: Parsec String () Color
colorP = 
   liftM mkColor $ symbol "Yellow" <|> symbol "Red" <|> symbol "Blue" <|> symbol "Green"
  where
   mkColor :: String -> Color
   mkColor "Yellow" = Yellow
   mkColor "Red" = Red
   mkColor "Blue" = Blue
   mkColor "Green" = Green

我创建了symbol解析器,它基本上占用了尽可能多的空格,然后吃掉了给定的字符串s。但是,这似乎不起作用。我使用以下调用测试此代码:

parse colorP "" "        Red"

这给了我以下错误:

unexpected "R"
expecting space or "Yellow"

但是,我在Hoogle上寻找与<|>运营商合作的文档,并在那里找到了以下内容:

  

这个组合器实现了选择。解析器p&lt; |&gt;首先应用p。如果成功,则返回p的值。如果p在没有消耗任何输入的情况下失败,则尝试解析器q。

所以,我认为上面例子的问题是解析器p(在这种情况下是symbol "Yellow")已经消耗了一些输入,即空白!所以,我像这样重构了colorP

colorP =
  liftM mkColor $ spaces >> (string "Yellow" <|> string "Red" <|> string "Blue" <|> string "Green")
 where
   -- mkColor same as before

给出了我想要的结果。

现在,我想知道是否没有像我编写的symbol解析器那样的解析器,但是如果失败则会放回输入。或者是colorP的第二个实现是Haskell-ish最多的那个?

1 个答案:

答案 0 :(得分:2)

您可以使用try

symbol s = try (spaces >> string s)
  

解析器try p的行为类似于解析器p,除了它假装它在发生错误时没有消耗任何输入。