Парсинг в блоке case

Итак, я пишу свой собственный синтаксический анализатор, который почти готов, однако я продолжаю застревать с возвратом моей функции. Мой возврат - 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; конструктор плитки Coord Bool Bool.

Это, конечно, не работает, потому что parsePosition возвращает Parser Coord и ожидает Coord (без "parse"). Обычно я просто «распаковывал» его, но как мне это сделать в случае?

спасибо за помощь


person swaffelay    schedule 31.07.2019    source источник


Ответы (2)


Обычно я просто «распаковывал» его, но как мне это сделать в случае?

Вам нужно сначала «протолкнуть» окончательный 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)

Теперь, имея запущенные ветки в монаде парсера, можно распаковывать как обычно:

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" -> ...
person chi    schedule 31.07.2019

Что-то типа

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 элементы являются синтаксическими анализаторами.

Или реструктурируйте его для уменьшения дублирования кода, используя затенение для "обновления" соответствующего переменная, как

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).

person Will Ness    schedule 31.07.2019
comment
Как второй меньше дублирования кода? Конечно, мы произносим в Tile раз меньше, но теперь говорим в (,,) раза больше. - person Daniel Wagner; 31.07.2019
comment
@DanielWagner в случае и т. д., как в ответе, то есть может быть еще несколько шагов до окончательного возврата, на что я намекнул с помощью -- ...... то, что я хотел, было возможностью продолжить после дела. первый (самый непосредственный) перевод - это расщепление (на три хвоста), второй соединяет обратно раздвоенные концы в одну линию, так сказать (на схеме потока управления). - person Will Ness; 31.07.2019