2

trifecta の実験として、次の単純な関数を作成しました。

filterParser :: (a -> Bool) -> Parser a -> Parser a
filterParser cond p = do
  a <- p
  if cond a 
    then return a 
    else unexpected "condition failed!"

アイデアは、パーサーに条件を追加できるようにすることでした。たとえば (述語primeが既に存在すると仮定して)、次のように記述 filterParser prime integerします。素数のみを受け入れるパーサーを作成します。


単一の解析では問題ないようです:

> parseString (filterParser (> 'm') letter) mempty "z"
> Success 'z

> parseString (filterParser (> 'm') letter) mempty "a"
> Failure (interactive):1:2: error: unexpected
> condition failed!

しかし、「多数」では機能しません-比較してください:

> parseString (many $ filterParser (> 'm') letter) mempty "zzz2"
> Success "zzz"

> parseString (many $ filterParser (> 'm') letter) mempty "zzza"
> Failure (interactive):1:5: error: unexpected
> condition failed!

最後の例も返されることを望んでいましたSuccess "zzz"。への呼び出しunexpectedは、解析全体を脱線させるように見えますが、これは私が望んでいたものではありません。

4

2 に答える 2

1

filterParser次を使用して回復可能にする必要がありますtry

import Text.Trifecta
import Control.Applicative

filterParser :: (a -> Bool) -> Parser a -> Parser a
filterParser cond p = try $ do
  x <- p
  if cond x then return x else empty

ただし、これによりカスタム解析エラーが解消されます。ブランチで使用unexpected "Condition failed"してそれを復元しても、 .elsetry

代わりに、次の後にカスタム エラー メッセージを元に戻すことができますtry

filterParser :: (a -> Bool) -> Parser a -> Parser a
filterParser cond p = (<|> unexpected "Condition failed") $ try $ do
  x <- p
  if cond x then return x else empty

これは期待どおりに機能します。

*Main> parseString (many $ filterParser (> 'm') letter) mempty "zzza"
Success "zzz"

*Main> parseString (filterParser (> 'm') letter) mempty "a"
Failure (interactive):1:1: error: unexpected
    Condition failed
a<EOF> 
于 2016-03-22T06:09:34.297 に答える
1

カクタスが提案する解決策に加えて、次の方法があります。


filterParser :: (a -> Bool) -> Parser a -> Parser a
filterParser cond p = do
  a <- lookAhead p
  if cond a then p else unexpected "condition failed!"

これは私が欲しいものを私に与えるようです:

> parseString (filterParser (> 'm') letter) mempty "z"
> Success 'z'

> parseString (filterParser (> 'm') letter) mempty "4"
> Failure (interactive):1:1: error: expected: letter

> parseString (filterParser (> 'm') letter) mempty "a"
> Failure (interactive):1:1: error: unexpected
>     condition failed!

> parseString (many $ filterParser (> 'm') letter) mempty "zzz4"
> Success "zzz"

> parseString (many $ filterParser (> 'm') letter) mempty "zzza"
> Success "zzz"
于 2016-03-22T14:41:00.983 に答える