mirror of
https://github.com/fluencelabs/lalrpop
synced 2025-03-16 17:00:53 +00:00
Conditional alternatives.
This commit is contained in:
parent
3305bbdd3e
commit
9e311d41d3
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user