## Customizing output

The program can take a properties file to translate terminals and non-terminals. The same file can also contain settings to modify shape, color, fonts, and spacing of almost everything.

### Syntax of the properties file

The properties file used by the program is a normal Java properties file. Its syntax is described in the Java 21 API Specification.

In short:

- It is a file format that consists of lines of text.

- Empty lines are allowed and are skipped.

- Lines beginning with `#` or `!` are considered to be comment lines and are ignored.

- Data lines contain key/value pairs.

- By convention, properties files use the `.props` extension to their name.

Here, a key of a data line is a sequence of words, separated by a dot, for example, `terminal.token.Identifier`. The key is followed by an optional but recommended separator character, either `:` or `=`. The remainder of the line is the value part, where leading and trailing white space is removed.

The properties file format uses `\` as continuation character to the next line and also as escape character.

### Kinds of values

In the tables below, the properties keys recognized by the program are listed along with an example and an expected value.

This table lists the used expected values, and gives some more information about them.

Type name | Examples | Description
--- | --- | ---
Boolean | `yes`, `false' | Boolean value to enable or disable a flag.
RGB color | `151 7 230` | Three integer numbers between `0` and `255` inclusive, separated by spaces.
Integer | `10` | Integer value, usually with ‘pixel’ unit.
Font name | `Serif` | Name of the font to use. The program currently supports the `Dialog`, `DialogInput`, `Monospaced`, `Serif`, and `SansSerif` fonts.
Font height | `12` | Integer number specifying the point size of the font.
Font style | `plain` | Style of the font. The program currently supports `plain`, `bold`, and `italics` styles.
Text | `literal` | Arbitrary text to display for a token.

### Global settings

The following settings affect background and the rail line.

Property name | Value type | Description
--- | --- | ---
`diagram.background.color` | RGB color | Color of the background of the generated image.
`rail.linewidth` | Integer | Width of the rail line.
`rail.color` | RGB color | Color of the rail line.

### Diagram settings

The diagram settings configure the global layout of an image. At the top is a header line with the name of the rule, below it are one or more railroad pictures with some additional rail at both ends.

Property name | Value type | Description
--- | --- | ---
`rule.padding.top` | Integer | Amount of space above the header line.
`rule.padding.left` | Integer | Amount of space left of the header line.
`rule.padding.bottom` | Integer | Amount of space between the last railroad picture and the bottom of the diagram.
`rule.padding.right` | Integer | Minimum amount of space right of the header line.
`rule.diagram.padding.top` | Integer | Amount of space above each railroad picture.
`rule.diagram.padding.left` | Integer | Amount of space left of each railroad picture.
`rule.diagram.lead.width` | Integer | Horizontal length of the rail line before the railroad picture.
`rule.diagram.trail.width` | Integer | Horizontal length of the rail line after the railroad picture.
`diagram-header.text.color` | RGB color | Color of the diagram header text.
`diagram-header.text.font` | Font name | Font of the diagram header text.
`diagram-header.text.font.size` | Font height | Font size in points of the diagram header text.
`diagram-header.text.font.style` | Font style | Style of the diagram header text.

### Empty node

Each kind of node has a number of settings as well, starting with the simplest node, `()`.

Property name | Value type | Description
--- | --- | ---
`empty.width` | Integer | Horizontal length of the empty node.

### Branch label

The bracketed string `[refname]` node configuration settings are listed below.

Property name | Value type | Description
--- | --- | ---
`branch-label.padding.left` | Integer | Amount of space at the left of the label text.
`branch-label.padding.right` | Integer | Amount of space at the right of the label text.
`branch-label.padding.top` | Integer | Amount of space above the label text.
`branch-label.padding.bottom` | Integer | Amount of space between the label text and the rail line.
`branch-label.min-width` | Integer | Minimum horizontal length of the label node.
`branch-label.text.color` | RGB color | Color of the label text.
`branch-label.text.font` | Font name | Font used for the label text.
`branch-label.text.font.size` | Font height | Font size in pt of the label text.
`branch-label.text.font.style` | Font style | Font style of the label text.

