gpt4 book ai didi

xml - 如何使用 Alex 和 Happy Lex、解析和序列化到 XML 电子邮件

转载 作者:行者123 更新时间:2023-12-04 04:51:37 25 4
gpt4 key购买 nike

我正在努力输入任何电子邮件消息并输出等效的 XML 编码。

我从小处开始,使用其中一个电子邮件标题——“发件人标题”

以下是 From header 的示例:

From: John Doe <john@doe.org>

我想把它转换成这个 XML:
<From>
<Mailbox>
<DisplayName>John Doe</DisplayName>
<Address>john@doe.org</Address>
</Mailbox>
</From>

我想使用词法分析器“Alex”( http://www.haskell.org/alex/doc/html/ )来分解(标记化)From Header。

我想使用解析器“Happy”( http://www.haskell.org/happy/ )来处理标记并生成解析树。

然后我想使用序列化器来遍历解析树并输出 XML。

From Header 的格式由 Internet Message Format (IMF), RFC 5322 ( http://tools.ietf.org/html/rfc5322 ) 指定。

以下是 From Headers 和所需 XML 输出的更多示例:

从没有显示名称的标题:
From: <john@doe.org>

所需的 XML 输出:
<From>
<Mailbox>
<Address>john@doe.org</Address>
</Mailbox>
</From>

从没有显示名称且地址周围没有尖括号的标题:
From: john@doe.org

所需的 XML 输出:
<From>
<Mailbox>
<Address>john@doe.org</Address>
</Mailbox>
</From>

从带有多个邮箱的 Header 开始,每个邮箱用逗号分隔:
From: <john@doe.org>, "Simon St. John" <simon@stjohn.org>, sally@smith.org

所需的 XML 输出:
<From>
<Mailbox>
<Address>john@doe.org</Address>
</Mailbox>
<Mailbox>
<DisplayName>Simon St. John</DisplayName>
<Address>simon@stjohn.org</Address>
</Mailbox>
<Mailbox>
<Address>sally@smith.org</Address>
</Mailbox>
</From>

RFC 5322 说注释的语法是:( ... )。这是一个包含评论的 From Header:
From: (this is a comment) "John Doe" <john@doe.org>

我希望在词法分析期间删除所有评论。

所需的 XML 输出是这样的:
<From>
<Mailbox>
<DisplayName>John Doe</DisplayName>
<Address>john@doe.org</Address>
</Mailbox>
</From>

RFC 说可能有“折叠空白”散布在整个 From Header 中。这是一个 From Header,第一行是 From: 标记,第二行是显示名称,第三行是地址:
From: 
"John Doe"
<john@doe.org>

XML 输出不应受折叠空格的影响:
<From>
<Mailbox>
<DisplayName>John Doe</DisplayName>
<Address>john@doe.org</Address>
</Mailbox>
</From>

RFC 说地址中的@ 字符后可以是括号括起来的字符串,例如:
From: "John Doe" <john@[website]>

我必须承认,我从来没有见过这样的电子邮件。尽管如此,RFC 表示这是允许的,所以我当然希望我的词法分析器和解析器能够处理这样的输入。这是所需的输出:
<From>
<Mailbox>
<DisplayName>John Doe</DisplayName>
<Address>john@[website]</Address>
</Mailbox>
</From>

错误处理

如果 From Header 不正确,我想要一个错误。以下是错误的 From Headers 和所需输出的几个示例:

显示名称错误地放在地址之后:
From: <john@doe.org> "John Doe"

输出应指定发现错误的位置:
serialize: parse error at line 1 and column 22. Error occurred at "John Doe"

此 From Header 在显示名称前有一个错误的“23”:
From: 23 "John Doe" <john@doe.org>

同样,输出应指定发现错误的位置:
serialize: parse error at line 1 and column 10. Error occurred at "John Doe"

你能展示一下如何实现词法分析器、解析器和序列化器吗?

最佳答案

将任务拆分为五个步骤:

第 1 步 : 为 From Header 指定完整的、权威的 BNF

步骤 #2 : 创建词法分析函数,lex ,将 From Header 分成一系列小块,例如 from: , displayName , angleAddress ,等等。这些小块被称为 token

lex :: String -> [Token]

步骤 #3 : 定义数据类型, From , 代表 From Header

第 4 步 : 创建解析器函数, parser ,它消耗标记序列并生成类型 From 的解析树
parse :: [Token] -> From

步骤 #5 : 创建一个函数, serialize , 遍历解析树并生成 XML
serialize :: From -> XML

第 1 步:为数据格式指定完整的、权威的 BNF

RFC 5322 中指定了 From header 的完整、权威的 BNF。我提取了适用于 From header 的部分:

http://www.xfront.com/parsing/RFC-5322/From-Header/From-Header-BNF.pdf

第 2 步:创建一个词法分析器,将 From Headers 分解为标记

这是一个示例,显示了如何对 From header 进行标记:

将此 From header 标记化:
From: "John Doe" <john@doe.org>

词法分析器的输出是这个标记列表:
[ 
TokenFrom (AlexPn 0 1 1)
, TokenDisplayName (AlexPn 6 1 7) "\"John Doe\""
, TokenAngleAddress (AlexPn 17 1 18) "<john@doe.org>"
]

列表中的每一项都包含一个标记的标签、位置信息和一个可选的值。位置信息是括号中的内容。 “AlexPn”是指示这是位置信息的标签。接下来的三个数字表示 token 的位置:开始位置、行号和列号。

下面是 BFN 的词法分析器。观察 BNF 和 token 定义之间的一对一映射。例如,BNF 有这样的产生式规则:
qcontent  = ( qtext  |  quoted-pair )

词法分析器具有以下标记定义:
@qcontent = ( $qtext | @quoted_pair )

除了细微的语法差异外,它们是相同的。这真的很强大。假设电子邮件“From header”的定义是正确的(即 BNF 是正确的),那么我们可以非常确定词法分析器是正确的。

这是词法分析器:

http://www.xfront.com/parsing/RFC-5322/From-Header/Lexer.x.txt

第 3 步:定义一个数据类型来表示 From Header

token 序列将使用 this from 数据类型在内部表示:
data From
= From MailboxList
deriving Show

type MailboxList
= [ Mailbox ]

data Mailbox
= LongMailbox DisplayName AngleAddress
| AngleMailbox AngleAddress
| ShortMailbox AddressSpecification
deriving Show

data DisplayName
= DisplayName String
deriving Show

data AngleAddress
= AngleAddress String
deriving Show

data AddressSpecification
= AddressSpecification String
deriving Show

第 4 步:创建解析器——使用标记序列并生成“From”类型的解析树

这是一个示例,显示了如何解析 From Headers:

解析这个 From header :
From: "John Doe" <john@doe.org>

解析器的输出是这个解析树:
From 
[
LongMailbox
(DisplayName "John Doe")
(AngleAddress "john@doe.org")
]

这是解析器:

http://www.xfront.com/parsing/RFC-5322/From-Header/Parser.y.txt

第 5 步:遍历解析树并在值周围添加 XML 开始标记、结束标记对

每个语法产生式都有一个函数。例如,这里是 From 语法产生式的函数:
serialize :: From -> String
serialize (From mailboxList) = "<From>" ++ serializeMailboxList mailboxList ++ "</From>"

该函数的参数是解析树的根,其标签为 From。该函数调用另一个函数 serializeMailboxList 来处理根的子项。结果包含在 From start-tag, end-tag 对中。

这是 XML 序列化程序:

http://www.xfront.com/parsing/RFC-5322/From-Header/serialize.hs.txt

关于xml - 如何使用 Alex 和 Happy Lex、解析和序列化到 XML 电子邮件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17354442/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com