The DOT Language Graphviz中的“DOT”语言

如下是DOT语言的简明语法定义。

终端以粗体显示,非终端以斜体显示。文本字符使用单引号包含。括号(和)指明一些必要的组合。方括号[和]表示一些可选项。竖线|把一些备选方法分割开。

graph   :   [ strict ] (graph | digraph) [ ID ] '{' stmt_list '}'
stmt_list   :   [ stmt [ ';' ] stmt_list ]
stmt    :   node_stmt
|   edge_stmt
|   attr_stmt
|   ID '=' ID
|   subgraph
attr_stmt   :   (graph | node | edge) attr_list
attr_list   :   '[' [ a_list ] ']' [ attr_list ]
a_list  :   ID '=' ID [ (';' | ',') ] [ a_list ]
edge_stmt   :   (node_id | subgraph) edgeRHS [ attr_list ]
edgeRHS :   edgeop (node_id | subgraph) [ edgeRHS ]
node_stmt   :   node_id [ attr_list ]
node_id :   ID [ port ]
port    :   ':' ID [ ':' compass_pt ]
|   ':' compass_pt
subgraph    :   [ subgraph [ ID ] ] '{' stmt_list '}'
compass_pt  :   (n | ne | e | se | s | sw | w | nw | c | _)

需要注意的是,关键字node, edge, graph, digraph, subgraph和strict是忽略大小写的。另外,那些给出的指示符值并不是关键字,因此这些字符串在别处可以作为普通标识符来使用。反过来说,解析器会接受任何标识符。

