我正在尝试解析 RFC5322 电子邮件地址。我的解析器的工作原理是在结果中,其中一个是正确的。但是,我该如何选择“正确”的结果呢?
给定字符串Foo Bar <foo@bar.com>
,我的解析器应该产生一个Address (Just "Foo Bar") "foo@bar.com"
.
或者,给定字符串foo@bar.com
,我的解析器应该产生Address Nothing "foo@bar.com"
.
包含名称的值是首选。
我的解析器如下所示:
import Control.Applicative
import Data.Char
import qualified Data.Text as T
import Text.ParserCombinators.ReadP
onlyEmail :: ReadP Address
onlyEmail = do
skipSpaces
email <- many1 $ satisfy isAscii
skipSpaces
return $ Address Nothing (T.pack email)
withName :: ReadP Address
withName = do
skipSpaces
name <- many1 (satisfy isAscii)
skipSpaces
email <- between (char '<') (char '>') (many1 $ satisfy isAscii)
skipSpaces
return $ Address (Just $ T.pack name) (T.pack email)
rfc5322 :: ReadP Address
rfc5322 = withName <|> onlyEmail
当我使用 运行解析器时readP_to_S rfc5322 "Foo Bar <foo@bar.com>"
,它会产生以下结果:
[ (Address {addressName = Nothing, addressEmail = "F"},"oo Bar <foo@bar.com>")
, (Address {addressName = Nothing, addressEmail = "Fo"},"o Bar <foo@bar.com>")
, (Address {addressName = Nothing, addressEmail = "Foo"},"Bar <foo@bar.com>")
, (Address {addressName = Nothing, addressEmail = "Foo "},"Bar <foo@bar.com>")
, (Address {addressName = Nothing, addressEmail = "Foo B"},"ar <foo@bar.com>")
, (Address {addressName = Nothing, addressEmail = "Foo Ba"},"r <foo@bar.com>")
, (Address {addressName = Nothing, addressEmail = "Foo Bar"},"<foo@bar.com>")
, (Address {addressName = Nothing, addressEmail = "Foo Bar "},"<foo@bar.com>")
, (Address {addressName = Nothing, addressEmail = "Foo Bar <"},"foo@bar.com>")
, (Address {addressName = Nothing, addressEmail = "Foo Bar <f"},"oo@bar.com>")
, (Address {addressName = Nothing, addressEmail = "Foo Bar <fo"},"o@bar.com>")
, (Address {addressName = Nothing, addressEmail = "Foo Bar <foo"},"@bar.com>")
, (Address {addressName = Nothing, addressEmail = "Foo Bar <foo@"},"bar.com>")
, (Address {addressName = Nothing, addressEmail = "Foo Bar <foo@b"},"ar.com>")
, (Address {addressName = Nothing, addressEmail = "Foo Bar <foo@ba"},"r.com>")
, (Address {addressName = Nothing, addressEmail = "Foo Bar <foo@bar"},".com>")
, (Address {addressName = Nothing, addressEmail = "Foo Bar <foo@bar."},"com>")
, (Address {addressName = Nothing, addressEmail = "Foo Bar <foo@bar.c"},"om>")
, (Address {addressName = Nothing, addressEmail = "Foo Bar <foo@bar.co"},"m>")
, (Address {addressName = Nothing, addressEmail = "Foo Bar <foo@bar.com"},">")
, (Address {addressName = Just "Foo Bar", addressEmail = "foo@bar.com"},"")
, (Address {addressName = Just "Foo Bar ", addressEmail = "foo@bar.com"},"")
, (Address {addressName = Nothing, addressEmail = "Foo Bar <foo@bar.com>"},"")
]
在这种情况下,我真正想要的结果出现在列表的倒数第三位。我如何表达这种偏好?