代码之家  ›  专栏  ›  技术社区  ›  kirill fedorov

解析器库中的try和<|>函数如何工作

  •  0
  • kirill fedorov  · 技术社区  · 6 年前

    (I使用 trifecta Right 和文字序列(允许字母、数字符号和“-”进入) Left :

    *Lib>  parseString myParser mempty "123 qwe 123qwe 123-qwe-"
    Success [Right 123,Left "qwe",Left "123qwe",Left "123-qwe-"]
    

    myParser :: Parser [Either String Integer]
    myParser = sepBy1 (try (Right . read <$> (some digit <* notFollowedBy (choice [letter, char '-'])))
               <|>          Left         <$>  some (choice [alphaNum, char '-']))
                      (char ' ')
    

    我的问题是我不明白为什么 try 在那里(以及任何其他类似情况下)是需要的。什么时候 尝试 如果未使用,则会出现错误:

    *Lib>  parseString myParser mempty "123 qwe 123qwe 123-qwe-"
    Failure (ErrInfo {_errDoc = (interactive):1:12: error: expected: digit
    1 | 123 qwe 123qwe 123-qwe-<EOF>
      |            ^                 , _errDeltas = [Columns 11 11]})
    

    所以 将解析游标放回失败时开始的位置。想象 尝试 未使用:

    123qwe              
       ^ failed there, the cursor position remains there
    

    另一方面 <|> 就像“要么”。它应该运行第二个解析器 Left <$> some (choice [alphaNum, char '-'])) (当第一个解析器失败时)只使用“qwe”。 在某个地方我错了。

    0 回复  |  直到 6 年前
        1
  •  4
  •   Fyodor Soikin    6 年前

    如果第二个解析器有机会运行,那么它确实会使用“qwe”部分。但它没有得到这样的机会。

    看看 the definition of (<|>) 对于 Parser :

    Parser m <|> Parser n = Parser $ \ eo ee co ce d bs ->
      m eo (\e -> n (\a e' -> eo a (e <> e')) (\e' -> ee (e <> e')) co ce d bs) co ce d bs
    

    隐马尔可夫模型。。。也许这不是个好主意。不过,让我们继续努力吧。理解所有这些 eo , ee 等等,让我们看看他们的解释 on the Parser definition :

    前四个参数是行为连续性:

    epsilon成功 :解析器没有消耗任何输入,并且有结果以及可能的错误;位置和区块不变(参见pure)

    ε故障 :解析器没有消耗任何输入,并且由于给定错误而失败;位置和区块不变(请参阅空)

    承诺的成功 :解析器已消耗输入并正在生成结果、允许此解析继续的预期字符串集、新位置和继续的剩余块。

    :解析器已使用输入,并且由于给定的错误信息(面向用户的错误消息)而失败

    在你的情况下,我们显然有“严重的失败”,即 Right 解析器消耗了一些输入并失败。所以在这种情况下,它将调用第四个连续-表示 ce 在定义中 (<|>) .

    现在看一下定义的主体:第四个连续传递给解析器 m 未更改:

    m eo (\e -> n (\a e' -> eo a (e <> e')) (\e' -> ee (e <> e')) co ce d bs) co ce d bs
                                                                                 ^
                                                                                 |
                                                                             here it is
    

    (<|>) 将在解析器 m 叫它。这意味着,在解析器 m

    推荐文章