Home

Awesome

<p align="center"> <img alt="Melody Logo" height="250px" src="https://user-images.githubusercontent.com/14347895/159069215-7da8f087-65d5-4982-9592-639c1d81e7f1.svg#gh-dark-mode-only"> <img alt="Melody Logo" height="250px" src="https://user-images.githubusercontent.com/14347895/159069181-53bce5b3-a831-43f1-8c14-af6c6ed7b92b.svg#gh-light-mode-only"> </p> <p align="center"> <a href="https://github.com/yoav-lavi/melody/actions/workflows/rust.yml"> <img alt="Rust CI" src="https://github.com/yoav-lavi/melody/actions/workflows/rust.yml/badge.svg"> </a> <a href="https://crates.io/crates/melody_compiler"> <img alt="Crates.io" src="https://img.shields.io/crates/v/melody_compiler?label=compiler"> </a> <a href="https://crates.io/crates/melody_cli"> <img alt="Crates.io" src="https://img.shields.io/crates/v/melody_cli?label=cli"> </a> <a href="https://melody-playground.vercel.app"> <img alt="melody playground" src="https://img.shields.io/badge/melody-playground-brightgreen"> </a> <a href="https://yoav-lavi.github.io/melody/book/"> <img alt="melody playground" src="https://img.shields.io/badge/melody-book-blue"> </a> </p> <p align="center"> Melody is a language that compiles to ECMAScript regular expressions, while aiming to be more readable and maintainable. </p> <p align="center"> <img width="400" alt="code example" src="https://user-images.githubusercontent.com/14347895/154124756-ddbd3c84-f8b2-45bd-b624-2c510482c4e2.png"> </p>

Examples

Note: these are for the currently supported syntax and may change

Batman Theme  <sub><sup><a href="https://melody-playground.vercel.app?content=MTYlMjBvZiUyMCUyMm5hJTIyJTNCJTBBJTBBMiUyMG9mJTIwbWF0Y2glMjAlN0IlMEElMjAlMjAlM0NzcGFjZSUzRSUzQiUwQSUyMCUyMCUyMmJhdG1hbiUyMiUzQiUwQSU3RCUwQSUwQSUyRiUyRiUyMCVGMCU5RiVBNiU4NyVGMCU5RiVBNiVCOCVFMiU4MCU4RCVFMiU5OSU4MiVFRiVCOCU4Rg==">try in playground</a></sup></sub>

16 of "na";

2 of match {
  <space>;
  "batman";
}

// 🦇🦸‍♂️

Turns into

(?:na){16}(?: batman){2}

Twitter Hashtag  <sub><sup><a href="https://melody-playground.vercel.app?content=JTIyJTIzJTIyJTNCJTBBc29tZSUyMG9mJTIwJTNDd29yZCUzRSUzQiUwQSUwQSUyRiUyRiUyMCUyM21lbG9keQ==">try in playground</a></sup></sub>

"#";
some of <word>;

// #melody

Turns into

#\w+

Introductory Courses  <sub><sup><a href="https://melody-playground.vercel.app?content=c29tZSUyMG9mJTIwJTNDYWxwaGFiZXRpYyUzRSUzQiUwQSUzQ3NwYWNlJTNFJTNCJTBBJTIyMSUyMiUzQiUwQTIlMjBvZiUyMCUzQ2RpZ2l0JTNFJTNCJTBBJTBBJTJGJTJGJTIwY2xhc3NuYW1lJTIwMXh4">try in playground</a></sup></sub>

some of <alphabetic>;
<space>;
"1";
2 of <digit>;

// classname 1xx

Turns into

[a-zA-Z]+ 1\d{2}

Indented Code (2 spaces)  <sub><sup><a href="https://melody-playground.vercel.app?content=c29tZSUyMG9mJTIwbWF0Y2glMjAlN0IlMEElMjAlMjAyJTIwb2YlMjAlM0NzcGFjZSUzRSUzQiUwQSU3RCUwQSUwQXNvbWUlMjBvZiUyMCUzQ2NoYXIlM0UlM0IlMEElMjIlM0IlMjIlM0IlMEElMEElMkYlMkYlMjBsZXQlMjB2YWx1ZSUyMCUzRCUyMDUlM0I=">try in playground</a></sup></sub>

