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
IDは次のいずれかです。
- アルファベット(
[a-zA-Z\200-\377]
)文字、アンダースコア('_'
)、または数字([0-9]
)の任意の文字列。ただし、数字で始まるものは除きます。 - 数値[
-
]?(.
[0
-9
]⁺|
[0
-9
]⁺(.
[0
-9
]*)? ); - エスケープされた引用符(
\"
)¹を含む可能性のある任意の二重引用符付き文字列("..."
)。 - HTML文字列(
<...>
)。
IDは単なる文字列です。最初の2つの形式に引用符文字がないのは、単に簡潔にするためです。abc_2
と"abc_2"
の間、または2.34
と"2.34"
の間には意味的な違いはありません。明らかに、キーワードをIDとして使用するには、引用符で囲む必要があります。
HTML文字列
HTML文字列では、山括弧は一致するペアで出現する必要があり、改行やその他の書式設定用の空白文字が許可されていることに注意してください。さらに、コンテンツは有効なXMLである必要があるため、", &, <、および>の特殊なXMLエスケープシーケンスは、これらの文字を属性値または生のテキストに埋め込むために必要になる場合があります。IDとして、HTML文字列は任意の有効なXML文字列にすることができます。ただし、label属性として使用する場合、HTMLライクなラベルの構文に従う必要があり、特別に解釈されます。
引用符付き文字列とHTML文字列は両方とも1つのユニットとしてスキャンされるため、埋め込まれたコメントは文字列の一部として扱われます。
エッジ操作(edgeops)
edgeopは、有向グラフでは->
、無向グラフでは--
です。
コメントとオプションの書式設定
この言語はC++スタイルのコメントをサポートしています:/* */
と//
。さらに、'#'文字で始まる行は、Cプリプロセッサからの行出力(例:# 34 は34行目を示す)と見なされ、破棄されます。
セミコロンとコンマは読みやすさを助けますが、必須ではありません。また、任意の量の空白を終端記号の間に入れることができます。
読みやすさを向上させるもう1つの手段として、dotでは、標準のC規約である、改行文字の直前にバックスラッシュを置くことで、二重引用符で囲まれた文字列が複数の物理行にまたがることを許可しています²。さらに、二重引用符で囲まれた文字列は、'+'演算子を使用して連結できます。HTML文字列には書式設定のためだけに使用される改行文字を含めることができるため、この言語では、エスケープされた改行や連結演算子をHTML文字列内で使用することはできません。
サブグラフとクラスタ
サブグラフはGraphvizで3つの役割を果たします。まず、サブグラフはグラフ構造を表すために使用でき、特定のノードとエッジをグループ化する必要があることを示します。これがサブグラフの通常の役割であり、通常はグラフコンポーネントに関するセマンティック情報を指定します。また、エッジの便利な短縮形を提供することもできます。エッジステートメントでは、エッジ演算子の左右両側にサブグラフを記述できます。これが発生すると、左側のすべてのノードから右側のすべてのノードにエッジが作成されます。たとえば、仕様
A -> {B C}
は、以下と同等です。
A -> B
A -> C
2番目の役割として、サブグラフは属性を設定するためのコンテキストを提供できます。たとえば、サブグラフは、そこで定義されたすべてのノードのデフォルトの色が青であると指定できます。グラフ描画の文脈では、より興味深い例は次のとおりです。
subgraph {
rank = same; A; B; C;
}
この(匿名の)サブグラフは、dotを使用して描画する場合、ノードA、B、およびCがすべて同じランクに配置されるように指定します。
サブグラフの3つ目の役割は、特定のレイアウトエンジンがグラフをどのように配置するかに直接関わります。サブグラフの名前がcluster
で始まる場合、Graphvizはそのサブグラフを特別なクラスタサブグラフとして認識します。対応している場合、レイアウトエンジンは、クラスタに属するノードが一緒に描画され、クラスタ全体の描画が境界となる長方形内に収まるようにレイアウトを行います。良い点も悪い点もありますが、クラスタサブグラフはDOT言語の一部ではなく、特定のレイアウトエンジンが準拠する構文上の慣習に過ぎないことに注意してください。
語彙的および意味的な注意事項
グラフは、digraphまたはgraphのいずれかとして指定する必要があります。意味的には、これはエッジのノードの1つから他方へ自然な方向があるかどうかを示します。字句的には、digraphはエッジ演算子->
を使用してエッジを指定する必要があり、無向グラフは--
を使用する必要があります。操作的には、この区別は異なるデフォルトのレンダリング属性を定義するために使用されます。たとえば、digraphのエッジは、デフォルトで、ヘッドノードを指す矢印付きで描画されます。通常のグラフでは、エッジはデフォルトで矢印なしで描画されます。
グラフは、strictと記述することもできます。これにより、多重エッジの作成が禁止されます。つまり、有向グラフの場合、特定のテールノードとヘッドノードを持つエッジは最大で1つしか存在できません。無向グラフの場合、同じ2つのノードに接続されるエッジは最大で1つしか存在できません。同じ2つのノードを使用する後続のエッジステートメントは、以前に定義されたエッジを識別し、エッジステートメントで指定された属性を適用します。たとえば、次のグラフ
strict graph {
a -- b
a -- b
b -- a [color=blue]
}
では、ノードa
とb
を接続する単一のエッジが存在し、その色は青になります。
node、edge、またはgraphステートメントを使用して、あるいはノードやエッジに付加されていない属性の割り当てによって、デフォルトの属性が定義されている場合、その後で定義された適切なタイプのオブジェクトは、この属性値を継承します。これは、デフォルトの属性が新しい値に設定されるまで保持され、その時点から新しい値が使用されます。デフォルトの属性が設定される前に定義されたオブジェクトには、デフォルトの属性定義が行われると、属性に空の文字列値が付加されます。
特に、サブグラフは定義時に親グラフの属性設定を受け取ることに注意してください。これは便利です。たとえば、ルートグラフにフォントを割り当てると、すべてのサブグラフもそのフォントを使用します。ただし、一部の属性については、このプロパティは望ましくありません。ラベルをルートグラフに付加した場合、すべてのサブグラフでそのラベルを使用するのはおそらく望ましい効果ではありません。グラフの先頭にグラフ属性を記述し、サブグラフで必要に応じて属性をリセットする代わりに、適切なサブグラフが定義されるまでグラフの属性定義を延期することができます。
エッジがクラスタに属する場合、その端点はそのクラスタに属します。したがって、エッジをどこに配置するかによってレイアウトが影響を受ける可能性があります。これは、クラスタが再帰的にレイアウトされる場合があるためです。
サブグラフとクラスタには特定の制限があります。まず、現時点では、グラフとそのサブグラフの名前は同じ名前空間を共有します。したがって、各サブグラフには一意の名前が必要です。次に、ノードは任意の数のサブグラフに属することができますが、クラスタはノードとエッジのサブセットとして見た場合、厳密な階層を形成すると想定されています。
文字エンコーディング
DOT言語は、少なくともASCII文字セットを想定しています。通常の文字列とHTMLのような文字列の両方で、引用符で囲まれた文字列には非ASCII文字を含めることができます。ほとんどの場合、これらの文字列は解釈されません。これらは、一意の識別子または変更されていない値として渡されるだけです。ただし、ラベルは表示されることを目的としているため、ソフトウェアはテキストのサイズを計算し、適切なグリフを決定できる必要があります。このためには、どの文字エンコードが使用されているかを知る必要があります。
デフォルトでは、DOTはUTF-8文字エンコードを想定しています。また、入力グラフがこれを指定するためにcharset属性を使用していると仮定して、Latin1(ISO-8859-1)文字セットも受け入れます。他の文字セットを使用するグラフの場合、通常、iconv
などのある文字セットから別の文字セットに変換するプログラムがあります。
ラベルで非ASCII文字を避ける別の方法は、特殊文字にHTMLエンティティを使用することです。ラベル評価中に、これらのエンティティは基になる文字に変換されます。この表は、サポートされているエンティティを、そのUnicode値、典型的なグリフ、およびHTMLエンティティ名とともに示しています。したがって、小文字のギリシャ文字のベータを文字列に含めるには、ASCIIシーケンスβ
を使用できます。一般に、出力文字セットで許可されており、フォントにグリフが存在するエンティティのみを使用する必要があります。
- DOTの引用符で囲まれた文字列では、エスケープされる文字は二重引用符
"
のみです。つまり、引用符で囲まれた文字列では、ダイアド\"
は"
に変換されます。他のすべての文字は変更されません。特に、\\
は\\
のままです。レイアウトエンジンは、追加のエスケープシーケンスを適用する場合があります。 - 2.30より前のバージョンでは、言語はHTML文字列以外の場所でエスケープされた改行を使用することができました。新しいlexベースのスキャナーでは、これを実装することが困難になっています。この一般性の有用性が低いと認識されているため、この機能を二重引用符付き文字列に制限しました。ここでは、実際に役立つ可能性があります。