ID可以是如下任何一种类型:

  • 任意字符类型的字母 ([a-zA-Z\200-\377]) , 下划线 ('_') 数字 ([0-9]), 不能以数字开头;
  • 一个数字 [-]?(.[0-9]+ | [0-9]+(.[0-9]*)? );
  • 双引号 ("...")包裹的字符串可能包含独立的转义引号 (")1;
  • HTML 字符串 (<...>).

ID就是一个字符串。前面的两个例子上没有加引号只是为了简单起见。事实上, abc_2 和 "abc_2", 或者 2.34 和 "2.34"这两种表达方式并没有什么区别。

显而易见,如果我们要把一个关键词作为ID,那么就要加上引号。需要注意的是,在HTML语言中,尖括号必须成对的出现,并且换行符和其他标准空字符是可以使用呢的。另外,HTML语言的内容必须符合标准的XML, 因此在原文中使用XML中的特殊字符时需要进行转义,比如 ", &, <, 和 > 。

带引号的内容和HTML代码都会被作为一个单元识别出来。所以被识别在这个单元内部的任何内容都会被认为是他们的一部分。

edgeop(边操作)使用 -> 表明有向图边 , -- 表明无向图边。
我们支持C++的注释风格:使用 /* */ 和 //. 同时,一行以#号开头的句子也会被认为是C预处理器的输出内容而不被识别。 (我理解是#也是注释)

分号和逗号有助于提高可读性,但不是必需的。此外,可以在终端之间插入任何的空白字符。

另一个为了可读性方便的案例是,DOT允许在双引号包裹的字符串内跨越多个物理行,只要你紧接在换行符前面使用标准C约定的反斜杠作为识别。
另外,双引号包裹的字符串可以使用‘+’来进行连接。由于HTML字符串允许内部有换行符,因此该语言不允许使用转移换行符和连接运算符。

子图和集合

在Graphviz中,子图有三个作用。子图可以用来表示图结构,标示某些点和边可以组合在一起。这是子图常用的方法,指明图组件的语义信息。其次,它还可以为边提供一个简便的缩写。在边的状态中,子图可以同时在边操作符的左边和右边。当这种状态的时候,会为左边的每个节点和右边的每个节点之间都创建一条表。例如:

A -> {B C}

相当于

  A -> B
  A -> C

第二点,子图可以为设置属性提供一些上下文。比如说,子图可以设定蓝色作为所有节点产生时的默认颜色。这里有一个更有意思的栗子:

subgraph { 
rank = same; A; B; C; 
}

这个子图定义了ABC三个节点置于同一个等级。
子图的第三个作用是在使用布局引擎对图像进行布局时进行干预。如果子图的名字被定义为cluster,那么Graphviz会识别到这是一个特殊的cluster子图。在使用这个方法时,布局引擎会把这个cluster下面的所有节点画在一起,并用一个矩形框把它们括在一起。不过需要注意的是,cluster子图并不是一个标准的DOT语句,它只是为了适配部分布局引擎的特殊需求而单独约定的。

语法和语义要点

在该语言中,一个图要么被指定为一个有向图,要么被指定为一个无向图。在语义上来说,有向图需要在每一条边上都设定一个方向或者两个方向,而无向图的边则设定为没有方向。在语法上来说,一个有向图的边要用->,一个无向图的边要用--来表述。有向图和无向图需要在定义图形的时候就指定,作为一个默认属性。在有向图中,一条线默认会有一个箭头指向头部节点,在无向图中则不会有任何箭头。

图也可以被定义为严谨图,禁止创建多边对象,这意味着在任何两点之间只能有一条边。对于无向图,两个节点之间只能有一条线连接。在紧接着的边声明中,可以使用这两个事先声明的点来唯一标识这一条边,并且可以使用边定义中的任何属性。例如下面这样

strict graph { 
  a -- b
  a -- b
  b -- a [color=blue]
} 

通过上述定义,我们就可以在点a和b之间创建一条蓝色的边。
如果使用节点,边或图形语句或未附加到节点或边的属性赋值定义默认属性,则之后定义的任何相应类型的对象将继承此属性值。
这种状态将一直维持下去,除非这个值被赋予了一个新的值,那么从这个新的节点开始,后面都会使用新的值。已经定义但没有赋值的对象会有一个空字符串值。
值得注意的是,一个子图在被定义的时候就会继承父节点的属性。这个功能很有用,比如你在根图就制定了一个字体,在整个图上的子图都会使用这个字体。但是对于某些属性,是不适用这个功能的。比如在根图上加了一个标签,大概率上来说这个标签都不需要加在所有的子图上。所以不必在图的顶点就列出所有属性,然后在子图上加以修改。可以简单的进行处理,那就是当你需要的时候再加上这个属性。
如果一条边属于一个集合,那么它的端点也属于这个集合。因此,边的放置会影响布局,因为集合有时候是递归布局的。
子图和集合需要一些限制。首先,一个图和所有子图共享一个命名空间,所以所有的子图都需要有一个唯一的命名。其次,尽管节点可以属于任何子图,但是当节点是某个集合的边或节点的子集的时候,该集合应该是有严格的等级的。

字符编码

DOT语言支持ASCII字符编码字符集。在引用的字符中,普通引用和类HTML引用可能包含非ASCII编码字符。在大多数情况下,这些字符都不会被解析。它们会被当做标识符或者字符值来进行传递。其中有一类比较特殊的,即标签(Labels),需要用来在前端展示,需要在软件需求的长度范围内,并使用合适的字体。因此,对于这部分需要知道使用了什么字符编码格式。
DOT语言默认是UTF-8编码。也可以使用Latin1 (ISO-8859-1)编码,但是需要使用 charset
来指明。对于其他的字符编码比如iconv,需要转换成上面的两种。
在labels中避免非法字符的另外一种方法是在使用特殊字符时包进HTML实体中。在识别标签的时候,这些实体被转换成底层标签。table这个表里记录了所有支持的实体,连带它们的Unicode值,标准字形和HTML实体名。因此,要将小写的希腊语beta包含在字符串中,可以使用ascii编码&beta;。通常,应该只使用输出字符集中允许的实体,并且字体中只有一个字形。

  1. 在DOT中的引用字符串中,唯一的转义字符是双引号(")。也就是说,在引用的字符串中,dyad \“被转换为”;所有其他字符保持不变。尤其是\仍然\。布局引擎可以应用其他转义序列。
  2. 在2.30版本之前,该语言允许在HTML字符串之外的任何地方使用转义换行符。新的语义识别器很难实现这个功能,同时因为这个功能的用处也不是很大,我们将此功能限制为仅限于使用双引号的字符串,这样在需要的时候也可以发挥一点作用。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,743评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,296评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,285评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,485评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,581评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,821评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,960评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,719评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,186评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,516评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,650评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,936评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,757评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,991评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,370评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,527评论 2 349

推荐阅读更多精彩内容

  • 从匹配中返回值 Match 对象 成功的匹配总是返回一个 Match 对象, 这个对象通常也被放进 $/ 中, (...
    焉知非鱼阅读 1,790评论 0 1
  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,370评论 0 5
  • 这次开一个小脑洞。因为是脑洞,所以是有水分的,很多定义是模糊的,推理过程也并不要求严格。 话题先从标题的最后一项开...
    LostAbaddon阅读 1,838评论 8 11
  • JavaScript语言精粹 前言 约定:=> 表示参考相关文章或书籍; JS是JavaScript的缩写。 本书...
    微笑的AK47阅读 578评论 0 3
  • 字符串和字符 [TOC] 字符串是例如 "hello, world" , "albatross" 这样的有序的 C...
    伍哥___阅读 1,083评论 0 0