【问题标题】:Parsing within case block在 case 块内解析
【发布时间】:2019-12-08 22:10:36
【问题描述】:

所以我正在编写自己的解析器,它几乎完成了,但是我一直被函数的返回所困。我的回报是case,但在case 内我必须进行解析,但我无法使其工作。

parseCompontntsTile :: Tile -> Parser Tile
parseCompontntsTile (Tile pos fix wiel) = 
    do  parseWhiteSpace
        patern <- match "pos:" `mplus`     match "fixed:" `mplus` match "wheel:"
        return (case patern of
                 "pos"   -> (Tile  parsePosition  fix  wiel)
                 "fixed" -> (Tile  pos     parseFixed  wiel)
                 "wheel" -> (Tile  pos     fix    parseWiel) )

函数parsePosition来自parsePosition :: Parser Coord类型; tile的构造函数是Coord Bool Bool

这当然行不通,因为 parsePosition 返回 Parser Coord 并且它需要 Coord(没有 "parse")。通常我只会“解包”它,但是,我将如何在一个案例中做到这一点?

感谢帮助

【问题讨论】:

    标签: parsing haskell functional-programming monads do-notation


    【解决方案1】:

    通常我只会“解包”它,但是,我将如何在一个案例中执行此操作?

    你需要先将最后的return“推送”到case分支内

    pattern <- match "pos:" `mplus`  ....
    case pattern of
       "pos"   -> return (Tile  parsePosition  fix  wiel)
       "fixed" -> return (Tile  pos     parseFixed  wiel)
       "wheel" -> return (Tile  pos     fix    parseWiel)
    

    现在,在解析器 monad 中运行分支,您可以像往常一样解包:

    pattern <- match "pos:" `mplus`  ....
    case pattern of
       "pos"   -> do  -- alternative 1
          pp <- parsePosition
          return (Tile pp fix wiel)
       "fixed" -> -- alternative 2
          (\pf -> Tile pos pf wiel) <$> parseFixed
       "wheel" -> ...
    

    【讨论】:

      【解决方案2】:

      类似

      parseCompontntsTile :: Tile -> Parser Tile
      parseCompontntsTile (Tile pos fix wiel) = 
          do  parseWhiteSpace
              pattern <- match "pos:" `mplus` match "fixed:" `mplus` match "wheel:"
              case pattern of
                       "pos"   -> do { pos <- parsePosition ; return $ Tile pos fix wiel }
                       "fixed" -> do { fix <- parseFixed    ; return $ Tile pos fix wiel }
                       "wheel" -> do { wiel <- parseWiel    ; return $ Tile pos fix wiel } 
      

      假设那些 parseXXXX 项是解析器。

      或者重构它以减少代码重复,通过使用shadowing"update"对应的变量,如

      parseCompontntsTile :: Tile -> Parser Tile
      parseCompontntsTile (Tile pos fix wiel) = 
          do  parseWhiteSpace
              pattern <- match "pos:" `mplus` match "fixed:" `mplus` match "wheel:"
              (pos,fix,wiel) <- case pattern of
                       "pos"   -> do { pos <- parsePosition ; return (pos,fix,wiel) }
                       "fixed" -> do { fix <- parseFixed    ; return (pos,fix,wiel) }
                       "wheel" -> do { wiel <- parseWiel    ; return (pos,fix,wiel) } 
              -- .....
              return $ Tile pos fix wiel
      

      以防实际的后处理步骤涉及更多(即在case 之后,在最终的return 之前有更多步骤)。

      【讨论】:

      • 第二个如何减少代码重复?当然,我们说Tile 的次数减少了,但现在我们说(,,) 的次数更多了。
      • @DanielWagner "in case" 等如答案 - 即在最终返回之前可能还有一些步骤,我用-- ..... 暗示了这一点。我想要的是能够案件之后继续。第一个(最直接的)翻译是拆分(分成三个尾部),第二个将拆分端连接成一条线(在控制流程图中)。
      猜你喜欢
      • 2020-09-18
      • 2015-09-14
      • 2011-08-18
      • 2015-10-17
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多