Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/mbe/src/lib.rs')
-rw-r--r--crates/mbe/src/lib.rs83
1 files changed, 61 insertions, 22 deletions
diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs
index 5ef20ff8a9..665bce474a 100644
--- a/crates/mbe/src/lib.rs
+++ b/crates/mbe/src/lib.rs
@@ -34,7 +34,8 @@ pub use ::parser::TopEntryPoint;
pub use crate::{
syntax_bridge::{
- parse_exprs_with_sep, parse_to_token_tree, syntax_node_to_token_tree,
+ parse_exprs_with_sep, parse_to_token_tree, syntax_node_to_token_map,
+ syntax_node_to_token_map_with_modifications, syntax_node_to_token_tree,
syntax_node_to_token_tree_with_modifications, token_tree_to_syntax_node, SyntheticToken,
SyntheticTokenId,
},
@@ -131,6 +132,7 @@ pub struct DeclarativeMacro {
// This is used for correctly determining the behavior of the pat fragment
// FIXME: This should be tracked by hygiene of the fragment identifier!
is_2021: bool,
+ err: Option<Box<ParseError>>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -206,81 +208,118 @@ impl Shift {
}
}
-#[derive(Debug, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Origin {
Def,
Call,
}
impl DeclarativeMacro {
+ pub fn from_err(err: ParseError, is_2021: bool) -> DeclarativeMacro {
+ DeclarativeMacro {
+ rules: Box::default(),
+ shift: Shift(0),
+ is_2021,
+ err: Some(Box::new(err)),
+ }
+ }
+
/// The old, `macro_rules! m {}` flavor.
- pub fn parse_macro_rules(
- tt: &tt::Subtree,
- is_2021: bool,
- ) -> Result<DeclarativeMacro, ParseError> {
+ pub fn parse_macro_rules(tt: &tt::Subtree, is_2021: bool) -> DeclarativeMacro {
// Note: this parsing can be implemented using mbe machinery itself, by
// matching against `$($lhs:tt => $rhs:tt);*` pattern, but implementing
// manually seems easier.
let mut src = TtIter::new(tt);
let mut rules = Vec::new();
+ let mut err = None;
+
while src.len() > 0 {
- let rule = Rule::parse(&mut src, true)?;
+ let rule = match Rule::parse(&mut src, true) {
+ Ok(it) => it,
+ Err(e) => {
+ err = Some(Box::new(e));
+ break;
+ }
+ };
rules.push(rule);
if let Err(()) = src.expect_char(';') {
if src.len() > 0 {
- return Err(ParseError::expected("expected `;`"));
+ err = Some(Box::new(ParseError::expected("expected `;`")));
}
break;
}
}
for Rule { lhs, .. } in &rules {
- validate(lhs)?;
+ if let Err(e) = validate(lhs) {
+ err = Some(Box::new(e));
+ break;
+ }
}
- Ok(DeclarativeMacro { rules: rules.into_boxed_slice(), shift: Shift::new(tt), is_2021 })
+ DeclarativeMacro { rules: rules.into_boxed_slice(), shift: Shift::new(tt), is_2021, err }
}
/// The new, unstable `macro m {}` flavor.
- pub fn parse_macro2(tt: &tt::Subtree, is_2021: bool) -> Result<DeclarativeMacro, ParseError> {
+ pub fn parse_macro2(tt: &tt::Subtree, is_2021: bool) -> DeclarativeMacro {
let mut src = TtIter::new(tt);
let mut rules = Vec::new();
+ let mut err = None;
if tt::DelimiterKind::Brace == tt.delimiter.kind {
cov_mark::hit!(parse_macro_def_rules);
while src.len() > 0 {
- let rule = Rule::parse(&mut src, true)?;
+ let rule = match Rule::parse(&mut src, true) {
+ Ok(it) => it,
+ Err(e) => {
+ err = Some(Box::new(e));
+ break;
+ }
+ };
rules.push(rule);
if let Err(()) = src.expect_any_char(&[';', ',']) {
if src.len() > 0 {
- return Err(ParseError::expected("expected `;` or `,` to delimit rules"));
+ err = Some(Box::new(ParseError::expected(
+ "expected `;` or `,` to delimit rules",
+ )));
}
break;
}
}
} else {
cov_mark::hit!(parse_macro_def_simple);
- let rule = Rule::parse(&mut src, false)?;
- if src.len() != 0 {
- return Err(ParseError::expected("remaining tokens in macro def"));
+ match Rule::parse(&mut src, false) {
+ Ok(rule) => {
+ if src.len() != 0 {
+ err = Some(Box::new(ParseError::expected("remaining tokens in macro def")));
+ }
+ rules.push(rule);
+ }
+ Err(e) => {
+ err = Some(Box::new(e));
+ }
}
- rules.push(rule);
}
for Rule { lhs, .. } in &rules {
- validate(lhs)?;
+ if let Err(e) = validate(lhs) {
+ err = Some(Box::new(e));
+ break;
+ }
}
- Ok(DeclarativeMacro { rules: rules.into_boxed_slice(), shift: Shift::new(tt), is_2021 })
+ DeclarativeMacro { rules: rules.into_boxed_slice(), shift: Shift::new(tt), is_2021, err }
}
- pub fn expand(&self, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
- // apply shift
- let mut tt = tt.clone();
+ pub fn expand(&self, mut tt: tt::Subtree) -> ExpandResult<tt::Subtree> {
self.shift.shift_all(&mut tt);
expander::expand_rules(&self.rules, &tt, self.is_2021)
}
+ pub fn err(&self) -> Option<&ParseError> {
+ self.err.as_deref()
+ }
+
pub fn map_id_down(&self, id: tt::TokenId) -> tt::TokenId {
self.shift.shift(id)
}