1

我正在尝试使用 uu_parsinglib 创建一个 Monadic 解析器。我以为我已经涵盖了,但我在测试中得到了一些意想不到的结果

我的解析器的一个精简示例是:

pType :: Parser ASTType
pType = addLength 0 $
  do (Amb n_list) <- pName
     let r_list = filter attributeFilter n_list
     case r_list of
        (ASTName_IdName a : [] )   -> return (ASTType a)
        (ASTName_TypeName a : [] ) -> return (ASTType a)
        _                          -> pFail
     where nameFilter :: ASTName' -> Bool
           nameFilter a =
              case a of
                 (ASTName_IDName _)   -> True
                 (ASTName_TypeName _) -> True
                 _                    -> False

data ASTType  = ASTType ASTName

data ASTName  = Amb [ASTName']

data ASTName' =
   ASTName_IDName     ASTName
   ASTName_TypeName   ASTName
   ASTName_OtherName  ASTName
   ASTName_Simple     String

pName 是一个模棱两可的解析器。我想要类型解析器做的是应用一个后过滤器,并返回所有满足 nameFilter 的替代方案,包装为 ASTType。

如果没有,它应该会失败。

(我意识到如果列表中有多个有效匹配项,我给出的示例将失败,但该示例服务于它的目的)

现在,据我所知,这一切都有效。问题在于当您在更复杂的语法中使用它时,似乎会出现奇怪的匹配。我怀疑问题是 addLength 0 部分

我想做的是将单子和应用部分分开。使用过滤组件创建一元解析器,然后使用 <**> 运算符应用 pName。

或者

对于 addLength 正在做什么,我会接受一个非常好的解释。

4

1 回答 1

1

我已经整理了一个软糖/解决方法,用于使用 uu-parsinglib 进行单子解析。我使用 Monadic 解析器的唯一方法是分析一个过于慷慨的初始解析器,并选择性地使其结果失败。

bind' :: Parser a -> (a -> Parser b) -> Parser b
bind' a@(P _ _ _ l') b = let (P t nep e _) = (a >>= b) in P t nep e l'

使用此解析器时要记住的重要一点是

a -> M b

必须不消耗任何输入。它必须要么返回 a 的转换版本,要么失败。

警告

目前对此进行的测试很少,并且其行为不受类型强制。这是一种软糖。

于 2013-08-17T20:34:36.223 回答