Skip to content

Commit b75a93a

Browse files
committed
extract parse_sttmt_mac
1 parent 666ff8f commit b75a93a

File tree

1 file changed

+73
-63
lines changed

1 file changed

+73
-63
lines changed

src/librustc_parse/parser/stmt.rs

Lines changed: 73 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ impl<'a> Parser<'a> {
4444
let lo = self.token.span;
4545

4646
Ok(Some(if self.eat_keyword(kw::Let) {
47-
let stmt = self.parse_local(attrs.into())?;
48-
self.mk_stmt(lo.to(self.prev_span), StmtKind::Local(stmt))
47+
let local = self.parse_local(attrs.into())?;
48+
self.mk_stmt(lo.to(self.prev_span), StmtKind::Local(local))
4949
} else if let Some(macro_def) = self.eat_macro_def(
5050
&attrs,
5151
&respan(lo, VisibilityKind::Inherited),
@@ -56,79 +56,31 @@ impl<'a> Parser<'a> {
5656
// such as a union items, item with `crate` visibility or auto trait items.
5757
// Our goal here is to parse an arbitrary path `a::b::c` but not something that starts
5858
// like a path (1 token), but it fact not a path.
59-
// `union::b::c` - path, `union U { ... }` - not a path.
60-
// `crate::b::c` - path, `crate struct S;` - not a path.
6159
} else if self.token.is_path_start()
6260
&& !self.token.is_qpath_start()
63-
&& !self.is_union_item()
64-
&& !self.is_crate_vis()
61+
&& !self.is_union_item() // `union::b::c` - path, `union U { ... }` - not a path.
62+
&& !self.is_crate_vis() // `crate::b::c` - path, `crate struct S;` - not a path.
6563
&& !self.is_auto_trait_item()
6664
&& !self.is_async_fn()
6765
{
6866
let path = self.parse_path(PathStyle::Expr)?;
6967

70-
if !self.eat(&token::Not) {
71-
let expr = if self.check(&token::OpenDelim(token::Brace)) {
72-
self.parse_struct_expr(lo, path, ThinVec::new())?
73-
} else {
74-
let hi = self.prev_span;
75-
self.mk_expr(lo.to(hi), ExprKind::Path(None, path), ThinVec::new())
76-
};
77-
78-
let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
79-
let expr = this.parse_dot_or_call_expr_with(expr, lo, attrs.into())?;
80-
this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr))
81-
})?;
82-
return Ok(Some(self.mk_stmt(lo.to(self.prev_span), StmtKind::Expr(expr))));
68+
if self.eat(&token::Not) {
69+
return self.parse_stmt_mac(lo, attrs.into(), path, macro_legacy_warnings);
8370
}
8471

85-
let args = self.parse_mac_args()?;
86-
let delim = args.delim();
87-
let hi = self.prev_span;
88-
89-
let style = if delim == token::Brace {
90-
MacStmtStyle::Braces
72+
let expr = if self.check(&token::OpenDelim(token::Brace)) {
73+
self.parse_struct_expr(lo, path, ThinVec::new())?
9174
} else {
92-
MacStmtStyle::NoBraces
93-
};
94-
95-
let mac = Mac {
96-
path,
97-
args,
98-
prior_type_ascription: self.last_type_ascription,
75+
let hi = self.prev_span;
76+
self.mk_expr(lo.to(hi), ExprKind::Path(None, path), ThinVec::new())
9977
};
10078

101-
let kind = if delim == token::Brace
102-
|| self.token == token::Semi
103-
|| self.token == token::Eof
104-
{
105-
StmtKind::Mac(P((mac, style, attrs.into())))
106-
}
107-
// We used to incorrectly stop parsing macro-expanded statements here.
108-
// If the next token will be an error anyway but could have parsed with the
109-
// earlier behavior, stop parsing here and emit a warning to avoid breakage.
110-
else if macro_legacy_warnings
111-
&& self.token.can_begin_expr()
112-
&& match self.token.kind {
113-
// These can continue an expression, so we can't stop parsing and warn.
114-
token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) |
115-
token::BinOp(token::Minus) | token::BinOp(token::Star) |
116-
token::BinOp(token::And) | token::BinOp(token::Or) |
117-
token::AndAnd | token::OrOr |
118-
token::DotDot | token::DotDotDot | token::DotDotEq => false,
119-
_ => true,
120-
}
121-
{
122-
self.warn_missing_semicolon();
123-
StmtKind::Mac(P((mac, style, attrs.into())))
124-
} else {
125-
let e = self.mk_expr(lo.to(hi), ExprKind::Mac(mac), ThinVec::new());
126-
let e = self.maybe_recover_from_bad_qpath(e, true)?;
127-
let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
128-
let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
129-
StmtKind::Expr(e)
130-
};
131-
self.mk_stmt(lo.to(hi), kind)
79+
let expr = self.with_res(Restrictions::STMT_EXPR, |this| {
80+
let expr = this.parse_dot_or_call_expr_with(expr, lo, attrs.into())?;
81+
this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr))
82+
})?;
83+
return Ok(Some(self.mk_stmt(lo.to(self.prev_span), StmtKind::Expr(expr))));
13284
} else {
13385
// FIXME: Bad copy of attrs
13486
let old_directory_ownership =
@@ -184,6 +136,64 @@ impl<'a> Parser<'a> {
184136
}))
185137
}
186138