some of match {
  2 of <space>;
}

some of <char>;
";";

// let value = 5;

Turns into

(?: {2})+.+;

Semantic Versions  <sub><sup><a href="https://melody-playground.vercel.app?content=JTNDc3RhcnQlM0UlM0IlMEElMEFvcHRpb24lMjBvZiUyMCUyMnYlMjIlM0IlMEElMEFjYXB0dXJlJTIwbWFqb3IlMjAlN0IlMEElMjAlMjBzb21lJTIwb2YlMjAlM0NkaWdpdCUzRSUzQiUwQSU3RCUwQSUwQSUyMi4lMjIlM0IlMEElMEFjYXB0dXJlJTIwbWlub3IlMjAlN0IlMEElMjAlMjBzb21lJTIwb2YlMjAlM0NkaWdpdCUzRSUzQiUwQSU3RCUwQSUwQSUyMi4lMjIlM0IlMEElMEFjYXB0dXJlJTIwcGF0Y2glMjAlN0IlMEElMjAlMjBzb21lJTIwb2YlMjAlM0NkaWdpdCUzRSUzQiUwQSU3RCUwQSUwQSUzQ2VuZCUzRSUzQiUwQSUwQSUyRiUyRiUyMHYxLjAuMA==">try in playground</a></sup></sub>

<start>;

option of "v";

capture major {
  some of <digit>;
}

".";

capture minor {
  some of <digit>;
}

".";

capture patch {
  some of <digit>;
}

<end>;

// v1.0.0

Turns into

^v?(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)$

Playground

You can try Melody in your browser using the playground

Book

Read the book here

Install

Cargo

cargo install melody_cli

From Source

git clone https://github.com/yoav-lavi/melody.git
cd melody
cargo install --path crates/melody_cli

Binary

Community

CLI Usage

USAGE:
    melody [OPTIONS] [INPUT_FILE_PATH]

ARGS:
    <INPUT_FILE_PATH>    Read from a file
                         Use '-' and or pipe input to read from stdin

OPTIONS:
    -f, --test-file <TEST_FILE>
            Test the compiled regex against the contents of a file

        --generate-completions <COMPLETIONS>
            Outputs completions for the selected shell
            To use, write the output to the appropriate location for your shell

    -h, --help
            Print help information

    -n, --no-color
            Print output with no color

    -o, --output <OUTPUT_FILE_PATH>
            Write to a file

    -r, --repl
            Start the Melody REPL

    -t, --test <TEST>
            Test the compiled regex against a string

    -V, --version
            Print version information

Changelog

See the changelog here or in the release page

Syntax

Quantifiers

All quantifiers can be preceded by lazy to match the least amount of characters rather than the most characters (greedy). Equivalent to regex +?, *?, etc.

Symbols

All symbols can be preceeded with not to match any character other than the symbol

Special Symbols

Unicode Categories

Note: these are not supported when testing in the CLI (-t or -f) as the regex engine used does not support unicode categories. These require using the u flag.

These descriptions are from regular-expressions.info

Character Ranges

Literals

Raw

Groups

Assertions

Assertions can be preceeded by not to create a negative assertion (equivalent to regex (?!...), (?<!...))

Variables

Extras

File Extension

The Melody file extensions are .mdy and .melody

Crates

Extensions

Packages

Integrations

Performance

Last measured on v0.19.0

Measured on an 8 core 2021 MacBook Pro 14-inch, Apple M1 Pro using criterion:

To reproduce, run cargo bench or cargo xtask benchmark

Future Feature Status

🐣 - Partially implemented

❌ - Not implemented

❔ - Unclear what the syntax will be

❓ - Unclear whether this will be implemented

MelodyRegexStatus
not "A";[^A]🐣
variables / macros🐣
<...::...>\p{...}🐣
not <...::...>\P{...}🐣
file watcher
multiline groups in REPL
flags: global, multiline, .../.../gm...
(?)\#
(?)\k<name>
(?)\uYYYY
(?)\xYY
(?)\ddd
(?)\cY
(?)$1
(?)<code>$`</code>
(?)$&
(?)x20
(?)x{06fa}
any of "a", "b", "c" *[abc]
multiple ranges *[a-zA-Z0-9]
regex optimization
standard library / patterns
reverse compiler

* these are expressable in the current syntax using other methods