myst (work in progress)
A mystical shell parser, formatter, and interpreter written in Rust.
Myst is a fast, extensible, and hackable toolkit for working with POSIX-style shell scripts. It includes a parser, formatter, and interpreter built from scratch in Rust. Myst understands real-world shell syntax and provides structured AST access for static analysis, tooling, and transformation.
Inspired by mvdan/sh, but engineered from the ground up with performance and extensibility in mind.
Motivation
Myst was created to serve two main purposes: as a learning project to better understand shell parsing and syntax, and as a tool for testing and embedding within the Rio terminal emulator, a GPU-accelerated terminal written in Rust.
Feature Coverage
This table outlines the supported features of POSIX Shell and Bash. Use it to track what your Myst parser and interpreter implementation in Rust supports.
Legends:
- ✅ fully supported.
- ⚠️ only supported in parser and formatter.
- ❌ not supported.
| Category | Functionality / Feature | POSIX Shell | Bash | Myst | Notes |
|---|---|---|---|---|---|
| Basic Syntax | Variable assignment | ✅ | ✅ | ✅ | VAR=value |
| Command substitution | ✅ | ✅ | ✅ | $(cmd) and `cmd` |
|
| Arithmetic substitution | ❌ | ✅ | ❌ | $((expr)) |
|
Comments (#) |
✅ | ✅ | ✅ | ||
Quoting (', "", \) |
✅ | ✅ | ✅ | ||
Globbing (*, ?, [...]) |
✅ | ✅ | ❌ | ||
| Control Structures | if / else / elif |
✅ | ✅ | ❌ | |
case / esac |
✅ | ✅ | ❌ | ||
for loops |
✅ | ✅ | ❌ | ||
while, until loops |
✅ | ✅ | ❌ | ||
select loop |
❌ | ✅ | ❌ | ||
[[ ... ]] test command |
❌ | ✅ | ❌ | Extended test | |
| Functions | Function definition (name() {}) |
✅ | ✅ | ✅ | |
function keyword |
❌ | ✅ | ✅ | Bash-specific | |
| I/O Redirection | Output/input redirection (>, <, >>) |
✅ | ✅ | ✅ | |
Here documents (<<, <<-) |
✅ | ✅ | ❌ | ||
Here strings (<<<) |
❌ | ✅ | ❌ | ||
File descriptor duplication (>&, <&) |
✅ | ✅ | ❌ | ||
| Job Control | Background execution (&) |
✅ | ✅ | ❌ | |
Job control commands (fg, bg, jobs) |
✅ | ✅ | ✅ | May be interactive-only | |
Process substitution (<(...), >(...)) |
❌ | ✅ | ❌ | ||
| Arrays | Indexed arrays | ❌ | ✅ | ✅ | arr=(a b c) |
| Associative arrays | ❌ | ✅ | ❌ | declare -A |
|
| Parameter Expansion | ${var} basic expansion |
✅ | ✅ | ❌ | |
${var:-default}, ${var:=default} |
✅ | ✅ | ❌ | ||
${#var}, ${var#pattern} |
✅ | ✅ | ❌ | ||
${!var} indirect expansion |
❌ | ✅ | ❌ | ||
${var[@]} / ${var[*]} array expansion |
❌ | ✅ | ❌ | ||
| Command Execution | Pipelines (` | `) | ✅ | ✅ | ❌ |
Logical AND / OR (&&, ` |
`) | ✅ | ✅ | ||
Grouping (( ), { }) |
✅ | ✅ | ❌ | ||
Subshell (( )) |
✅ | ✅ | ❌ | ||
Coprocesses (coproc) |
❌ | ✅ | ❌ | ||
| Builtins | cd, echo, test, read, eval, etc. |
✅ | ✅ | ✅ | |
shopt, declare, typeset |
❌ | ✅ | ❌ | Bash-only | |
let, local, export |
✅ | ✅ | ❌ | ||
| Debugging | set -x, set -e, trap |
✅ | ✅ | ❌ | |
BASH_SOURCE, FUNCNAME arrays |
❌ | ✅ | ❌ | ||
| Miscellaneous | Brace expansion ({1..5}) |
❌ | ✅ | ❌ | |
Extended globbing (extglob) |
❌ | ✅ | ❌ | Requires shopt |
|
Bash version variables ($BASH_VERSION) |
❌ | ✅ | ❌ | ||
Source other scripts (. or source) |
✅ | ✅ | ❌ | source is Bash synonym |
Install as your shell
⚠️ Myst is still under development. Use it with caution in production environments.
Option 1:
Option 2:
&&
Option 3:
# Linux
# MacOS/BSD
# Done
Set as default
Optionally you can also set as default
# Add your myst path to:
# Linux:
# MacOS/BSD:
🔌 Embed in Your Rust Project
As an Interpreter
use Interpreter;
use io;
As a Lexer/Tokenizer
As a Parser
use Lexer;
use Parser;
As Formatter
assert_eq!;
Or by receiving AST
let mut formatter = new;
let node = Comment;
assert_eq!;
📦 Crate Info
Add Myst to your Cargo.toml:
= "0.x"
TODO
- Remove interop custom functions from
run_interopand allow to receive as parameter. It will split the current code there tobin.rsfile. - Functions for parser and interop.
- Loops for parser and interop.
- Array index references.
Resources
- https://www.gnu.org/software/bash/manual/bash.html
- https://www.shellcheck.net/
- https://stackblitz.com/edit/bash-ast?file=src%2Fapp%2Fapp.component.ts