use ast::*;
#[pub]
glop -> Glop
= __ ms:matches __ { Glop{ matches: ms } }
matches -> Vec<Match>
= m:match __ ms:matches { let mut ms = ms; ms.insert(0, m); ms }
/ m:match { vec![m] }
match -> Match
= "when" __ "(" __ c:conditions __ ")" __ a:matchActions {?
let acting_roles_set = acting_roles(&c);
let acting_roles = acting_roles_set.iter().collect::<Vec<&String>>();
if acting_roles.len() > 1 {
Err("multiple acting roles in the same match is not supported")
} else {
let acting_role = if acting_roles.is_empty() {
None
} else {
Some(acting_roles[0].to_string())
};
Ok(Match{
conditions: c,
actions: a,
acting_role: acting_role,
})
}
}
matchActions -> Vec<Action>
= "{" __ a:actions __ "}" { a }
/ v:$("#!" (!"!#" .)+) "!#" { vec![Action::Script(String::from(v))] }
conditions -> Vec<Condition>
= c:condition __ "," __ cs:conditions { let mut cs = cs; cs.insert(0, c); cs }
/ c:condition { vec![c] }
condition -> Condition
= k:identifier __ op:cmpop __ v:value { Condition::Cmp(k, op, v) }
/ unaryfunc
identifier -> Identifier
= part:idpart "." rest:identifier { let mut rest = rest; rest.insert(0, part); rest }
/ part:idpart { vec![part] }
idpart -> String
= v:$([a-z][a-z0-9_^.]+) { String::from(v) }
value -> String
= v:$([A-Za-z0-9_]+) { String::from(v) }
/ "\"" v:$([^"]+) "\"" { String::from(v) }
unaryfunc -> Condition
= "message" __ topic:identifier __ src_role:maybeSrcRole __ acting_role:maybeActingRole {
Condition::Message{
topic: topic.join("."),
src_role: src_role,
acting_role: acting_role,
}
}
/ "is_set" __ k:identifier { Condition::IsSet(k) }
/ "is_unset" __ k:identifier { Condition::IsUnset(k) }
maybeSrcRole -> Option<String>
= "from" __ role:idpart { Some(role) }
/ { None }
maybeActingRole -> Option<String>
= "as" __ role:idpart { Some(role) }
/ { None }
cmpop -> CmpOpcode
= "==" { CmpOpcode::Equal }
/ "!=" { CmpOpcode::NotEqual }
actions -> Vec<Action>
= n:action __ ns:actions { let mut ns = ns; ns.insert(0, n); ns }
/ n:action { vec![n] }
/ { vec![] }
action -> Action
= "var" __ "set" __ k:identifier __ v:value __ ";" { Action::SetVar(k, v) }
/ "var" __ "unset" __ k:identifier __ ";" { Action::UnsetVar(k) }
/ "script" __ v:$("#!" (!"!#" .)+) "!#" { Action::Script(String::from(v)) }
/ m:match { Action::Match(m) }
/* The following is borrowed from rust-peg's own grammar */
__ = (whitespace / eol / comment)*
/* Modeled after ECMA-262, 5th ed., 7.4. */
comment
= singleLineComment
/ multiLineComment
singleLineComment
= "//" (!eolChar .)*
multiLineComment
= "/*" (!"*/" .)* "*/"
/* Modeled after ECMA-262, 5th ed., 7.3. */
eol
= "\n"
/ "\r\n"
/ "\r"
/ "\u{2028}"
/ "\u{2029}"
eolChar
= [\n\r\u{2028}\u{2029}]
/* Modeled after ECMA-262, 5th ed., 7.2. */
whitespace
= [ \t\u{00A0}\u{FEFF}\u{1680}\u{180E}\u{2000}-\u{200A}\u{202F}\u{205F}\u{3000}] // \v\f removed