Skip to content

Commit a0e178d

Browse files
committed
Parse paths in statement and pattern macro invocations.
1 parent dc7ed30 commit a0e178d

File tree

1 file changed

+46
-31
lines changed

1 file changed

+46
-31
lines changed

src/libsyntax/parse/parser.rs

Lines changed: 46 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3625,29 +3625,16 @@ impl<'a> Parser<'a> {
36253625
pat = PatKind::Box(subpat);
36263626
} else if self.token.is_path_start() {
36273627
// Parse pattern starting with a path
3628-
if self.token.is_ident() && self.look_ahead(1, |t| *t != token::DotDotDot &&
3629-
*t != token::OpenDelim(token::Brace) &&
3630-
*t != token::OpenDelim(token::Paren) &&
3631-
*t != token::ModSep) {
3632-
// Plain idents have some extra abilities here compared to general paths
3633-
if self.look_ahead(1, |t| *t == token::Not) {
3634-
// Parse macro invocation
3635-
let path = self.parse_ident_into_path()?;
3636-
self.bump();
3637-
let delim = self.expect_open_delim()?;
3638-
let tts = self.parse_seq_to_end(
3639-
&token::CloseDelim(delim),
3640-
SeqSep::none(), |p| p.parse_token_tree())?;
3641-
let mac = Mac_ { path: path, tts: tts };
3642-
pat = PatKind::Mac(codemap::Spanned {node: mac,
3643-
span: mk_sp(lo, self.last_span.hi)});
3644-
} else {
3645-
// Parse ident @ pat
3646-
// This can give false positives and parse nullary enums,
3647-
// they are dealt with later in resolve
3648-
let binding_mode = BindingMode::ByValue(Mutability::Immutable);
3649-
pat = self.parse_pat_ident(binding_mode)?;
3650-
}
3628+
if self.token.is_ident() && self.look_ahead(1, |t| match *t {
3629+
token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) |
3630+
token::DotDotDot | token::ModSep | token::Not => false,
3631+
_ => true,
3632+
}) {
3633+
// Parse ident @ pat
3634+
// This can give false positives and parse nullary enums,
3635+
// they are dealt with later in resolve
3636+
let binding_mode = BindingMode::ByValue(Mutability::Immutable);
3637+
pat = self.parse_pat_ident(binding_mode)?;
36513638
} else {
36523639
let (qself, path) = if self.eat_lt() {
36533640
// Parse a qualified path
@@ -3659,6 +3646,17 @@ impl<'a> Parser<'a> {
36593646
(None, self.parse_path(PathStyle::Expr)?)
36603647
};
36613648
match self.token {
3649+
token::Not if qself.is_none() => {
3650+
// Parse macro invocation
3651+
self.bump();
3652+
let delim = self.expect_open_delim()?;
3653+
let tts = self.parse_seq_to_end(
3654+
&token::CloseDelim(delim),
3655+
SeqSep::none(), |p| p.parse_token_tree())?;
3656+
let mac = Mac_ { path: path, tts: tts };
3657+
pat = PatKind::Mac(codemap::Spanned {node: mac,
3658+
span: mk_sp(lo, self.last_span.hi)});
3659+
}
36623660
token::DotDotDot => {
36633661
// Parse range
36643662
let hi = self.last_span.hi;
@@ -3895,16 +3893,33 @@ impl<'a> Parser<'a> {
38953893
node: StmtKind::Local(self.parse_local(attrs.into())?),
38963894
span: mk_sp(lo, self.last_span.hi),
38973895
}
3898-
} else if self.token.is_ident()
3899-
&& !self.token.is_any_keyword()
3900-
&& self.look_ahead(1, |t| *t == token::Not) {
3901-
// it's a macro invocation:
3896+
} else if self.token.is_path_start() && self.token != token::Lt && {
3897+
!self.check_keyword(keywords::Union) ||
3898+
self.look_ahead(1, |t| *t == token::Not || *t == token::ModSep)
3899+
} {
3900+
let pth = self.parse_path(PathStyle::Expr)?;
39023901

3903-
// Potential trouble: if we allow macros with paths instead of
3904-
// idents, we'd need to look ahead past the whole path here...
3905-
let pth = self.parse_ident_into_path()?;
3906-
self.bump();
3902+
if !self.eat(&token::Not) {
3903+
let expr = if self.check(&token::OpenDelim(token::Brace)) {
3904+
self.parse_struct_expr(lo, pth, ThinVec::new())?
3905+
} else {
3906+
let hi = self.last_span.hi;
3907+
self.mk_expr(lo, hi, ExprKind::Path(None, pth), ThinVec::new())
3908+
};
3909+
3910+
let expr = self.with_res(Restrictions::RESTRICTION_STMT_EXPR, |this| {
3911+
let expr = this.parse_dot_or_call_expr_with(expr, lo, attrs.into())?;
3912+
this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr))
3913+
})?;
3914+
3915+
return Ok(Some(Stmt {
3916+
id: ast::DUMMY_NODE_ID,
3917+
node: StmtKind::Expr(expr),
3918+
span: mk_sp(lo, self.last_span.hi),
3919+
}));
3920+
}
39073921

3922+
// it's a macro invocation
39083923
let id = match self.token {
39093924
token::OpenDelim(_) => keywords::Invalid.ident(), // no special identifier
39103925
_ => self.parse_ident()?,

0 commit comments

Comments
 (0)