in guard/src/rules/parser.rs [841:915]
fn clause_with_map<'loc, A, M, T: 'loc>(input: Span<'loc>,
access: A,
mapper: M) -> IResult<Span<'loc>, T>
where A: Fn(Span<'loc>) -> IResult<Span<'loc>, AccessQuery<'loc>>,
M: Fn(GuardAccessClause<'loc>) -> T + 'loc
{
let location = FileLocation {
file_name: input.extra,
line: input.location_line(),
column: input.get_utf8_column() as u32,
};
let (rest, not) = preceded( zero_or_more_ws_or_comment, opt(not))(input)?;
let (rest, (query, cmp)) = map(tuple((
|a| access(a),
context("expecting one or more WS or comment blocks", zero_or_more_ws_or_comment),
// error if there is no value_cmp, has to exist
context("expecting comparison binary operators like >, <= or unary operators KEYS, EXISTS, EMPTY or NOT",
value_cmp)
)), |(query, _ign, value)| {
(query, value)
})(rest)?;
if !does_comparator_have_rhs(&cmp.0) {
let (rest, custom_message) = map(preceded(zero_or_more_ws_or_comment, opt(custom_message)),
|msg| {
msg.map(String::from)
})(rest)?;
Ok((rest,
mapper(
GuardAccessClause {
access_clause: AccessClause {
query,
comparator: cmp,
compare_with: None,
custom_message,
location,
},
negation: not.is_some() }
)))
}
else {
let (rest, (compare_with, custom_message)) =
context("expecting either a property access \"engine.core\" or value like \"string\" or [\"this\", \"that\"]",
cut(alt((
//
// Order does matter here as true/false and other values can be interpreted as access
//
map(tuple((
parse_value, preceded(zero_or_more_ws_or_comment, opt(custom_message)))),
move |(rhs, msg)| {
(Some(LetValue::Value(rhs)), msg.map(String::from).or(None))
}),
map(tuple((
preceded(zero_or_more_ws_or_comment, access),
preceded(zero_or_more_ws_or_comment, opt(custom_message)))),
|(rhs, msg)| {
(Some(LetValue::AccessClause(rhs)), msg.map(String::from).or(None))
}),
))))(rest)?;
Ok((rest,
mapper(
GuardAccessClause {
access_clause: AccessClause {
query,
comparator: cmp,
compare_with,
custom_message,
location,
},
negation: not.is_some()
})
))
}
}