1 unstable release
new 0.1.0 | Mar 3, 2025 |
---|
#54 in Parser tooling
97 downloads per month
18KB
232 lines
Multilinear Parser
A companion parser for the multilinear
crate that converts a human-readable format into constrained parallel state channels.
Features
- 📝 Markdown-inspired syntax
- ↔️ State transition declarations (
from > to
) - 🧩 Logical condition combinations (
&
and|
) - 🗂️ Header-based event grouping
- 🚦 Automatic channel/value management
Syntax
The basic syntax looks like this:
# [event]
[channel]: [required_value]
[channel]: [current_value] > [new_value]
For naming events, channels 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.
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 channel.
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 channel. 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 channel 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 channel for both alternatives has to be the same.
It's also possilbe 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 channels in all sets of conditions. But in some cases it's allowed that some channels 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 TVs 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
Precedence rules
&
- 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 explicite grouping using parentheses like this:
# Complex Event
((a: 1 | (b: 2 & c: 3)) & d: 4) | a: 5
Usage
use multilinear_parser::parse_multilinear;
use std::fs::File;
let file = File::open("story.mld").unwrap();
let parsed = parse_multilinear(file).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 | clothes: 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 evens).
And not using grouping at all is also an option.
Dependencies
~315–760KB
~17K SLoC