### Name node

A name node is a string of text within a box. The text is often a single name, and the box may have rounded corners. At the left and right of the box, a rail line is connected.

First the configuration of the rail lines, followed by the configuration settings of the box and the text.

Property name | Value type | Description
--- | --- | ---
`name.rail.entry.width` | Integer | Horizontal length of the rail line at the left of the box.
`name.rail.exit.width` | Integer | Horizontal length of the rail line at the right of the box.

There are three configurations for name and box. One for terminals, one for meta-terminals, and one for non-terminals. The structure of the settings is the same for all three, their default values are a little different, in particular in choices of corner radius and font.

#### Terminal text and box properties

Property name | Value type | Description
--- | --- | ---
`terminal.name.padding.horizontal` | Integer | Amount of horizontal space between the text and the box around the text.
`terminal.name.padding.vertical` | Integer | Amount of vertical space between the text and the box around the text.
`terminal.corner.radius` | Integer | Radius of the corners of the box. `0` means a rectangular box.
`terminal.box.color` | RGB color | Color of the line of the box.
`terminal.box.linewidth` | Integer | Width of the line of the box.
`terminal.text.color` | RGB color | Color of the terminal text.
`terminal.text.font` | Font name | Font used for the terminal text.
`terminal.text.font.size` | Font height | Height of the terminal text.
`terminal.text.font.style` | Font style | Style of the terminal text.

#### Meta-terminal text and box properties

Property name | Value type | Description
--- | --- | ---
`meta-terminal.name.padding.horizontal` | Integer | Amount of horizontal space between the text and the box around the text.
`meta-terminal.name.padding.vertical` | Integer | Amount of vertical space between the text and the box around the text.
`meta-terminal.corner.radius` | Integer | Radius of the corners of the box. `0` means a rectangular box.
`meta-terminal.box.color` | RGB color | Color of the line of the box.
`meta-terminal.box.linewidth` | Integer | Width of the line of the box.
`meta-terminal.text.color` | RGB color | Color of the meta-terminal text.
`meta-terminal.text.font` | Font name | Font used for the meta-terminal text.
`meta-terminal.text.font.size` | Font height | Height of the meta-terminal text.
`meta-terminal.text.font.style` | Font style | Style of the meta-terminal text.

#### Non-terminal text and box properties

Property name | Value type | Description
--- | --- | ---
`nonterminal.name.padding.horizontal` | Integer | Amount of horizontal space between the text and the box around the text.
`nonterminal.name.padding.vertical` | Integer | Amount of vertical space between the text and the box around the text.
`nonterminal.corner.radius` | Integer | Radius of the corners of the box. `0` means a rectangular box.
`nonterminal.box.color` | RGB color | Color of the line of the box.
`nonterminal.box.linewidth` | Integer | Width of the line of the box.
`nonterminal.text.color` | RGB color | Color of the non-terminal text.
`nonterminal.text.font` | Font name | Font used for the non-terminal text.
`nonterminal.text.font.size` | Font height | Height of the non-terminal text.
`nonterminal.text.font.style` | Font style | Style of the non-terminal text.

#### Token text translations

In the diagram input files, token names may be used, but terminals often contain other symbols. The translation between the token name and the text it should display can also be configured.

There are three groups of settings. Different settings within a group only differ in the name of the token that they translate. Such a name is listed here as `<token-name>`.

Property name | Value type | Description
--- | --- | ---
`terminal.token.<token-name>` | Text | The literal text to display in the diagram for terminal token `<token-name>`.
`meta-terminal.<token-name>` | Text | The literal text to display in the diagram for meta-terminal token `<token-name>`.
`nonterminal.token.<token-name>` | Text | The literal text to display in the diagram for non-terminal token `<token-name>`.

All tokens must have a different name. Both terminals and meta-terminals token lists are assumed to be complete. The non-terminal list is fully optional, and the default choice if a token name cannot be found. All missing entries use the token name as their text.

Note that the property file reader applies some interpretation to the text as well so what you enter in the file may not be what you get. Please check the property file syntax section for details.

