Conditional alternatives.

This commit is contained in:
Niko Matsakis 2015-06-15 07:26:38 -04:00
parent 3305bbdd3e
commit 9e311d41d3
4 changed files with 55 additions and 5 deletions

View File

@ -49,7 +49,7 @@ grammar Type<'input, T> {
// Example 2: conditional patterns
Expr<M>: Expr = {
~Expr "(" ~Comma<Expr> ")" => Expr::CallExpr(~~~);
~Expr "(" ~Comma<Expr> ")" => Expr::CallExpr(~~);
ID if M !~ "NO_ID" => {
};
@ -92,10 +92,28 @@ pub struct NonterminalData {
pub struct Alternative {
pub expr: Vec<Symbol>,
// if C, only legal in macros
pub condition: Option<Condition>,
// => { code }
pub action: Option<String>,
}
#[derive(Clone, Debug)]
pub enum Condition {
// X == "Foo", equality
Equals(InternedString, InternedString),
// X != "Foo", inequality
NotEquals(InternedString, InternedString),
// X ~~ "Foo", regexp match
Match(InternedString, InternedString),
// X !~ "Foo", regexp non-match
NotMatch(InternedString, InternedString),
}
#[derive(Clone, Debug)]
pub enum Symbol {
// (<X> <Y>) etc

View File

@ -20,8 +20,8 @@ pub fn normalize(input: &pt::Grammar) -> Result<pt::Grammar> {
// X = ...1 Vec_X ...2
// Comma_X: Vec<<X>> = ...;
//
// AFTER THIS POINT: No more macros or macro references, though type
// indirections may occur.
// AFTER THIS POINT: No more macros, macro references, or guarded
// alternatives, though type indirections may occur.
// mod macro_expand;
// Computes types where the user omitted them (or

View File

@ -67,13 +67,34 @@ rusty_peg! {
("{" <a:{ALTERNATIVE}> "}" ";") => a;
ALTERNATIVE: Alternative =
(<s:{SYMBOL}> <a:[ACTION]> ";") => Alternative {
(<s:{SYMBOL}> <c:[IF_COND]> <a:[ACTION]> ";") => Alternative {
expr: s,
condition: c,
action: a
};
IF_COND: Condition =
("if" <c:COND>) => c;
ACTION: String = ("=>" <b:CODE>) => b;
// Conditions
COND: Condition =
(EQUALS_COND / NOT_EQUALS_COND / MATCH_COND / NOT_MATCH_COND);
EQUALS_COND: Condition =
(<a:ID> "==" <b:LITERAL>) => Condition::Equals(a, b);
NOT_EQUALS_COND: Condition =
(<a:ID> "!=" <b:LITERAL>) => Condition::NotEquals(a, b);
MATCH_COND: Condition =
(<a:ID> "~~" <b:LITERAL>) => Condition::Match(a, b);
NOT_MATCH_COND: Condition =
(<a:ID> "!~" <b:LITERAL>) => Condition::NotMatch(a, b);
// Symbols
SYMBOL: Symbol =
@ -148,7 +169,7 @@ rusty_peg! {
(<i:ID_RE>) => intern(i);
ID_RE: &'input str =
regex(r"[a-zA-Z_][a-zA-Z0-9_]*");
regex(r"[a-zA-Z_][a-zA-Z0-9_]*") - ["if"];
LIFETIME: InternedString =
(<i:LIFETIME_RE>) => intern(i);

View File

@ -82,3 +82,14 @@ fn macro_nt() {
.unwrap();
}
#[test]
fn cond_nt() {
super::parse_nonterminal(
"Foo<E> = {
X if E == \"Bar\";
X if E ~~ \"Bar\";
X if E != \"Bar\";
X if E !~ \"Bar\";
};").unwrap();
}