Here's a more interesting example, consider this:
/// predicate <- ':' ( '?' -> MarkSkippable ) '$' ( identifier -> Predicate )
fn predicate(&mut self, s: &mut &'s str) -> Result<bool, PatternError<'s>> {
let mut cursor = *s;
Ok(
strip_prefix(&mut cursor, ":")
&&
{
let skippable = strip_prefix(&mut cursor, "?");
strip_prefix(&mut cursor, "$")
&&
{
let start = cursor;
self.identifier(&mut cursor)?
&&
{
let name = &start[..pos_of(start, cursor).unwrap()];
// TODO move predicate from self.preds into
// self.consts.predicates and add id to self.pred_ids
let id = todo!();
let proto = self.consts.protos.last_mut().expect("protos");
proto.push(PatternElement::ApplyPredicate(id, skippable, std::marker::PhantomData));
*s = cursor;
true
}
}
}
)
}
It would be nice if it could be instead:
/// predicate <- ':' ( '?' -> MarkSkippable ) '$' ( identifier -> Predicate )
fn predicate(&mut self, s: &mut &'s str) -> Result<bool, PatternError<'s>> {
let mut cursor = *s;
Ok(
'matches: {
strip_prefix(&mut cursor, ":") 'matches?;
let skippable = strip_prefix(&mut cursor, "?");
strip_prefix(&mut cursor, "$") 'matches?;
let start = cursor;
self.identifier(&mut cursor)? 'matches?;
let name = &start[..pos_of(start, cursor).unwrap()];
// TODO move predicate from self.preds into
// self.consts.predicates and add id to self.pred_ids
let id = todo!();
let proto = self.consts.protos.last_mut().expect("protos");
proto.push(PatternElement::ApplyPredicate(id, skippable, std::marker::PhantomData));
*s = cursor;
true
}
)
}
And lib-based solutions would provide forward drift, which is less than ideal in this case.
A macro-based solution can work tho:
/// predicate <- ':' ( '?'? -> MarkSkippable ) '$' ( identifier -> Predicate )
fn predicate(&mut self, s: &mut &'s str) -> Result<bool, PatternError<'s>> {
let mut cursor = *s;
Ok(lblock!('matches: {
bry!('matches strip_prefix(&mut cursor, ":"));
let skippable = strip_prefix(&mut cursor, "?");
bry!('matches strip_prefix(&mut cursor, "$"));
let start = cursor;
bry!('matches self.identifier(&mut cursor)?);
let name = &start[..pos_of(start, cursor).unwrap()];
// TODO move predicate from self.preds into
// self.consts.predicates and add id to self.pred_ids
let id = todo!();
let proto = self.consts.protos.last_mut().expect("protos");
proto.push(PatternElement::ApplyPredicate(id, skippable, std::marker::PhantomData));
*s = cursor;
true
}))
}