mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-29 21:35:20 +00:00
Infallibe ExpandDatabase::macro_def
This commit is contained in:
parent
4ff93398fd
commit
d5f64f875a
10 changed files with 215 additions and 164 deletions
|
@ -132,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)]
|
||||
|
@ -214,65 +215,100 @@ pub enum Origin {
|
|||
}
|
||||
|
||||
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> {
|
||||
|
@ -282,6 +318,10 @@ impl DeclarativeMacro {
|
|||
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)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue