A rust macro for generating PEG parsers.
"Hello"
'c'
'0'..='9'
$e
@e
name: e
&e
!e
e e
e | e
e*
e+
e?
any = // Matches any single character
digit = '0'..='9'
alpha = insensitive['a'..='z']
alnum = alpha | digit
comment = !any
space = (whitespace | comment)*
rule = name '=' alt
alt = cat ('|' cat)* action?
cat = (named | unary)+
named = name ':' unary
unary = prefix | postfix | atom
prefix_op
= '$' // Span
| '@' // Atomic
| '!' // Negative lookahead
| '&' // Positive lookahead
postfix_op
= '*' // Many0
| '+' // Many1
| '?' // Optional
prefix = prefix_op atom
postfix = postfix_op atom
atom = name | literal | parenthesized
parenthesized = '(' alt ')'
Try the rule over and over, with recursion depth from 1.., until the parse fails. Now the latest cached result is the answer.
For delimiters, we may want to select for
- 0 or more occurrences []
- 1 or more occurrences [1]
- 1 or more occurrences, but only when there is a trailing comma [1,]
- When x
has return type X
and y
has return type Y
, x ^ y
should have return type (Vec<X>, Vec<Y>)
- Tuple can be made as follows:
tuple = '(' item: item ',' items: item ^ ',' ')' {
let mut items = items.0;
items.insert(0, item);
items
}
Alternatively (this isn't possible yet)
tuple = '(' items: item ^ ',' ')' {?
// At least one comma
match items.1.len() {
0 => None
_ => Some(items.0)
}
}