Python Graphviz: DOT 语言

2024 年 8 月 29 日 | 阅读 6 分钟

接下来是一个抽象的理论语法,定义了DOT语言的特征。终结符以醒目的文本样式显示,非终结符以斜体显示。确切的字符以单语句表示。括号(和)在需要时表示分组。方括号[和]包含可选项。竖线|分隔选项。

关键字strict、subgraph、digraph、Graph、edgenode不区分大小写。同样,允许的方位值不是关键字,因此这些字符串可以被用作常规标识符,或者解析器将接受任何标识符。

ID是以下之一

  • 任何由字母([a-zA-Z\200-\377])、下划线('\_')或数字([0-9])组成的字符行,且不以数字开头;
  • 一个数字([-]?(.[0-9]? | [0-9]?(.[0-9]*)? ));
  • 任何双引号字符串("..."),可能包含转义引号(\")¹;
  • 一个HTML字符串(<...>)。

集群和子图

子图在Graphviz中扮演三个角色。首先,子图可用于表示图的结构,表明某些节点和边应将它们组合在一起。这是子图的常规角色,通常指定图部分的语义信息。它也可以为边提供一个有用的简写。例如,该规定。一个边的声明允许在边的操作符的左侧和右侧使用子图。当发生这种情况时,将从左侧的每个节点到右侧的每个节点创建一个边。

在第二个角色中,子图可以为设置属性提供上下文。例如,子图可以指定蓝色是其中定义的所有节点的默认颜色。就图绘制而言,一个有趣的例子是

这个(神秘的)子图表明,节点A、B和C应该位于同一个位置,如果它们是用点图绘制的话。

子图的第三个角色直接涉及某些布局引擎如何展开图。如果子图的名称以cluster开头,Graphviz会将该子图视为一个特殊的集群子图。当得到支持时,布局引擎将执行布局,以便属于集群的节点一起绘制,整个集群的绘图包含在一个圆角矩形内。请注意,无论好坏,集群子图都不是DOT语言的一部分,而是仅由某些布局引擎遵守的语法约定。

语义和词法说明

图应指定为digraph或graph。从语义上讲,这表明是否存在从边的节点之一到另一个节点的自然方向。

从功能上讲,该区别用于定义不同的默认渲染属性。从词法上讲,digraph必须使用edge操作符->指定边,而undirected Graph必须使用--。例如,digraph中的边将默认绘制箭头指向头部节点。对于常规图,边绘制时没有箭头。

Graph也可以被描述为strict。这禁止创建多边,即在有向情况下,具有给定尾节点和头节点的同一条边最多只能出现一次。对于无向图,最多只能有一条边连接相同的两个节点。使用相同两个节点的后续边声明将识别出与新定义边不同的边,并应用边声明中提供的任何属性。例如,图

它将有一条单独的边连接节点a和b,其颜色为蓝色。

如果使用节点、边或图声明定义了默认属性,或者通过与节点或边无关的属性赋值定义了默认属性,那么之后定义的任何相应类型的对象都将继承该属性值。这会一直持续,直到默认属性被设置为新值,然后使用新值。在设置默认属性之前定义的对象的属性将带有空字符串值,一旦创建了默认属性定义。

特别要注意的是,子图在其定义时会继承其父图的属性设置。这可能很有用;例如,可以为根图分配字体,所有子图也将使用该字体。然而,对于某些属性,这种继承是不期望的。如果在根图上设置标签,那么所有子图使用该标签可能不是理想的。与其在图的顶部列出图属性并在子图中单独重置属性,不如推迟图的属性定义,直到合适的子图被定义为止。

如果一条边属于一个集群,那么它的端点也属于该集群。因此,边的放置方式可能会影响布局,因为集群有时会递归展开。

子图和集群存在一些限制。首先,图及其子图的名称共享相同的命名空间。因此,每个子图都必须有一个唯一的名称。其次,尽管节点可以属于任意数量的子图,但当将集群视为节点和边的子集时,假定集群构成严格的层次结构。

字符编码

DOT语言主要使用ASCII字符集。引用的字符串,无论是常规字符串还是HTML风格字符串,都可以包含非ASCII字符。通常,这些字符串是未解释的:它们充当了纯粹传递的特殊标识符或值。然而,名称是为了显示而设计的,这就要求软件能够计算文本的大小并确定适当的字形。为此,它需要知道使用了哪种字符编码。

默认情况下,DOT假定使用UTF-8字符编码。它还接受Latin1(ISO-8859-1)字符集,前提是输入图使用charset属性来指定它。通常有用于其他字符集的图程序,例如图标,它们会进行从一个字符集到另一个字符集的解释。

避免在名称中使用非ASCII字符的另一种方法是使用HTML实体来表示特殊字符。因此,要在字符串中包含小写希腊字母beta,可以使用ASCII序列&beta;。通常,应该使用在结果字符集中允许的实体,并且对于这些实体存在字体的字形。在名称解析期间,这些实体将被转换为底层字符。此表显示了支持的实体、它们的Unicode值、一个常规字形以及HTML实体名称。

  1. 在DOT的引用字符串中,唯一的转义字符是双引号"。也就是说,在引用字符串中,转义序列\"将被转换为";所有其他字符将保持不变。特别是,\\仍然是\\。格式化引擎可能会应用额外的转义序列。
  2. 在2.30之前,该语言允许在HTML字符串以外的任何地方使用转义换行符。新的基于词法的扫描器使得实现这一点变得困难。考虑到这种简化的明显缺乏用处,我们将此功能限制在双引号字符串中,在那里它可能很有用。