malachi 0.8.0

A domain specific pattern matching language made for defining bot commands.
Documentation
# malachi
A domain specific pattern matching language made mainly for defining bot commands.

# Crate Examples
Please check out the examples subdirectory of this repository.

# Notes
-	While declaring commands, any kind of whitespace (space, tab, newline, crlf) are treated the same.
-	`<>` defines a capture.
-	`[]` defines a list of captures to be matched out of order.
-	You can include a space literal by escaping it with `\\`. I.e. `.foo\ bar` will match the literal `"foo bar"` but not `"foo     bar"`.

# Capture Syntax
You can define captures in 3 ways:

1.	`<NAME[QUANTIFIER]>`
2.	`<NAME[QUANTIFIER]: FILTERS>`
3.	`<NAME[QUANTIFIER]: FILTERS1; FILTERS2; FILTERS3...>`

Quantifiers:
-	`?`: Match this capture 1 or 0 times.
-	`*`: Match this capture 0 or more times. The captures will be returned in a `Vec`.
-	`+`: Match this capture at least once. The values are returned in a `Vec`.
-	None: Match this exactly once.

If you use the first form, the default is to match on words (whitespace separated).
Otherwise you must use a filter.

# Filter Syntax
Filters are exactly like a function call in any mainstream language.
They may take arguments.
Arguments are always quoted strings.

Some examples:

-	`starts("--")`
-	`foo()`

# Strings
Strings are always quoted with one of the `"`, `'` or `\``.

You can escape the quotation to include it in the string.

Some more escape patterns are recognized:

-	`\n`: newline.
-	`\t`: tab.
-	`\r`: carriage return.

# Capture Group Syntax
A capture group defines a list of patterns that will be matched out of order.
There are two forms of capture groups:
-	Priority groups: These are delimited with `[]` and the match priority of the captures enclosed are unchanged.
-	Normal group: These groups are enclosed in `{}` and the enclosed captures may be re-ordered for potentially more matches.

The syntax is as follows:

Priority groups:
```
[ CAPTURE1 CAPTURE2 ...CAPTURE_N ]
```

Normal groups:
```
{ CAPTURE1 CAPTURE2 ...CAPTURE_N }
```

Example:

```
[<first> <second> <maybe_third?>]
```

# Some defaults
-	Patterns have an implicit starting anchor (`^` in regex).
-	Whitespace is only used as a terminator while matching.
-	`starts` and `ends` filters trim the match.

# Examples
## Run code
This example demonstrates a command for running code.
The flags are optional but must start with `--`
The code block is not optional and must either start and end with:
-	"\`\`\`"
-	"\`"
Or,
-	Starts with \`\`\`rust or \`\`\`rs and ends with \`\`\`.

```
.run
<flags*: starts("--")>
<code:
	starts("```rust", "```rs", "```"), ends("```");
	starts("`"), ends("`");
>
```

## Get a Bible Verse
This example command has 3 arguments:
-	`book`: required, must start with `"book=`
-	`chapter`: Optional, must start with either `chapter=` or `ch=`, case is not important.
-	`verse`: optional, must start with `verse=`.

Since the patterns are wrapped in `[]`, they can be matched out of order.

```
.bible
[
	<book: starts("book=")>
	<chapter?: starts("chapter=", "ch="), nocase()>
	<verse?: starts("verse=")>
]
```

## Bet some credits
This basic example command lets you bet some of your discord credits.
The only required argument is the amount.

```
.bet <amount>
```

## See a tag
This command takes 1 or more space separated arguments.
It does not specify any pattern so the defaults apply:
-	Arguments are whitespace separated.

```
.tag <tags+:>
```

# Filters
Every filter can be used any number of times, the arguments are combined into one filter.

- `starts(prefix1, prefix2, ...prefixN)`: Any of the given prefixes must match.
- `ends(suffix1, suffix2, ...suffixN)`: Any of the suffixes must match.
- `eq(s1, s2, ...sN)`: Must match any string given as an argument. Only other filter that can occur if `eq` is specified is `nocase`. `"foo"` is shorthand for `eq("foo")`.
- `nocase()`: Ignore case while matching. Not always accurate and ignored while matching suffixes.
- `notrim()`: Do not trim the prefix/suffix while using `starts()` or `ends()`. Only valid in those two filters.