带条件失败的uu parsinglib解析
针对更完整的问题进行编辑: 我想创建一个解析器(我使用的是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
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)