Merge #11159
11159: minor: Simplify r=Veykril a=Veykril bors r+ Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
commit
bc81dca3dc
4 changed files with 47 additions and 59 deletions
|
@ -27,6 +27,14 @@ use crate::{
|
||||||
pub use ::parser::TopEntryPoint;
|
pub use ::parser::TopEntryPoint;
|
||||||
pub use tt::{Delimiter, DelimiterKind, Punct};
|
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)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub enum ParseError {
|
pub enum ParseError {
|
||||||
UnexpectedToken(String),
|
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
|
/// 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
|
/// 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`
|
/// `tt::TokenTree`, but there's a crucial difference: in macro rules, `$ident`
|
||||||
|
@ -121,11 +121,9 @@ impl Shift {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tt::TokenTree::Leaf(leaf) => {
|
tt::TokenTree::Leaf(leaf) => {
|
||||||
let id = match leaf {
|
let &(tt::Leaf::Ident(tt::Ident { id, .. })
|
||||||
tt::Leaf::Literal(it) => it.id,
|
| tt::Leaf::Punct(tt::Punct { id, .. })
|
||||||
tt::Leaf::Punct(it) => it.id,
|
| tt::Leaf::Literal(tt::Literal { id, .. })) = leaf;
|
||||||
tt::Leaf::Ident(it) => it.id,
|
|
||||||
};
|
|
||||||
|
|
||||||
(id != tt::TokenId::unspecified()).then(|| id.0)
|
(id != tt::TokenId::unspecified()).then(|| id.0)
|
||||||
}
|
}
|
||||||
|
@ -138,15 +136,15 @@ impl Shift {
|
||||||
pub fn shift_all(self, tt: &mut tt::Subtree) {
|
pub fn shift_all(self, tt: &mut tt::Subtree) {
|
||||||
for t in &mut tt.token_trees {
|
for t in &mut tt.token_trees {
|
||||||
match t {
|
match t {
|
||||||
tt::TokenTree::Leaf(leaf) => match leaf {
|
tt::TokenTree::Leaf(
|
||||||
tt::Leaf::Ident(ident) => ident.id = self.shift(ident.id),
|
tt::Leaf::Ident(tt::Ident { id, .. })
|
||||||
tt::Leaf::Punct(punct) => punct.id = self.shift(punct.id),
|
| tt::Leaf::Punct(tt::Punct { id, .. })
|
||||||
tt::Leaf::Literal(lit) => lit.id = self.shift(lit.id),
|
| tt::Leaf::Literal(tt::Literal { id, .. }),
|
||||||
},
|
) => *id = self.shift(*id),
|
||||||
tt::TokenTree::Subtree(tt) => {
|
tt::TokenTree::Subtree(tt) => {
|
||||||
if let Some(it) = tt.delimiter.as_mut() {
|
if let Some(it) = tt.delimiter.as_mut() {
|
||||||
it.id = self.shift(it.id);
|
it.id = self.shift(it.id);
|
||||||
};
|
}
|
||||||
self.shift_all(tt)
|
self.shift_all(tt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -155,10 +153,11 @@ impl Shift {
|
||||||
|
|
||||||
pub fn shift(self, id: tt::TokenId) -> tt::TokenId {
|
pub fn shift(self, id: tt::TokenId) -> tt::TokenId {
|
||||||
if id == tt::TokenId::unspecified() {
|
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> {
|
pub fn unshift(self, id: tt::TokenId) -> Option<tt::TokenId> {
|
||||||
id.0.checked_sub(self.0).map(tt::TokenId)
|
id.0.checked_sub(self.0).map(tt::TokenId)
|
||||||
|
@ -190,8 +189,8 @@ impl DeclarativeMacro {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for rule in &rules {
|
for Rule { lhs, .. } in &rules {
|
||||||
validate(&rule.lhs)?;
|
validate(lhs)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(DeclarativeMacro { rules, shift: Shift::new(tt) })
|
Ok(DeclarativeMacro { rules, shift: Shift::new(tt) })
|
||||||
|
@ -220,12 +219,13 @@ impl DeclarativeMacro {
|
||||||
cov_mark::hit!(parse_macro_def_simple);
|
cov_mark::hit!(parse_macro_def_simple);
|
||||||
let rule = Rule::parse(&mut src, false)?;
|
let rule = Rule::parse(&mut src, false)?;
|
||||||
if src.len() != 0 {
|
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);
|
rules.push(rule);
|
||||||
}
|
}
|
||||||
for rule in &rules {
|
|
||||||
validate(&rule.lhs)?;
|
for Rule { lhs, .. } in &rules {
|
||||||
|
validate(lhs)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(DeclarativeMacro { rules, shift: Shift::new(tt) })
|
Ok(DeclarativeMacro { rules, shift: Shift::new(tt) })
|
||||||
|
@ -281,28 +281,18 @@ fn validate(pattern: &MetaTemplate) -> Result<(), ParseError> {
|
||||||
Op::Repeat { tokens: subtree, separator, .. } => {
|
Op::Repeat { tokens: subtree, separator, .. } => {
|
||||||
// Checks that no repetition which could match an empty token
|
// 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
|
// https://github.com/rust-lang/rust/blob/a58b1ed44f5e06976de2bdc4d7dc81c36a96934f/src/librustc_expand/mbe/macro_rules.rs#L558
|
||||||
|
let lsh_is_empty_seq = separator.is_none() && subtree.iter().all(|child_op| {
|
||||||
if separator.is_none()
|
|
||||||
&& subtree.iter().all(|child_op| {
|
|
||||||
match child_op {
|
match child_op {
|
||||||
Op::Var { kind, .. } => {
|
|
||||||
// vis is optional
|
// vis is optional
|
||||||
if kind.as_ref().map_or(false, |it| it == "vis") {
|
Op::Var { kind: Some(kind), .. } => kind == "vis",
|
||||||
return true;
|
Op::Repeat {
|
||||||
|
kind: parser::RepeatKind::ZeroOrMore | parser::RepeatKind::ZeroOrOne,
|
||||||
|
..
|
||||||
|
} => true,
|
||||||
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
Op::Repeat { kind, .. } => {
|
if lsh_is_empty_seq {
|
||||||
return matches!(
|
|
||||||
kind,
|
|
||||||
parser::RepeatKind::ZeroOrMore | parser::RepeatKind::ZeroOrOne
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Op::Leaf(_) => {}
|
|
||||||
Op::Subtree { .. } => {}
|
|
||||||
}
|
|
||||||
false
|
|
||||||
})
|
|
||||||
{
|
|
||||||
return Err(ParseError::RepetitionEmptyTokenTree);
|
return Err(ParseError::RepetitionEmptyTokenTree);
|
||||||
}
|
}
|
||||||
validate(subtree)?
|
validate(subtree)?
|
||||||
|
|
|
@ -76,9 +76,9 @@ impl PartialEq for Separator {
|
||||||
use Separator::*;
|
use Separator::*;
|
||||||
|
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Ident(ref a), Ident(ref b)) => a.text == b.text,
|
(Ident(a), Ident(b)) => a.text == b.text,
|
||||||
(Literal(ref a), Literal(ref b)) => a.text == b.text,
|
(Literal(a), Literal(b)) => a.text == b.text,
|
||||||
(Puncts(ref a), Puncts(ref b)) if a.len() == b.len() => {
|
(Puncts(a), Puncts(b)) if a.len() == b.len() => {
|
||||||
let a_iter = a.iter().map(|a| a.char);
|
let a_iter = a.iter().map(|a| a.char);
|
||||||
let b_iter = b.iter().map(|b| b.char);
|
let b_iter = b.iter().map(|b| b.char);
|
||||||
a_iter.eq(b_iter)
|
a_iter.eq(b_iter)
|
||||||
|
@ -131,9 +131,7 @@ fn next_op<'a>(first: &tt::TokenTree, src: &mut TtIter<'a>, mode: Mode) -> Resul
|
||||||
Op::Repeat { tokens, separator, kind }
|
Op::Repeat { tokens, separator, kind }
|
||||||
}
|
}
|
||||||
tt::TokenTree::Leaf(leaf) => match leaf {
|
tt::TokenTree::Leaf(leaf) => match leaf {
|
||||||
tt::Leaf::Punct(_) => {
|
tt::Leaf::Punct(_) => return Err(ParseError::Expected("ident".to_string())),
|
||||||
return Err(ParseError::Expected("ident".to_string()));
|
|
||||||
}
|
|
||||||
tt::Leaf::Ident(ident) if ident.text == "crate" => {
|
tt::Leaf::Ident(ident) if ident.text == "crate" => {
|
||||||
// We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path.
|
// We simply produce identifier `$crate` here. And it will be resolved when lowering ast to Path.
|
||||||
Op::Leaf(tt::Leaf::from(tt::Ident { text: "$crate".into(), id: ident.id }))
|
Op::Leaf(tt::Leaf::from(tt::Ident { text: "$crate".into(), id: ident.id }))
|
||||||
|
|
|
@ -81,7 +81,7 @@ pub fn parse_to_token_tree(text: &str) -> Option<(tt::Subtree, TokenMap)> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut conv = RawConvertor {
|
let mut conv = RawConvertor {
|
||||||
lexed: lexed,
|
lexed,
|
||||||
pos: 0,
|
pos: 0,
|
||||||
id_alloc: TokenIdAlloc {
|
id_alloc: TokenIdAlloc {
|
||||||
map: Default::default(),
|
map: Default::default(),
|
||||||
|
@ -147,8 +147,8 @@ fn convert_tokens<C: TokenConvertor>(conv: &mut C) -> tt::Subtree {
|
||||||
let entry = stack.last_mut().unwrap();
|
let entry = stack.last_mut().unwrap();
|
||||||
let result = &mut entry.subtree.token_trees;
|
let result = &mut entry.subtree.token_trees;
|
||||||
let (token, range) = match conv.bump() {
|
let (token, range) = match conv.bump() {
|
||||||
None => break,
|
|
||||||
Some(it) => it,
|
Some(it) => it,
|
||||||
|
None => break,
|
||||||
};
|
};
|
||||||
|
|
||||||
let k: SyntaxKind = token.kind(&conv);
|
let k: SyntaxKind = token.kind(&conv);
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
//! A "Parser" structure for token trees. We use this when parsing a declarative
|
//! A "Parser" structure for token trees. We use this when parsing a declarative
|
||||||
//! macro definition into a list of patterns and templates.
|
//! macro definition into a list of patterns and templates.
|
||||||
|
|
||||||
use crate::{to_parser_input::to_parser_input, ExpandError, ExpandResult};
|
|
||||||
|
|
||||||
use syntax::SyntaxKind;
|
use syntax::SyntaxKind;
|
||||||
use tt::buffer::TokenBuffer;
|
use tt::buffer::TokenBuffer;
|
||||||
|
|
||||||
|
use crate::{to_parser_input::to_parser_input, ExpandError, ExpandResult};
|
||||||
|
|
||||||
macro_rules! err {
|
macro_rules! err {
|
||||||
() => {
|
() => {
|
||||||
ExpandError::BindingError(format!(""))
|
ExpandError::BindingError(format!(""))
|
||||||
|
@ -27,7 +27,7 @@ impl<'a> TtIter<'a> {
|
||||||
|
|
||||||
pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ()> {
|
pub(crate) fn expect_char(&mut self, char: char) -> Result<(), ()> {
|
||||||
match self.next() {
|
match self.next() {
|
||||||
Some(tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: c, .. }))) if *c == char => {
|
Some(&tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: c, .. }))) if c == char => {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
|
|
Loading…
Add table
Reference in a new issue