mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 12:54:58 +00:00
Simplify
This commit is contained in:
parent
809461cc42
commit
a0e0e4575b
4 changed files with 47 additions and 59 deletions
|
@ -27,6 +27,14 @@ use crate::{
|
|||
pub use ::parser::TopEntryPoint;
|
||||
pub use tt::{Delimiter, DelimiterKind, Punct};
|
||||
|
||||
pub use crate::{
|
||||
syntax_bridge::{
|
||||
parse_exprs_with_sep, parse_to_token_tree, syntax_node_to_token_tree,
|
||||
syntax_node_to_token_tree_censored, token_tree_to_syntax_node,
|
||||
},
|
||||
token_map::TokenMap,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum ParseError {
|
||||
UnexpectedToken(String),
|
||||
|
@ -70,14 +78,6 @@ impl fmt::Display for ExpandError {
|
|||
}
|
||||
}
|
||||
|
||||
pub use crate::{
|
||||
syntax_bridge::{
|
||||
parse_exprs_with_sep, parse_to_token_tree, syntax_node_to_token_tree,
|
||||
syntax_node_to_token_tree_censored, token_tree_to_syntax_node,
|
||||
},
|
||||
token_map::TokenMap,
|
||||
};
|
||||
|
||||
/// This struct contains AST for a single `macro_rules` definition. What might
|
||||
/// be very confusing is that AST has almost exactly the same shape as
|
||||
/// `tt::TokenTree`, but there's a crucial difference: in macro rules, `$ident`
|
||||
|
@ -121,11 +121,9 @@ impl Shift {
|
|||
}
|
||||
}
|
||||
tt::TokenTree::Leaf(leaf) => {
|
||||
let id = match leaf {
|
||||
tt::Leaf::Literal(it) => it.id,
|
||||
tt::Leaf::Punct(it) => it.id,
|
||||
tt::Leaf::Ident(it) => it.id,
|
||||
};
|
||||
let &(tt::Leaf::Ident(tt::Ident { id, .. })
|
||||
| tt::Leaf::Punct(tt::Punct { id, .. })
|
||||
| tt::Leaf::Literal(tt::Literal { id, .. })) = leaf;
|
||||
|
||||
(id != tt::TokenId::unspecified()).then(|| id.0)
|
||||
}
|
||||
|
@ -138,15 +136,15 @@ impl Shift {
|
|||
pub fn shift_all(self, tt: &mut tt::Subtree) {
|
||||
for t in &mut tt.token_trees {
|
||||
match t {
|
||||
tt::TokenTree::Leaf(leaf) => match leaf {
|
||||
tt::Leaf::Ident(ident) => ident.id = self.shift(ident.id),
|
||||
tt::Leaf::Punct(punct) => punct.id = self.shift(punct.id),
|
||||
tt::Leaf::Literal(lit) => lit.id = self.shift(lit.id),
|
||||
},
|
||||
tt::TokenTree::Leaf(
|
||||
tt::Leaf::Ident(tt::Ident { id, .. })
|
||||
| tt::Leaf::Punct(tt::Punct { id, .. })
|
||||
| tt::Leaf::Literal(tt::Literal { id, .. }),
|
||||
) => *id = self.shift(*id),
|
||||
tt::TokenTree::Subtree(tt) => {
|
||||
if let Some(it) = tt.delimiter.as_mut() {
|
||||
it.id = self.shift(it.id);
|
||||
};
|
||||
}
|
||||
self.shift_all(tt)
|
||||
}
|
||||
}
|
||||
|
@ -155,9 +153,10 @@ impl Shift {
|
|||
|
||||
pub fn shift(self, id: tt::TokenId) -> tt::TokenId {
|
||||
if id == tt::TokenId::unspecified() {
|
||||
return id;
|
||||
id
|
||||
} else {
|
||||
tt::TokenId(id.0 + self.0)
|
||||
}
|
||||
tt::TokenId(id.0 + self.0)
|
||||
}
|
||||
|
||||
pub fn unshift(self, id: tt::TokenId) -> Option<tt::TokenId> {
|
||||
|
@ -190,8 +189,8 @@ impl DeclarativeMacro {
|
|||
}
|
||||
}
|
||||
|
||||
for rule in &rules {
|
||||
validate(&rule.lhs)?;
|
||||
for Rule { lhs, .. } in &rules {
|
||||
validate(lhs)?;
|
||||
}
|
||||
|
||||
Ok(DeclarativeMacro { rules, shift: Shift::new(tt) })
|
||||
|
@ -220,12 +219,13 @@ impl DeclarativeMacro {
|
|||
cov_mark::hit!(parse_macro_def_simple);
|
||||
let rule = Rule::parse(&mut src, false)?;
|
||||
if src.len() != 0 {
|
||||
return Err(ParseError::Expected("remain tokens in macro def".to_string()));
|
||||
return Err(ParseError::Expected("remaining tokens in macro def".to_string()));
|
||||
}
|
||||
rules.push(rule);
|
||||
}
|
||||
for rule in &rules {
|
||||
validate(&rule.lhs)?;
|
||||
|
||||
for Rule { lhs, .. } in &rules {
|
||||
validate(lhs)?;
|
||||
}
|
||||
|
||||
Ok(DeclarativeMacro { rules, shift: Shift::new(tt) })
|
||||
|
@ -281,28 +281,18 @@ fn validate(pattern: &MetaTemplate) -> Result<(), ParseError> {
|
|||
Op::Repeat { tokens: subtree, separator, .. } => {
|
||||
// Checks that no repetition which could match an empty token
|
||||
// https://github.com/rust-lang/rust/blob/a58b1ed44f5e06976de2bdc4d7dc81c36a96934f/src/librustc_expand/mbe/macro_rules.rs#L558
|
||||
|
||||
if separator.is_none()
|
||||
&& subtree.iter().all(|child_op| {
|
||||
match child_op {
|
||||
Op::Var { kind, .. } => {
|
||||
// vis is optional
|
||||
if kind.as_ref().map_or(false, |it| it == "vis") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Op::Repeat { kind, .. } => {
|
||||
return matches!(
|
||||
kind,
|
||||
parser::RepeatKind::ZeroOrMore | parser::RepeatKind::ZeroOrOne
|
||||
)
|
||||
}
|
||||
Op::Leaf(_) => {}
|
||||
Op::Subtree { .. } => {}
|
||||
}
|
||||
false
|
||||
})
|
||||
{
|
||||
let lsh_is_empty_seq = separator.is_none() && subtree.iter().all(|child_op| {
|
||||
match child_op {
|
||||
// vis is optional
|
||||
Op::Var { kind: Some(kind), .. } => kind == "vis",
|
||||
Op::Repeat {
|
||||
kind: parser::RepeatKind::ZeroOrMore | parser::RepeatKind::ZeroOrOne,
|
||||
..
|
||||
} => true,
|
||||
_ => false,
|
||||
}
|
||||
});
|
||||
if lsh_is_empty_seq {
|
||||
return Err(ParseError::RepetitionEmptyTokenTree);
|
||||
}
|
||||
validate(subtree)?
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue