Skip to content

Commit 901d2e1

Browse files
committed
refactor out a general reject method
We are going to rework the way that variables are given precedence to use explicit rejection instead.
1 parent 0f04609 commit 901d2e1

File tree

1 file changed

+39
-17
lines changed

1 file changed

+39
-17
lines changed

crates/formality-core/src/parse/parser.rs

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -380,35 +380,57 @@ where
380380
}
381381
}
382382

383-
/// Reject next identifier-like string if it is one of the given list of keywords.
384-
/// Does not consume any input.
385-
/// You can this to implement positional keywords -- just before parsing an identifier or variable,
386-
/// you can invoke `reject_custom_keywords` to reject anything that you don't want to permit in this position.
383+
/// Accepts any of the given keywords.
387384
#[tracing::instrument(level = "trace", ret)]
388-
pub fn reject_custom_keywords(&self, keywords: &[&str]) -> Result<(), Set<ParseError<'t>>> {
385+
pub fn expect_keyword_in(&mut self, expected: &[&str]) -> Result<String, Set<ParseError<'t>>> {
386+
let text0 = self.text;
387+
match self.identifier_like_string() {
388+
Ok(ident) if expected.iter().any(|&kw| ident == kw) => Ok(ident),
389+
_ => Err(ParseError::at(
390+
skip_whitespace(text0),
391+
format!("expected any of `{:?}`", expected),
392+
)),
393+
}
394+
}
395+
396+
/// Attempts to execute `op` and, if it successfully parses, then returns an error
397+
/// with the value (which is meant to be incorporated into a par)
398+
/// If `op` fails to parse then the result is `Ok`.
399+
pub fn reject<T>(
400+
&self,
401+
op: impl Fn(&mut ActiveVariant<'s, 't, L>) -> Result<T, Set<ParseError<'t>>>,
402+
err: impl FnOnce(T) -> Set<ParseError<'t>>,
403+
) -> Result<(), Set<ParseError<'t>>> {
389404
let mut this = ActiveVariant {
390405
text: self.text,
391406
reductions: vec![],
392407
scope: self.scope,
393408
is_cast_variant: false,
394409
};
395410

396-
match this.identifier_like_string() {
397-
Ok(ident) => {
398-
if keywords.iter().any(|&kw| kw == ident) {
399-
return Err(ParseError::at(
400-
self.text,
401-
format!("expected identified, found keyword `{ident:?}`"),
402-
));
403-
}
404-
405-
Ok(())
406-
}
407-
411+
match op(&mut this) {
412+
Ok(value) => Err(err(value)),
408413
Err(_) => Ok(()),
409414
}
410415
}
411416

417+
/// Reject next identifier-like string if it is one of the given list of keywords.
418+
/// Does not consume any input.
419+
/// You can this to implement positional keywords -- just before parsing an identifier or variable,
420+
/// you can invoke `reject_custom_keywords` to reject anything that you don't want to permit in this position.
421+
#[tracing::instrument(level = "trace", ret)]
422+
pub fn reject_custom_keywords(&self, keywords: &[&str]) -> Result<(), Set<ParseError<'t>>> {
423+
self.reject(
424+
|p| p.expect_keyword_in(keywords),
425+
|ident| {
426+
ParseError::at(
427+
self.text,
428+
format!("expected identified, found keyword `{ident:?}`"),
429+
)
430+
},
431+
)
432+
}
433+
412434
/// Extracts a string that meets the regex for an identifier
413435
/// (but it could also be a keyword).
414436
#[tracing::instrument(level = "trace", ret)]

0 commit comments

Comments
 (0)