领域特定语言(DSL)是一种针对特定领域优化的小型语言。由于 DSL 有明确的针对性,它允许使用者声明自己_想要什么_,而不是_如何去_做,因此能极大地提升工作效率和理解程度。
它的一个常见应用领域是复杂的自定义和配置。
例如,DOT 语言允许你用文本描述一张图,然后由 Graphviz 工具(比如dot)将其转换成图片。一个简单的图长这样:
graph {
graph [bgcolor="yellow"]
a [color="red"]
b [color="blue"]
a -- b [color="green"]
}
把这段内容放进文件example.dot,再运行dot example.dot -T png -o example.png,就会生成一张example.png图片:黄色背景上,一个红色圆圈和一个蓝色圆圈由一条绿色线相连。
请编写一个类似 Graphviz dot 语言的领域特定语言。
我们的 DSL 与 Graphviz dot 语言相似,都是用来创建图数据结构的。不过,与 DOT 语言不同,我们的 DSL 是一种内部 DSL,只在本语言中使用。
在这个 DSL 中,图是 Graph 类型的对象。它接收一个 list,里面包含一个或多个元组,用来描述:
NodesEdgesNode 和 Edge 的实现已在 dot_dsl.py 中提供。
关于该 DSL 的预期设计,以及预期的错误类型和错误消息的更多细节,请查看 dot_dsl_test.py 中的测试用例。
有时需要抛出异常。这样做时,应该始终包含一条有意义的错误消息,说明错误来自哪里。这能让你的代码更易读,也大大有助于调试。如果已知错误来源属于某种类型,你可以选择抛出某种内置错误类型,但仍应包含一条有意义的错误消息。
这个练习要求你使用 raise 语句,在 Graph 格式不正确时“抛出” TypeError,在 Edge、Node 或 attribute 格式不正确时“抛出” ValueError。只有当你既 raise 了 exception,又为它附上一条消息时,测试才会通过。
要抛出带有消息的错误,请把消息写成 exception 类型的实参:
# Graph is malformed
raise TypeError("Graph data malformed")
# Edge has incorrect values
raise ValueError("EDGE malformed")