use ast::Ident;
use syntax_pos::{self, BytePos, Span};
-use codemap::Spanned;
+use codemap::respan;
use errors::FatalError;
use ext::tt::quoted::{self, TokenTree};
use parse::{Directory, ParseSess};
}
}
+/// The token is an identifier, but not `_`.
+/// We prohibit passing `_` to macros expecting `ident` for now.
+fn get_macro_ident(token: &Token) -> Option<Ident> {
+ match *token {
+ token::Ident(ident) if ident.name != keywords::Underscore.name() => Some(ident),
+ _ => None,
+ }
+}
+
/// Checks whether a non-terminal may begin with a particular token.
///
/// Returning `false` is a *stability guarantee* that such a matcher will *never* begin with that
match name {
"expr" => token.can_begin_expr(),
"ty" => token.can_begin_type(),
- "ident" => token.is_ident(),
+ "ident" => get_macro_ident(token).is_some(),
"vis" => match *token {
// The follow-set of :vis + "priv" keyword + interpolated
Token::Comma | Token::Ident(_) | Token::Interpolated(_) => true,
"expr" => token::NtExpr(panictry!(p.parse_expr())),
"ty" => token::NtTy(panictry!(p.parse_ty())),
// this could be handled like a token, since it is one
- "ident" => match p.token {
- token::Ident(sn) => {
- p.bump();
- token::NtIdent(Spanned::<Ident> {
- node: sn,
- span: p.prev_span,
- })
- }
- _ => {
- let token_str = pprust::token_to_string(&p.token);
- p.fatal(&format!("expected ident, found {}", &token_str[..]))
- .emit();
- FatalError.raise()
- }
- },
+ "ident" => if let Some(ident) = get_macro_ident(&p.token) {
+ p.bump();
+ token::NtIdent(respan(p.prev_span, ident))
+ } else {
+ let token_str = pprust::token_to_string(&p.token);
+ p.fatal(&format!("expected ident, found {}", &token_str)).emit();
+ FatalError.raise()
+ }
"path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))),
"meta" => token::NtMeta(panictry!(p.parse_meta_item())),
"vis" => token::NtVis(panictry!(p.parse_visibility(true))),
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! identity {
+ ($i: ident) => (
+ $i
+ )
+}
+
+fn main() {
+ let identity!(_) = 10; //~ ERROR no rules expected the token `_`
+}