syntax: Unsupport foo! bar { ... } macros in the parser

Unreserve `macro_rules` as a macro name
This commit is contained in:
Vadim Petrochenkov
2019-07-01 01:08:49 +03:00
parent 5748825cc8
commit 3f39dc1b90
11 changed files with 70 additions and 186 deletions

View File

@@ -4353,8 +4353,9 @@ impl<'a> Parser<'a> {
(ident, ast::MacroDef { tokens: tokens.into(), legacy: false })
}
token::Ident(name, _) if name == sym::macro_rules &&
self.look_ahead(1, |t| *t == token::Not) => {
token::Ident(name, false) if name == sym::macro_rules &&
self.look_ahead(1, |t| *t == token::Not) &&
self.look_ahead(2, |t| t.is_ident()) => {
let prev_span = self.prev_span;
self.complain_if_pub_macro(&vis.node, prev_span);
self.bump();
@@ -4434,34 +4435,6 @@ impl<'a> Parser<'a> {
}));
}
// it's a macro invocation
let id = match self.token.kind {
token::OpenDelim(_) => Ident::invalid(), // no special identifier
_ => self.parse_ident()?,
};
// check that we're pointing at delimiters (need to check
// again after the `if`, because of `parse_ident`
// consuming more tokens).
match self.token.kind {
token::OpenDelim(_) => {}
_ => {
// we only expect an ident if we didn't parse one
// above.
let ident_str = if id.name == kw::Invalid {
"identifier, "
} else {
""
};
let tok_str = self.this_token_descr();
let mut err = self.fatal(&format!("expected {}`(` or `{{`, found {}",
ident_str,
tok_str));
err.span_label(self.token.span, format!("expected {}`(` or `{{`", ident_str));
return Err(err)
},
}
let (delim, tts) = self.expect_delimited_token_tree()?;
let hi = self.prev_span;
@@ -4471,59 +4444,38 @@ impl<'a> Parser<'a> {
MacStmtStyle::NoBraces
};
if id.name == kw::Invalid {
let mac = respan(lo.to(hi), Mac_ { path: pth, tts, delim });
let node = if delim == MacDelimiter::Brace ||
self.token == token::Semi || self.token == token::Eof {
StmtKind::Mac(P((mac, style, attrs.into())))
}
// We used to incorrectly stop parsing macro-expanded statements here.
// If the next token will be an error anyway but could have parsed with the
// earlier behavior, stop parsing here and emit a warning to avoid breakage.
else if macro_legacy_warnings &&
self.token.can_begin_expr() &&
match self.token.kind {
// These can continue an expression, so we can't stop parsing and warn.
token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) |
token::BinOp(token::Minus) | token::BinOp(token::Star) |
token::BinOp(token::And) | token::BinOp(token::Or) |
token::AndAnd | token::OrOr |
token::DotDot | token::DotDotDot | token::DotDotEq => false,
_ => true,
} {
self.warn_missing_semicolon();
StmtKind::Mac(P((mac, style, attrs.into())))
} else {
let e = self.mk_expr(mac.span, ExprKind::Mac(mac), ThinVec::new());
let e = self.maybe_recover_from_bad_qpath(e, true)?;
let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
StmtKind::Expr(e)
};
Stmt {
id: ast::DUMMY_NODE_ID,
span: lo.to(hi),
node,
}
let mac = respan(lo.to(hi), Mac_ { path: pth, tts, delim });
let node = if delim == MacDelimiter::Brace ||
self.token == token::Semi || self.token == token::Eof {
StmtKind::Mac(P((mac, style, attrs.into())))
}
// We used to incorrectly stop parsing macro-expanded statements here.
// If the next token will be an error anyway but could have parsed with the
// earlier behavior, stop parsing here and emit a warning to avoid breakage.
else if macro_legacy_warnings &&
self.token.can_begin_expr() &&
match self.token.kind {
// These can continue an expression, so we can't stop parsing and warn.
token::OpenDelim(token::Paren) | token::OpenDelim(token::Bracket) |
token::BinOp(token::Minus) | token::BinOp(token::Star) |
token::BinOp(token::And) | token::BinOp(token::Or) |
token::AndAnd | token::OrOr |
token::DotDot | token::DotDotDot | token::DotDotEq => false,
_ => true,
} {
self.warn_missing_semicolon();
StmtKind::Mac(P((mac, style, attrs.into())))
} else {
// if it has a special ident, it's definitely an item
//
// Require a semicolon or braces.
if style != MacStmtStyle::Braces && !self.eat(&token::Semi) {
self.report_invalid_macro_expansion_item();
}
let span = lo.to(hi);
Stmt {
id: ast::DUMMY_NODE_ID,
span,
node: StmtKind::Item({
self.mk_item(
span, id /*id is good here*/,
ItemKind::Mac(respan(span, Mac_ { path: pth, tts, delim })),
respan(lo, VisibilityKind::Inherited),
attrs)
}),
}
let e = self.mk_expr(mac.span, ExprKind::Mac(mac), ThinVec::new());
let e = self.maybe_recover_from_bad_qpath(e, true)?;
let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
StmtKind::Expr(e)
};
Stmt {
id: ast::DUMMY_NODE_ID,
span: lo.to(hi),
node,
}
} else {
// FIXME: Bad copy of attrs
@@ -7611,16 +7563,6 @@ impl<'a> Parser<'a> {
// item macro.
let pth = self.parse_path(PathStyle::Mod)?;
self.expect(&token::Not)?;
// a 'special' identifier (like what `macro_rules!` uses)
// is optional. We should eventually unify invoc syntax
// and remove this.
let id = if self.token.is_ident() {
self.parse_ident()?
} else {
Ident::invalid() // no special identifier
};
// eat a matched-delimiter token tree:
let (delim, tts) = self.expect_delimited_token_tree()?;
if delim != MacDelimiter::Brace && !self.eat(&token::Semi) {
self.report_invalid_macro_expansion_item();
@@ -7628,7 +7570,8 @@ impl<'a> Parser<'a> {
let hi = self.prev_span;
let mac = respan(mac_lo.to(hi), Mac_ { path: pth, tts, delim });
let item = self.mk_item(lo.to(hi), id, ItemKind::Mac(mac), visibility, attrs);
let item =
self.mk_item(lo.to(hi), Ident::invalid(), ItemKind::Mac(mac), visibility, attrs);
return Ok(Some(item));
}