Melody is a language that compiles to ECMAScript regular expressions, while aiming to be more readable and maintainable.
Note: these are for the currently supported syntax and may change
Batman Theme Β try in playground
16 of "na";
2 of match {
<space>;
"batman";
}
// π¦π¦ΈββοΈ
Turns into
(?:na){16}(?: batman){2}
Twitter Hashtag Β try in playground
"#";
some of <word>;
// #melody
Turns into
#(?:\w)+
Introductory Courses Β try in playground
some of <alphabetic>;
<space>;
"1";
2 of <digit>;
// classname 1xx
Turns into
(?:[a-zA-Z])+ 1(?:\d){2}
Indented Code (2 spaces) Β try in playground
some of match {
2 of <space>;
}
some of <char>;
";";
// let value = 5;
Turns into
(?: {2})+.+;
Semantic Versions Β try in playground
<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)+)$
You can try Melody in your browser using the playground
Read the book here
cargo install melody_cli
git clone https://github.com/yoav-lavi/melody.git
cd melody
cargo install --path crates/melody_cli
- macOS binaries (aarch64 and x86_64) can be downloaded from the release page
-
Arch Linux (maintained by @ilai-deutel)
Installation instructions
-
Installation with an AUR helper, for instance using
paru
:paru -Syu melody
-
Install manually with
makepkg
:git clone https://aur.archlinux.org/melody.git cd melody makepkg -si
-
melody [OPTIONS] [INPUT_FILE_PATH]
ARGS:
<INPUT_FILE_PATH> Read from a file
OPTIONS:
-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
-V, --version Print version information
See the changelog here or in the release page
... of
- used to express a specific amount of a pattern. equivalent to regex{5}
(assuming5 of ...
)... to ... of
- used to express an amount within a range of a pattern. equivalent to regex{5,9}
(assuming5 to 9 of ...
)over ... of
- used to express more than an amount of a pattern. equivalent to regex{6,}
(assumingover 5 of ...
)some of
- used to express 1 or more of a pattern. equivalent to regex+
any of
- used to express 0 or more of a pattern. equivalent to regex*
option of
- used to express 0 or 1 of a pattern. equivalent to regex?
All quantifiers can be preceded by lazy
to match the least amount of characters rather than the most characters (greedy). Equivalent to regex +?
, *?
, etc.
<char>
- matches any single character. equivalent to regex.
<whitespace>
- matches any kind of whitespace character. equivalent to regex\s
or[ \t\n\v\f\r]
<newline>
- matches a newline character. equivalent to regex\n
<tab>
- matches a tab character. equivalent to regex\t
<return>
- matches a carriage return character. equivalent to regex\r
<feed>
- matches a form feed character. equivalent to regex\f
<null>
- matches a null characther. equivalent to regex\0
<digit>
- matches any single digit. equivalent to regex\d
or[0-9]
<vertical>
- matches a vertical tab character. equivalent to regex\v
<word>
- matches a word character (any latin letter, any digit or an underscore). equivalent to regex\w
or[a-zA-Z0-9_]
<alphabetic>
- matches any single latin letter. equivalent to regex[a-zA-Z]
<alphanumeric>
- matches any single latin letter or any single digit. equivalent to regex[a-zA-Z0-9]
<boundary>
- Matches a character between a character matched by<word>
and a character not matched by<word>
without consuming the character. equivalent to regex\b
<backspace>
- matches a backspace control character. equivalent to regex[\b]
All symbols can be preceeded with not
to match any character other than the symbol
<start>
- matches the start of the string. equivalent to regex^
<end>
- matches the end of the string. equivalent to regex$
... to ...
- used with digits or alphabetic characters to express a character range. equivalent to regex[5-9]
(assuming5 to 9
) or[a-z]
(assuminga to z
)
"..."
or'...'
- used to mark a literal part of the match. Melody will automatically escape characters as needed. Quotes (of the same kind surrounding the literal) should be escaped
`...`
- added directly to the output without any escaping
capture
- used to open acapture
or namedcapture
block. capture patterns are later available in the list of matches (either positional or named). equivalent to regex(...)
match
- used to open amatch
block, matches the contents without capturing. equivalent to regex(?:...)
either
- used to open aneither
block, matches one of the statements within the block. equivalent to regex(?:...|...)
ahead
- used to open anahead
block. equivalent to regex(?=...)
. use after an expressionbehind
- used to open anbehind
block. equivalent to regex(?<=...)
. use before an expression
Assertions can be preceeded by not
to create a negative assertion (equivalent to regex (?!...)
, (?<!...)
)
-
let .variable_name = { ... }
- defines a variable from a block of statements. can later be used with.variable_name
. Variables must be declared before being used. Variable invocations cannot be quantified directly, use a group if you want to quantify a variable invocationexample:
let .a_and_b = { "a"; "b"; } .a_and_b; "c"; // abc
/* ... */
,// ...
- used to mark comments (note:// ...
comments must be on separate line)
The Melody file extensions are .mdy
and .melody
melody_compiler
- The Melody compiler π¦ πmelody_cli
- A CLI wrapping the Melody compiler π¦ πmelody_wasm
- WASM binding for the Melody compiler
Last measured on V0.13.3
Measured on an 8 core 2021 MacBook Pro 14-inch, Apple M1 Pro using criterion:
-
8 lines:
compiler/normal (8 lines) time: [3.6560 us 3.6596 us 3.6644 us] slope [3.6560 us 3.6644 us] R^2 [0.9999367 0.9999233] mean [3.6577 us 3.6676 us] std. dev. [3.2234 ns 11.399 ns] median [3.6549 us 3.6674 us] med. abs. dev. [642.70 ps 12.973 ns]
-
1M lines:
compiler/long input (1M lines) time: [345.99 ms 348.85 ms 351.91 ms] mean [345.99 ms 351.91 ms] std. dev. [2.8317 ms 6.3397 ms] median [344.55 ms 352.85 ms] med. abs. dev. [893.36 us 8.5853 ms]
-
Deeply nested:
compiler/deeply nested time: [4.8259 us 4.8330 us 4.8399 us] slope [4.8259 us 4.8399 us] R^2 [0.9998793 0.9998830] mean [4.8259 us 4.8476 us] std. dev. [7.6412 ns 24.306 ns] median [4.8234 us 4.8484 us] med. abs. dev. [4.1349 ns 30.340 ns]
To reproduce, run cargo benchmark
π£ - Partially implemented
β - Not implemented
β - Unclear what the syntax will be
β - Unclear whether this will be implemented
Melody | Regex | Status |
---|---|---|
not "A"; |
[^A] |
π£ |
variables / macros | π£ | |
file watcher | β | |
TS / JS build step | β | |
multiline groups in REPL | β | |
flags: global, multiline, ... |
/.../gm... |
β |
(?) | \# |
β |
(?) | \k<name> |
β |
(?) | \p{...} |
β |
(?) | \P{...} |
β |
(?) | \uYYYY |
β |
(?) | \xYY |
β |
(?) | \ddd |
β |
(?) | \cY |
β |
(?) | $1 |
β |
(?) | $` |
β |
(?) | $& |
β |
(?) | 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