Multilinear Parser
A companion parser for the multilinear crate that converts a human-readable format into constrained parallel aspects.
Features
- 📝 Markdown-inspired syntax
- ↔️ State transition declarations (
from > to) - 🧩 Logical condition combinations (
&and|) - 🗂️ Header-based event grouping with hierarchical namespaces
- 📁 Recursive directory parsing for multi-file projects
- ⚙️ External aspect default configuration files
- 🚦 Automatic aspect/value management
Syntax
The basic syntax looks like this:
# [event]
[aspect]: [required_value]
[aspect]: [current_value] > [new_value]
For naming events, aspects and values, only alphanumeric characters, spaces and - and _ are allowed.
The names will be trimmed.
Empty names are allowed and are considered as the default values.
But you can also specify an additonal file to set custom default values.
Namespaces via Headers
Events can be grouped using headers (#), subheaders (##), etc. The header hierarchy creates a namespace for each event, which is useful for organizing complex stories:
# Chapter 1
## Scene A
### Event
...
This creates the namespace Chapter 1, Scene A for the Event.
Explanation
A simple event could be defined like this:
# Look around in livingroom
place: livingroom
Looking around in the livingroom is only possible if you are in the livingroom. This event doesn't change anything. Usually you want to change at least one aspect.
This could be done like this:
# Go from livingroom to kitchen
place: livingroom > kitchen
If you want to go from the livingroom to the kitchen, you have to be in the livingroom and afterwards you will be in the kitchen.
Technically every condition is a change of the aspect. The previous notation is only short for a change with the same start and end value.
So staying in the same place could also be written like this:
# Look around in livingroom
place: livingroom > livingroom
It's also allowed to require multiple conditions to be fulfilled:
# Change into pajamas
place: bedroom
clothes: casual > pajamas
You can only change into pajamas if you're in your bedroom and wear casual clothes. Afterwards you will still be in the bedroom, but wear pajamas.
So if there are multiple lines, all of these conditions have to be fulfilled. It's not allowed to use conditions of the same aspect multiple times.
But it's also possible to have multiple alternative conditions for the same event by adding an empty line between the conditions:
# Sleep
place: bedroom
place: livingroom
You can sleep in the bedroom (in your bed) and in the livingroom (on the couch).
In this case, the aspect for both alternatives has to be the same.
It's also possible to have multiple sets of conditions, which might be fulfilled. And they might also lead to different outcomes.
# Call mom
place: bedroom
mom place: livingroom > bedroom
place: kitchen
mom place: livingroom > kitchen
When you're at home, and mom is in the livingroom, you can call her to come to your current room.
In most cases it's useful to use the same aspects in all sets of conditions. But in some cases it's allowed that some aspects only appear in one condition.
Logical expressions
It's also allowed to use logical expressions using & and | in single lines.
By default, & has a higher precedence than |, but it's allowed to do explicit grouping using parentheses.
Everything can also be written in a single line using logical expressions.
The previous examples would then look like this:
# Look around in livingroom
place: livingroom
# Go from livingroom to kitchen
place: livingroom > kitchen
# Change into pajamas
place: bedroom & clothes: casual > pajamas
# Sleep
place: bedroom | place: livingroom
# Call mom
place: bedroom & mom place: livingroom > bedroom | place: kitchen & mom place: livingroom > kitchen
But when using this system, some things could even be simplified.
For example when having a shared condition:
# Watch TV
place: bedroom
time: afternoon
place: livingroom
time: afternoon
place: dining room
time: afternoon
You are only allowed to watch TV in the afternoon. And there are multiple rooms at home, but only some of them have a TV.
When using logical expressions, this could be simplified to look like this:
# Watch TV
place: bedroom | place: livingroom | place: dining room
time: afternoon
Since this uses the same aspect multiple times for an expression, there's another operator ;, which acts like |, but belongs to the specific aspect.
So the previous example could be simplified even further:
# Watch TV
place: bedroom; livingroom; dining room
time: afternoon
Precedence rules
;- Aspect-specific OR&- Explicit AND|- Explicit OR- Newlines - Implicit AND
- Empty lines - Implicit OR
Example showing precedence:
# Complex Event
a: 1 | b: 2 & c: 3
d: 4
a: 5
This could also be represented in a single line with explicit grouping using parentheses like this:
# Complex Event
((a: 1 | (b: 2 & c: 3)) & d: 4) | a: 5
Usage
Here you'll see some basic usage. For more complex usage, see the documentation.
Basic
This basic example shows how to parse single files:
use parse_multilinear;
use File;
let file = open.unwrap;
let parsed = parse_multilinear.unwrap;
Directories & Aspect Files
For larger projects, you can organize your story into directories and parse aspect defaults from separate files:
use parse_multilinear_extended;
// Parse a directory tree with custom aspect default values
let parsed = parse_multilinear_extended.unwrap;
// Parsing only a single file without aspects is also possible using this method, but less efficient
let parsed = parse_multilinear_extended.unwrap;
Full Example
This is how some more complex example might look like:
# At home
## In bedroom
### Get dressed
place: bedroom
clothes: pajamas > casual
### Get undressed
place: bedroom
clothes: casual > pajamas
### Go to livingroom
place: bedroom > livingroom
clothes: pajamas; casual
## In livingroom
### Talk sister in pajamas
place: livingroom
clothes: pajamas
### Talk mom in pajamas
place: livingroom
clothes: pajamas
### Talk sister casual
place: livingroom
clothes: casual
### Talk mom casual
place: livingroom
clothes: casual
### Go to bedroom
place: livingroom > bedroom
### Go outside
place: livingroom > outside
clothes: casual
### Try to go outside wearing pajamas
place: livingroom
clothes: pajamas
mom mood: happy > annoyed
# Outside
## Go home
place: outside > livingroom
## Travel to the city
place: outside > city
This even shows grouping using subheaders.
In this case, the events are grouped by place. But it would also make sense to group them by action type (like continuous actions and temporary events, or movement and local events).
And not using grouping at all is also an option.