带条件失败的uu parsinglib解析

带条件失败的uu parsinglib解析,parsing,haskell,applicative,Parsing,Haskell,Applicative,针对更完整的问题进行编辑: 我想创建一个解析器(我使用的是uu parsinglib),它接受前面解析器的结果,如果结果包含某个构造函数,则有条件地失败: 我现在意识到这一定是一个一元语法分析器 我有一个包含非直接左递归的语法。下面的例子说明了这个问题,现实稍微复杂一些: data Field = Field_A A Field_B B Field_C C Field_D String data A = A Pre

针对更完整的问题进行编辑:

我想创建一个解析器(我使用的是uu parsinglib),它接受前面解析器的结果,如果结果包含某个构造函数,则有条件地失败:

我现在意识到这一定是一个一元语法分析器

我有一个包含非直接左递归的语法。下面的例子说明了这个问题,现实稍微复杂一些:

data Field = 
       Field_A  A
       Field_B  B
       Field_C  C
       Field_D  String

data A =
       A Prefix String

data B =
       B Prefix String

data C =
       C Prefix String

data Prefix = 
       Prefix Field
大多数时候,我只对这个领域感兴趣,为了尽量减少回溯,最好把注意力集中在那个案例上

我定义了一个操作符来帮助您

(<..>) :: IsParser p => p (a -> b) -> p (b -> c) -> p (a -> c)
g <..> f = (.) <$> f <*> g
就pField而言,如果最右边的字段构造函数不是Field_a,则后置过滤器将失败。正如已经正确指出的,这是一个单元解析。我找不到任何令人信服的使用uu parsinglib作为一元语法分析器的例子,那么您建议的方法是什么


如果我找错了人,也请告诉我。

我想我找到了解决办法。我仍然对如何最好地解析这种间接左递归感兴趣

建议的解决方案是

pA :: Parser A
pA = do
   a <- pField
   case a of 
      (Field_A r) -> return r
      otherwise   -> pFail
pA::解析器A
pA=do
回程
否则->pFail

似乎只有当解析器返回的值通过某个测试时,您才能创建一个通用条件解析器。这当然使用了monad功能。然而,我不确定这是否是一件与uu parsinglib相关的好事情。在我的测试中,它似乎工作得很好,但有一个例外:当条件失败并且没有其他解析器可以使用输入时,库抛出一个异常。(没有给出纠正步骤的东西…)


我还想知道自由使用这种条件解析器会产生的其他陷阱。(如果有的话。)

一个解析器的“动作”不能依赖于另一个解析器的“结果”,而仅仅是
Applicative
API。这(即上下文敏感性)正是
Monad
赋予您的
Applicative
的力量。这一点很好。很明显,我现在必须考虑一下。请注意,
uu parsinglib
确实允许您在真正需要时使用一元接口。但是你描述的情况听起来好像你并不真的需要它…事实上,我想我真的真的需要它。我将用一个更有说服力的用例来编辑这个问题
pA' :: Parser (Prefix -> Field)
pA' = ( (flip A) <$> pString ) <..> pReturn Field_A

pB' :: Parser (Prefix -> Field)
pB' = ( (flip B) <$> pString ) <..> pReturn Field_B

pC' :: Parser (Prefix -> Field)
pC' = ( (flip C) <$> pString ) <..> pReturn Field_C

-- This consumes no input
pPrefix' :: Parser (Field -> Prefix)
pPrefix' = pReturn Prefix
pA :: Parser A
pA :: Parser A
pA = do
   a <- pField
   case a of 
      (Field_A r) -> return r
      otherwise   -> pFail
pConditional :: Parser a -> (a -> Bool) -> Parser a
pConditional p test = p >>= (\result -> case (test result) of
    True -> pure result
    False -> empty)