1 unstable release

new 0.1.0 Mar 3, 2025

#54 in Parser tooling

Download history 97/week @ 2025-02-28

97 downloads per month

MIT/Apache

18KB
232 lines

Multilinear Parser

Crates.io Docs.rs

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

  1. & - Explicit AND
  2. | - Explicit OR
  3. Newlines - Implicit AND
  4. 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