2016-01-18 45 views
5

我正在写一个SVG解析器,主要作为学习如何使用Parsec的练习。目前我使用下面的数据类型来表示我的SVG文件:SVG解析和数据类型

data SVG = Element String [Attribute] [SVG] 
     | SelfClosingTag [Attribute] 
     | Body String 
     | Comment String 
     | XMLDecl String 

这工作得很好,但我不知道我的数据类型的Element String [Attribute] [SVG]一部分。 由于SVG中潜在的tags数量有限,我正在考虑使用类型来表示SVG元素,而不是使用String。类似这样的:

data SVG = Element TagName [Attribute] [SVG] 
     | ... 

data TagName = A 
      | AltGlyph 
      | AltGlyphDef 
      ... 
      | View 
      | Vkern 

这是一个好主意吗?如果有这样做会有什么好处? 有没有更优雅的解决方案?

回答

4

我个人更喜欢列举所有可能的TagName s的方法。这样,如果你犯了一些粗心的错误,编译器会给你错误和警告。例如,如果我想编写一个涵盖每种可能类型的函数Element,那么如果每个类型都在ADT中枚举,编译器可以给你非详尽的匹配警告。如果你将它表示为一个字符串,这是不可能的。另外,如果我想匹配一个特定类型的Element,并且我意外地拼错了TagName,编译器会抓住它。第三个原因可能并不适用于此,但一般来说值得注意的是,如果我稍后决定添加或删除TagName的变体,那么编译器会告诉我需要修改的每个位置。我怀疑SVG标签名称会出现这种情况,但总的来说,应该记住这一点。

4

要回答你的问题:

你可以做到这一点无论哪种方式,取决于你要你做后,它与您解析树做什么。

如果你只关心你,SVG解析器描述的是SGV数据的形状,你只需要一个字符串。另一方面,如果您想以某种方式将该SVG数据转换为类似图形的东西(即您期望评估AST),则会发现最好是在类型系统中表示所有语义信息。这将使下一步更容易。

我脑海中的问题是,解析过程是否正是发生这种情况的地方。 (完全披露,我对SVG只有一个熟悉的习惯。)我怀疑,而不仅仅是一个单一的标签列表,你最好用Element每个都有它自己的一套必需和可选属性。如果此转换“稍后在程序中发生”,则不需要创建一个TagName数据类型。您可以在将属性合并到Element的同时捕获所有类型错误。

。另一方面,一个很好的理由可以作出直接解析成一个完整的Element树在这种情况下,我将放弃Element构造的通用[Attribute][SVG]领域,而是在你TagName构造做出相应的字段。


另一个问题的答案,你没有问:

认沽源代码的位置到您解析树早。从个人的经历来看,我可以告诉你,越大的程序就越难。