phaser3-rex-plugins
Version:
189 lines (135 loc) • 4.91 kB
Markdown
# Flow Parser Format Specification
This parser reads a lightweight graph DSL and returns a normalized graph object.
## Input Format
### 1. Statement Types
The parser accepts these statement types:
1. `NODE [ ... ]`
Sets default attributes for all subsequently created normal nodes.
2. `EDGE [ ... ]`
Sets default attributes for all subsequently created edges.
3. `NodeId [ ... ]` or `NodeId`
Declares/updates a node.
4. `From -> To [ ... ]`, `From -.> To [ ... ]`, or `From *> To [ ... ]`
Declares one edge (or multiple edges if chained).
5. `;` or blank lines
Valid separators.
### 2. Line Endings and Separators
- A statement ends with `EOL`, `;`, or `EOF`.
- Attributes are written inside `[ ... ]`.
- Attributes are comma-separated and allow trailing commas.
- Newlines are allowed inside attribute blocks.
### 3. Comments
Supported comments:
- `# comment`
- `// comment`
- `/* block comment */`
### 4. Identifiers and Literals
- `IDENT`: starts with letter/underscore, then letters/digits/`_`/`-`/`.`.
- `QUOTED_STRING`: single or double quoted string.
- `NUMBER`: integer or float, supports optional leading `-`.
- `HEXNUMBER`: `0x...` (parsed as base 16 number).
### 5. Attribute Syntax
Each attribute is:
`key = value`
- `key`: `IDENT` or quoted string.
- `value`: `NUMBER`, `HEXNUMBER`, quoted string, or `IDENT`.
Value conversion:
- `NUMBER` -> JavaScript `Number`
- `HEXNUMBER` -> JavaScript `Number` via base-16 parsing
- quoted string -> unquoted string
- `IDENT` -> string
### 6. Node References in Edges
A node reference in an edge chain can be:
- `IDENT`
- `QUOTED_STRING`
- `*` (anonymous dummy node)
- `*name` (named dummy node)
Dummy node IDs generated by parser:
- anonymous `*` -> `_d$1`, `_d$2`, ...
- named `*name` -> `_d#name` (reused if referenced again)
### 7. Edge Operators
- `->` normal edge
- `-.>` dashed edge
- `*>` invisible edge
Dashed edge adds/overrides:
- `$dashed: true`
Invisible edge adds/overrides:
- `render: false`
- `$invisible: true`
- `elk.edge.thickness: 0`
### 8. Edge Chains
Chaining is supported:
`A -> B -> C`
This expands to:
- `A -> B`
- `B -> C`
If edge attributes are provided at chain end, they apply to every expanded edge in that chain.
### 9. Defaults and Special Handling
- Node defaults (`NODE`) are applied only when a normal node is first created.
- Edge defaults (`EDGE`) are merged into every created edge.
- Node attributes with keys starting with `elk.` are stored in `layoutOptions`; others go to `parameters`.
- Dummy nodes do not inherit `NODE` defaults.
- Parallel edges are disabled in current implementation; duplicate `(sourceId, targetId)` pairs are deduplicated with `first-wins`.
## Output Format
The parser returns:
```js
{
nodes: [
{
id: string,
parameters: { [key: string]: any },
layoutOptions: { [key: string]: any }
},
...
],
edges: [
{
id: string, // "_e1", "_e2", ...
sourceId: string,
targetId: string,
parameters: { [key: string]: any }
},
...
]
}
```
### Node Object
- `id`: node identifier (including generated dummy IDs).
- `parameters`: node attributes (non-`elk.*` keys).
- `layoutOptions`: node layout attributes (`elk.*` keys only).
### Edge Object
- `id`: auto-generated edge ID (`_e1`, `_e2`, ...).
- `sourceId`: source node ID.
- `targetId`: target node ID.
- `parameters`: merged edge properties:
- current `EDGE` defaults
- chain-level edge attributes (if any)
- dashed-edge override for `-.>` (`$dashed: true`)
- invisible-edge overrides for `*>`
## Minimal Example
```txt
NODE [color="blue", elk.direction=RIGHT]
EDGE [weight=2]
A [label="start"]
A -> *tmp -> "Task B" [kind=flow]
*tmp -.> D
*tmp *> C
```
Possible output shape:
```js
{
nodes: [
{ id: "A", parameters: { color: "blue", label: "start" }, layoutOptions: { "elk.direction": "RIGHT" } },
{ id: "_d#tmp", parameters: { $dummy: true }, layoutOptions: {} },
{ id: "Task B", parameters: { color: "blue" }, layoutOptions: { "elk.direction": "RIGHT" } },
{ id: "D", parameters: { color: "blue" }, layoutOptions: { "elk.direction": "RIGHT" } },
{ id: "C", parameters: { color: "blue" }, layoutOptions: { "elk.direction": "RIGHT" } }
],
edges: [
{ id: "_e1", sourceId: "A", targetId: "_d#tmp", parameters: { weight: 2, kind: "flow" } },
{ id: "_e2", sourceId: "_d#tmp", targetId: "Task B", parameters: { weight: 2, kind: "flow" } },
{ id: "_e3", sourceId: "_d#tmp", targetId: "D", parameters: { weight: 2, $dashed: true } },
{ id: "_e4", sourceId: "_d#tmp", targetId: "C", parameters: { weight: 2, render: false, $invisible: true, "elk.edge.thickness": 0 } }
]
}
```