Hummi Grammar Explanation

Table of contents:

Hummi Grammar is a subgraph description language designed for incrementally building a diagram (graph). Input is consumed from a textbox to produce either a standalone node, or a compound set of related nodes.

See Hummi Grammar Reference for a formal definition in ENBF.

Rationale

Creating and linking nodes individually is tedious. A little notation greatly reduces time to add nodes and relationship to a graph.

Given a node and multiple connections, we can create the nodes and edges much faster with notation:
‘Emily likes Susan, Sally, Kim and Jim’
Commonly found in a row from a table, or survey result.

Given a node we might identify parent nodes and child nodes:
‘Hate causes Anger, and is caused by Fear’
Commonly encountered while brainstorming.

Given a set of nodes we might create them in a group:
‘Parsers, Grammars, and Chess are all good fun’
Commonly encountered while enumerating objects with a shared trait or type.

Goals

  1. Text input of small subgraph components to a diagram.
  2. Never reject user input
  3. Create nodes, links, and groups in a single statement.
  4. Easy and fast to type

Anti-Goals

  1. Avoid tricky syntax which require planning, editing, and balancing to get right
  2. Avoid clashing with other user data where possible
  3. Not file format (Graphviz/JSON/EDN are better file formats)
  4. Not for top level lists. Emily;;Susan;;Sally should be created by pressing enter instead of typing ;;

Notation

Text from the main input box populates the node contents when creating a node. Normal text can contain pretty much anything. Special operators allow several connected nodes to be created in a single statement.

Normal input

Most text is the content of a node.

Some, text <b>I wrote</b>;

This text remains unchanged and be used as the content of a node. Hummi renders Markdown, HTML and Emoji. “I wrote” will render as bold.

Special operators

Special double character notation indicates an operator.

To create two linked nodes, enter:

P>>Q

Nodes P and Q are created, with a link from P to Q.

Whitespace on either side of an operator is ignored, but other whitespace is preserved.

Pool Party >> Q

Creates 2 nodes Pool Party and Q with a link from Pool Party to Q.

Multiple links can be created in a single statement:

Emily>>Susan>>Sally

Results in 3 nodes and 2 links. The links are from Emily to Susan and Emily to Sally.

WARNING: The link operator is not for chaining! Hummi link operators are “relative to the head”, not “chained from head to tail”. The example constructs Emily linking to both Susan and Sally; not a chain from Emily to Susan to Sally.

Chaining is done incrementally:

>>Tom

All currently selected nodes will be connected to Tom. When no nodes are selected, the prefix >> creates no links.

When nodes are added, they are selected.

Entering three separate statements:

A
>>B
>>C

Produces a chain from A to B to C. First A is created and automatically selected. Then B is created with a link from the selected node A, and now B is automatically selected. Then C is created with a link from the selected node B, and now C is automatically selected.

Explicit incremental construction without selection can be done by providing an existing name:

Sally>>Tom

Because Sally already exists, only Tom is created and linked from the existing Sally.

Links can be created in both directions:

Hate>>Anger<<Fear

Results in Hate linked to Anger and Hate from Fear, stated more simply as Fear linked to Hate linked to Anger.

REMINDER: This result is a little counter-intuitive. Visually you might have expected links to Anger from both Hate and Fear. All links are relative to the head, not chained.

Directional links can be provided in any order:

A>>B<<C>>D<<E

Results in A linked to both B and D, and linked from both C and E.

The lack of order or grouping constructs frees you from planning ahead of time which relationships will have what direction. Instead, you add them as they occur to you. The cost is remembering that links are relative to head, and the benefit is that you can create multiple links to and from the head as they occur to you.

Label ::

Links can be labelled like so:

P::implies>>Q

Creates P -implies-> Q; 2 nodes with a link between them labeled implies.

Links can also be labelled from the postfix position:

P>>Q::implies

Produces the same result P -implies-> Q. So you can create a label whenever you think of it; before defining the target node, or after.

::implies

Will label any currently selected relationships. This might be useful if you thought of a label after creating a link.

Create group [[ ]]

Creating a group puts an outline around a set of nodes.

[[ indicates the desire to create a group:

[[Becky;;Ben;;Bob

Produces 3 nodes Becky, Ben, and Bob in a group (outlined).

The balancing brackets is optional:

[[Becky;;Ben;;Bob]]

You can group from the right if you prefer:

Becky;;Ben;;Bob]]

All produce the same result.

Groups can contain linked nodes, and groups can link to other nodes or groups:

Becky>>Ben>>Bob]]>>Chess Club