139+
/// Parses a statement macro `mac!(args)` provided a `path` representing `mac`.
140+
/// At this point, the `!` token after the path has already been eaten.
141+
fn parse_stmt_mac(
142+
&mut self,
143+
lo: Span,
144+
attrs: ThinVec<Attribute>,
145+
path: ast::Path,
146+
legacy_warnings: bool,
147+
) -> PResult<'a, Option<Stmt>> {
148+
let args = self.parse_mac_args()?;
149+
let delim = args.delim();
150+
let hi = self.prev_span;
151+
152+
let style = if delim == token::Brace {
153+
MacStmtStyle::Braces
154+
} else {
155+
MacStmtStyle::NoBraces
156+
};
157+
158+
let mac = Mac {
159+
path,
160+
args,
161+
prior_type_ascription: self.last_type_ascription,
162+
};
163+
164+
let kind = if delim == token::Brace
165+
|| self.token == token::Semi
166+
|| self.token == token::Eof
167+
{
168+
StmtKind::Mac(P((mac, style, attrs.into())))
169+
}
170+
// We used to incorrectly stop parsing macro-expanded statements here.
171+
// If the next token will be an error anyway but could have parsed with the
172+
// earlier behavior, stop parsing here and emit a warning to avoid breakage.
173+
else if legacy_warnings
174+
&& self.token.can_begin_expr()
175+
&& match self.token.kind {
176+
// These can continue an expression, so we can't stop parsing and warn.
177+
token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) |
178+
token::BinOp(token::Minus) | token::BinOp(token::Star) |
179+
token::BinOp(token::And) | token::BinOp(token::Or) |
180+
token::AndAnd | token::OrOr |
181+
token::DotDot | token::DotDotDot | token::DotDotEq => false,
182+
_ => true,
183+
}
184+
{
185+
self.warn_missing_semicolon();
186+
StmtKind::Mac(P((mac, style, attrs)))
187+
} else {
188+
let e = self.mk_expr(lo.to(hi), ExprKind::Mac(mac), ThinVec::new());
189+
let e = self.maybe_recover_from_bad_qpath(e, true)?;
190+
let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
191+
let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
192+
StmtKind::Expr(e)
193+
};
194+
Ok(Some(self.mk_stmt(lo.to(hi), kind)))
195+
}
196+
187197
/// Parses a local variable declaration.
188198
fn parse_local(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Local>> {
189199
let lo = self.prev_span;

0 commit comments

Comments
 (0)