1
Fork 0

Parse paths in statement and pattern macro invocations.

This commit is contained in:
Jeffrey Seyfried 2016-09-22 05:10:16 +00:00
parent dc7ed303f7
commit a0e178db79

View file

@ -3625,29 +3625,16 @@ impl<'a> Parser<'a> {
pat = PatKind::Box(subpat); pat = PatKind::Box(subpat);
} else if self.token.is_path_start() { } else if self.token.is_path_start() {
// Parse pattern starting with a path // Parse pattern starting with a path
if self.token.is_ident() && self.look_ahead(1, |t| *t != token::DotDotDot && if self.token.is_ident() && self.look_ahead(1, |t| match *t {
*t != token::OpenDelim(token::Brace) && token::OpenDelim(token::Paren) | token::OpenDelim(token::Brace) |
*t != token::OpenDelim(token::Paren) && token::DotDotDot | token::ModSep | token::Not => false,
*t != token::ModSep) { _ => true,
// Plain idents have some extra abilities here compared to general paths }) {
if self.look_ahead(1, |t| *t == token::Not) {
// Parse macro invocation
let path = self.parse_ident_into_path()?;
self.bump();
let delim = self.expect_open_delim()?;
let tts = self.parse_seq_to_end(
&token::CloseDelim(delim),
SeqSep::none(), |p| p.parse_token_tree())?;
let mac = Mac_ { path: path, tts: tts };
pat = PatKind::Mac(codemap::Spanned {node: mac,
span: mk_sp(lo, self.last_span.hi)});
} else {
// Parse ident @ pat // Parse ident @ pat
// This can give false positives and parse nullary enums, // This can give false positives and parse nullary enums,
// they are dealt with later in resolve // they are dealt with later in resolve
let binding_mode = BindingMode::ByValue(Mutability::Immutable); let binding_mode = BindingMode::ByValue(Mutability::Immutable);
pat = self.parse_pat_ident(binding_mode)?; pat = self.parse_pat_ident(binding_mode)?;
}
} else { } else {
let (qself, path) = if self.eat_lt() { let (qself, path) = if self.eat_lt() {
// Parse a qualified path // Parse a qualified path
@ -3659,6 +3646,17 @@ impl<'a> Parser<'a> {
(None, self.parse_path(PathStyle::Expr)?) (None, self.parse_path(PathStyle::Expr)?)
}; };
match self.token { match self.token {
token::Not if qself.is_none() => {
// Parse macro invocation
self.bump();
let delim = self.expect_open_delim()?;
let tts = self.parse_seq_to_end(
&token::CloseDelim(delim),
SeqSep::none(), |p| p.parse_token_tree())?;
let mac = Mac_ { path: path, tts: tts };
pat = PatKind::Mac(codemap::Spanned {node: mac,
span: mk_sp(lo, self.last_span.hi)});
}
token::DotDotDot => { token::DotDotDot => {
// Parse range // Parse range
let hi = self.last_span.hi; let hi = self.last_span.hi;
@ -3895,16 +3893,33 @@ impl<'a> Parser<'a> {
node: StmtKind::Local(self.parse_local(attrs.into())?), node: StmtKind::Local(self.parse_local(attrs.into())?),
span: mk_sp(lo, self.last_span.hi), span: mk_sp(lo, self.last_span.hi),
} }
} else if self.token.is_ident() } else if self.token.is_path_start() && self.token != token::Lt && {
&& !self.token.is_any_keyword() !self.check_keyword(keywords::Union) ||
&& self.look_ahead(1, |t| *t == token::Not) { self.look_ahead(1, |t| *t == token::Not || *t == token::ModSep)
// it's a macro invocation: } {
let pth = self.parse_path(PathStyle::Expr)?;
// Potential trouble: if we allow macros with paths instead of if !self.eat(&token::Not) {
// idents, we'd need to look ahead past the whole path here... let expr = if self.check(&token::OpenDelim(token::Brace)) {
let pth = self.parse_ident_into_path()?; self.parse_struct_expr(lo, pth, ThinVec::new())?
self.bump(); } else {
let hi = self.last_span.hi;
self.mk_expr(lo, hi, ExprKind::Path(None, pth), ThinVec::new())
};
let expr = self.with_res(Restrictions::RESTRICTION_STMT_EXPR, |this| {
let expr = this.parse_dot_or_call_expr_with(expr, lo, attrs.into())?;
this.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(expr))
})?;
return Ok(Some(Stmt {
id: ast::DUMMY_NODE_ID,
node: StmtKind::Expr(expr),
span: mk_sp(lo, self.last_span.hi),
}));
}
// it's a macro invocation
let id = match self.token { let id = match self.token {
token::OpenDelim(_) => keywords::Invalid.ident(), // no special identifier token::OpenDelim(_) => keywords::Invalid.ident(), // no special identifier
_ => self.parse_ident()?, _ => self.parse_ident()?,