Produces 3 nodes in a group, Becky linked to both Ben and Bob, and the surrounding group is linked to a 4th node Chess Club.

Label groups with the :: operator:

[[fun::Parsers;;Grammars

Or

Parsers;;Grammars::fun]]

Both create and label the group [ Parsers Grammars ] as fun.

Matching and duplication

Hummi avoids creating duplicates except for solitary nodes and unnamed groups.

Entering [[fun:Chess adds a node Chess to the existing fun group.

Entering a new relation from or to an existing name will connect with the existing name.

Entering an existing relation has no effect.

Entering 2 separate solitary node statements will create 2 nodes with the same text:

A
A

Nesting

Expressions can be nested. Nested expressions tend to be ambiguous and confusing. Long statements run the risk of producing unexpected results that need significant editing. Avoid relying on nesting. Instead, grow your graph incrementally in small connected chunks.

Design considerations

Several tradeoffs need consideration to achieve the grammar goals.

No parse failures, ever

Poorly constructed expressions will be interpreted as node text. Always accepting input is better than interrupting the user. Prefer to create one or more nodes that the user can rearrange or edit to their desired state, rather than raising an error or forcing a notational decision upon the user.

Avoiding conflicts

Single character operators have a higher probability for conflicting with user input. This is addressed by using double characters (>> << [[ ;;) which are almost as fast to type. It also helps to avoid overlap with Markdown syntax, which is anticipated to be relatively common. In the rare event that you need to use these double characters as part of the text, the easiest thing to do is create the node without them first, and then edit it to add them. Alternatively, operators may be escaped by an extra character: >>> will produce a literal >> instead of creating a link. Would it be better to treat triples as notation? Or preserve them?

Personal Knowledge Graphs (such as Roam) use [[reference]] in their markdown, so there is potentially a notation overlap. It seems unlikely that this overlap would affect users in any way, but it is worth considering whether another grouping operator would be preferable. [[ has the advantage of not requiring a shift modifier to be pressed, but (( or {{ would also be logical choices.

Chaining vs relative to head

Chaining is partially achievable by pressing enter. This isn’t perfect. Consider when entering A>>B as one statement followed by >>C as another statement. Should this chain from B to C or should both A and B be linked to C? It is not clear that either make perfect sense, but probably both is more sensible than one because given A>>B>>C there is no clear good single choice. Creating unwanted links is not a huge deal as they can be deleted, but it is a little sad.

There might be a case for making >> and << be chaining operators, and provide separate relative to head operators like |> and |<. This might be more intuitive, and visually pleasing without sacrificing power. It does introduce the mental overhead of extra operators to remember. Also, the proposed operators are not double characters, making them slower to type.

What about search and auto-complete or select? (TBD)

When working on a large graph sometimes it’s hard to locate a node that you know exists in the graph. Using the browser’s built-in search feature is probably not ideal. To help people locate existing nodes, it would be helpful to have a visual search feature. When typing text into the input box it might be helpful to highlight in the diagram where that text occurs. There could be an auto-completion feature so when a match is unique it will fill with that node. It might be useful to have a select operator at that point? But maybe not if the highlighting and auto-complete is sufficient.

Compatibility with Graphviz (lack of)

Graphviz provides a superior file format. It would be easy to support -> as a synonym for >>. The downside is that it makes the grammar less specific. Adding -> should be considered if there is a desire for this from users.

Graphviz supports undirected links -- which don’t currently have meaning in Hummi. This might be a candidate for future inclusion as bidirectional linkage or undirected linkage.

Graphviz has a property notation which is currently out of scope for Hummi Grammar.

Graphviz can be used as an import/export file format. Support for import/export of other text formats (PlantUML, Mermaid, Drakon) will be added in the future.

Labelling nodes (lack of)

Groups and links can be labeled, but node labelling is currently undefined. For all intents and purposes node text is equivalent to a label. It remains to be seen if it would be useful to have node text and label be separate concepts. If they should be, then it introduces additional ambiguity into the notation. We would need to distinguish between link labels and node labels. It seems fine for the label operator to be restricted to groups and links.

Group selected (lack of)

It might be interesting to make

 [[

Groups currently selected nodes similar to how the other operators work on selected nodes and links. But maybe users should click the Group button instead.