### Sequence

A sequence connects one or more child diagram nodes in one or more rows such that they are all visited in sequential order.

Its configuration settings cover the elements around the child nodes.

Property name | Value type | Description
--- | --- | ---
`sequence.padding.first-row.prefix` | Integer | Amount of space before the first child at the first row.
`sequence.padding.other-row.prefix` | Integer | Amount of space left of the left connecting vertical line to a next row.
`sequence.padding.row.suffix` | Integer | If there is more than one row, the minimal amount of space between the right vertical line connecting a next row, and the vertical line up to the exit.
`sequence.padding.interrow` | Integer | Minimal amount of space between the bottom of a row, and the connecting horizontal line to the next row beneath it. Also, the minimal amount of space between the same horizontal line and the top of the next row.
`sequence.arc-radius` | Integer | Radius of the arcs connecting horizontal lines with vertical lines.

### Choice

The choice node expresses a choice between one of the child diagram nodes.

Its configurable properties are:

Property name | Value type | Description
--- | --- | ---
`choice.arc-radius` | Integer | Radius of the arcs connecting horizontal lines with vertical lines.
`choice.padding.vertical` | Integer | Minimal amount of vertical space between two child diagrams.

Note that the space between the first and second child is not only influenced by the `choice.padding.vertical` setting, but also influenced by the `choice.arc-radius`, as two arcs have to fit vertically as well.

### Repetition

The repetition node `A + B` expresses an alternating execution sequence `A(BA)*`. The `A` child node is referred to as forward, as its execution runs normally from left to right in the diagram, while the `B` child is referred to as backward as its execution normally runs from right to left. The repetition is also known as loop due to the circular shape of the node.

Its configuration settings are:

Property name | Value type | Description
--- | --- | ---
`loop.arc-radius` | Integer | Radius of the arcs connecting horizontal lines with vertical lines.
`loop.padding.vertical` | Integer | Amount of vertical space between the nodes of the forward and backward sequences.
`loop.padding.left` | Integer | Amount of space left of the left vertical line.
`loop.padding.right` | Integer | Amount of space right of the right vertical line.

The `loop.padding.left` and `loop.padding.right` become important when a diagram contains a sequence of repetitions. If you set the left and right padding to `0`, the following may happen:

    SequenceLoops : (A + B) (C + D) ;

This results in:

Other nodes all have some space at either end, making it less apparent in those cases.

### Debugging properties

A diagram is actually a tree of simpler diagrams where at each node in the tree a set of position equations is solved for positioning all elements in its sub-tree. This happens in two sweeps through the tree. First a bottom-up computation of size and relative position of elements in their sub-tree is performed. In the second top-down sweep assignment of horizontal and vertical absolute offsets to all nodes is performed, giving all elements their final absolute position in the diagram. Output is produced by a walk over all nodes in the tree, and copying the elements with their absolute positions to the output.

There are several flags for generating detailed output of the above process to support debugging at several points in the computations.

#### Hierarchy

To view the tree hierarchy in the diagram, the `debug.structure` flag can be used.

Property name | Value type | Description
--- | --- | ---
`debug.structure` | Boolean | Dump internal structure of the diagram.

#### Constraint solving

Positions are computed by solving two sets of constraint equations at each node in the tree, one for horizontal positioning, and one for vertical positioning. The `debug.equations` flag shows the variables and equations, the `debug.solver` shows the solving process. Due to the large number of variables and equations in a typical diagram, enabling these settings produces a lot of detailed debug output.

Property name | Value type | Description
--- | --- | ---
`debug.equations` | Boolean | Dump positioning equations for the graphical elements.
`debug.solver` | Boolean | Dump reasoning and deciding edge position values for the graphical elements.

#### Coordinates

To debug problems in produced output, the following flags are useful. The `debug.rel_coordinates` flag shows position information at each level of the tree separately, this is mostly useful to find problems at a single level of a diagram. The `debug.abs_coordinates` flag shows the same position information, except all coordinates use the same top-left origin, enabling verification of positions between different levels in the hierarchy.

