parsing - 在 uu-parsinglib 中使用 `opt` 组合器

标签 parsing haskell

我正在为我的项目编写一个简单文本模板语言的解析器,并且我完全陷入了 uu-parsinglib 中的 opt 组合器(如果重要的话,版本 2.7.3.2)。关于如何正确使用它有什么想法吗?

这是一个非常简单的示例,显示了我的困境。

{-# LANGUAGE FlexibleContexts #-}

import Text.ParserCombinators.UU hiding (pEnd)
import Text.ParserCombinators.UU.Utils
import Text.ParserCombinators.UU.BasicInstances

pIdentifier :: Parser String
pIdentifier = pMany pLetter

pIfClause :: Parser ((String, String), String, Maybe (String, String), String)
pIfClause = (,,,) <$> pIf <*> pIdentifier <*> pOptionalElse <*> pEnd

pIf :: Parser (String, String)
pIf = pBraces ((,) <$> pToken "if " <*> pIdentifier)

pOptionalElse :: Parser (Maybe (String, String))
pOptionalElse = (((\x y -> Just (x, y)) <$> pElse <*> pIdentifier) `opt` Nothing)

pElse :: Parser String
pElse = pBraces (pToken "else")

pEnd :: Parser String
pEnd = pBraces (pToken "end")

main :: IO ()
main = do
  putStrLn $ show $ runParser "works" pIfClause "{if abc}def{else}ghi{end}"
  putStrLn $ show $ runParser "doesn't work" pIfClause "{if abc}def{end}"

第一个字符串正确解析,但第二个字符串失败并出现错误:

main: Failed parsing 'doesn't work' :
Expected  at position LineColPos 0 12 12 expecting one of [Whitespace, "else"] at LineColPos 0 12 12 :
                              v
                  {if abc}def{end}
                              ^

最佳答案

opt 的文档说:

If p can be recognized, the return value of p is used. Otherwise, the value v is used. Note that opt by default is greedy.

<<|> 的文档中解释了贪婪的含义。 :

<<|> is the greedy version of <|>. If its left hand side parser can make any progress then it commits to that alternative.

在您的情况下,opt 的第一个参数确实识别部分输入,因为 elseend两者都以 e 开头。因此,它 promise pElse ,这会失败并导致整个解析失败。

解决这个问题的一个简单方法是使用 ... <|> pure Nothing ,如文档所示。

关于parsing - 在 uu-parsinglib 中使用 `opt` 组合器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9512374/

相关文章:

haskell - 防止无意中使用不同类型的类实例

html - xpath 在页面中查找特定链接

c++ - 如何从 yaml 文件中获取特定的类别名称?

haskell - 在记录上映射身份仿函数

haskell - 显示 Haskell 中的函数列表

haskell - 为什么 "take"在 haskell 中改变数据类型?

haskell - Cabal 安装 gtk 失败

html - 如何从泰米尔语网站的不同网页中按顺序提取英文文本?

parsing - 我应该如何构建和遍历 ANTLR3 语法的 AST 输出?

java - 使用 Gson 解析嵌套数组的 Json