Property name | Value type | Description
--- | --- | ---
`debug.rel_coordinates` | Boolean | Dump coordinates of the graphical elements and child node positions within each element.
`debug.abs_coordinates` | Boolean | Dump absolute coordinates of the graphical elements and child node positions of the diagram.

Note that positions are stated as inclusive horizontal and vertical edge positions everywhere. This means that element `x[1—​1], y[1—​2]` is one unit wide horizontally, and two units vertically. Also, an element `x[2—​7], y[1—​2]` is directly next to the previous element, there is no space between them. Zero width or height is shown as an interval with the first value larger than the second value, for example `x[4—​3]`.

### Default property values

The default values for the various properties are as follows:

    # Background.
    diagram.background.color: 255 255 255

    # Rail.
    rail.linewidth: 1.0
    rail.color:     0 0 0

    # Diagram rule.
    rule.padding.top:          10
    rule.padding.left:         10
    rule.padding.bottom:       10
    rule.padding.right:        10
    rule.diagram.padding.top:  10
    rule.diagram.padding.left: 10
    rule.diagram.lead.width:   20
    rule.diagram.trail.width:  20

    # Choice.
    choice.arc-radius:       10
    choice.padding.vertical:  5

    # Loop.
    loop.arc-radius:       10
    loop.padding.vertical:  5
    loop.padding.left:      5
    loop.padding.right:     5

    # Sequence.
    sequence.padding.first-row.prefix:  0
    sequence.padding.other-row.prefix:  5
    sequence.padding.row.suffix:        5
    sequence.padding.interrow:          8
    sequence.arc-radius:               10

    # Branch label.
    branch-label.padding.left:    5
    branch-label.padding.right:   5
    branch-label.padding.top:     5
    branch-label.padding.bottom:  5
    branch-label.min-width:       5
    branch-label.text.color:      0 0 0
    branch-label.text.font:       SansSerif
    branch-label.text.font.size:  16
    branch-label.text.font.style: plain

    # Empty node.
    empty.width: 10

    # Name node, width of the entry and exit connections.
    name.rail.entry.width: 5
    name.rail.exit.width:  5

    # Header font and text.
    diagram-header.text.color:      0 0 0
    diagram-header.text.font:       SansSerif
    diagram-header.text.font.size:  16
    diagram-header.text.font.style: bold

    # 'terminal' name properties.
    terminal.name.padding.horizontal: 5
    terminal.name.padding.vertical:   5
    terminal.corner.radius:           12
    terminal.box.color:               0 0 0
    terminal.box.linewidth:           1.0
    terminal.text.color:              0 0 0
    terminal.text.font:               Monospaced
    terminal.text.font.size:          18
    terminal.text.font.style:         plain

    # 'meta-terminal' name properties.
    meta-terminal.name.padding.horizontal: 5
    meta-terminal.name.padding.vertical:   5
    meta-terminal.corner.radius:           12
    meta-terminal.box.color:               0 0 0
    meta-terminal.box.linewidth:           1.0
    meta-terminal.text.color:              0 0 0
    meta-terminal.text.font:               SansSerif
    meta-terminal.text.font.size:          16
    meta-terminal.text.font.style:         plain

    # 'nonterminal' name properties.
    nonterminal.name.padding.horizontal: 5
    nonterminal.name.padding.vertical:   5
    nonterminal.corner.radius:           0
    nonterminal.box.color:               0 0 0
    nonterminal.box.linewidth:           1.0
    nonterminal.text.color:              0 0 0
    nonterminal.text.font:               SansSerif
    nonterminal.text.font.size:          16
    nonterminal.text.font.style:         italic

    # Token text properties:
    # terminal.token.<tokname>: <toktext>, should always be fully specified.
    # meta-terminal.<tokname>: <toktext>, should always be fully specified.
    # nonterminal.token.<tokname>: <toktext>, with <toktext> optional, default value is <tokname>.

    # Debugging support, ordered by topic.
    debug.structure:       false
    debug.equations:       false
    debug.solver:          false
    debug.rel_coordinates: false
    debug.abs_coordinates: false