syntax: Make static/super/self/Self keywords + special ident cleanup
This commit is contained in:
parent
546c052d22
commit
e2c821d35e
28 changed files with 138 additions and 188 deletions
|
@ -271,47 +271,39 @@ impl Token {
|
|||
/// Returns `true` if the token is a given keyword, `kw`.
|
||||
pub fn is_keyword(&self, kw: keywords::Keyword) -> bool {
|
||||
match *self {
|
||||
Ident(id) => id.name == kw.to_name(),
|
||||
Ident(id) => id.name == kw.ident.name,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_path_segment_keyword(&self) -> bool {
|
||||
match *self {
|
||||
Ident(id) => id.name == SUPER_KEYWORD_NAME ||
|
||||
id.name == SELF_KEYWORD_NAME ||
|
||||
id.name == SELF_TYPE_KEYWORD_NAME,
|
||||
Ident(id) => id.name == keywords::Super.ident.name ||
|
||||
id.name == keywords::SelfValue.ident.name ||
|
||||
id.name == keywords::SelfType.ident.name,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the token is either a strict or reserved keyword.
|
||||
/// Returns `true` if the token is either a used or reserved keyword.
|
||||
pub fn is_any_keyword(&self) -> bool {
|
||||
match *self {
|
||||
Ident(id) => id.name == SELF_KEYWORD_NAME ||
|
||||
id.name == STATIC_KEYWORD_NAME ||
|
||||
id.name == SUPER_KEYWORD_NAME ||
|
||||
id.name == SELF_TYPE_KEYWORD_NAME ||
|
||||
id.name >= STRICT_KEYWORD_START &&
|
||||
Ident(id) => id.name >= USED_KEYWORD_START &&
|
||||
id.name <= RESERVED_KEYWORD_FINAL,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the token is either a strict keyword.
|
||||
pub fn is_strict_keyword(&self) -> bool {
|
||||
/// Returns `true` if the token is a used keyword.
|
||||
pub fn is_used_keyword(&self) -> bool {
|
||||
match *self {
|
||||
Ident(id) => id.name == SELF_KEYWORD_NAME ||
|
||||
id.name == STATIC_KEYWORD_NAME ||
|
||||
id.name == SUPER_KEYWORD_NAME ||
|
||||
id.name == SELF_TYPE_KEYWORD_NAME ||
|
||||
id.name >= STRICT_KEYWORD_START &&
|
||||
id.name <= STRICT_KEYWORD_FINAL,
|
||||
Ident(id) => id.name >= USED_KEYWORD_START &&
|
||||
id.name <= USED_KEYWORD_FINAL,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the token is either a keyword reserved for possible future use.
|
||||
/// Returns `true` if the token is a keyword reserved for possible future use.
|
||||
pub fn is_reserved_keyword(&self) -> bool {
|
||||
match *self {
|
||||
Ident(id) => id.name >= RESERVED_KEYWORD_START &&
|
||||
|
@ -378,7 +370,6 @@ impl fmt::Debug for Nonterminal {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Get the first "argument"
|
||||
macro_rules! first {
|
||||
( $first:expr, $( $remainder:expr, )* ) => ( $first )
|
||||
|
@ -392,122 +383,85 @@ macro_rules! last {
|
|||
|
||||
// In this macro, there is the requirement that the name (the number) must be monotonically
|
||||
// increasing by one in the special identifiers, starting at 0; the same holds for the keywords,
|
||||
// except starting from the next number instead of zero, and with the additional exception that
|
||||
// special identifiers are *also* allowed (they are deduplicated in the important place, the
|
||||
// interner), an exception which is demonstrated by "static" and "self".
|
||||
// except starting from the next number instead of zero.
|
||||
macro_rules! declare_special_idents_and_keywords {(
|
||||
// So now, in these rules, why is each definition parenthesised?
|
||||
// Answer: otherwise we get a spurious local ambiguity bug on the "}"
|
||||
pub mod special_idents {
|
||||
$( ($si_name:expr, $si_static:ident, $si_str:expr); )*
|
||||
$( ($si_index: expr, $si_const: ident, $si_str: expr); )*
|
||||
}
|
||||
|
||||
pub mod keywords {
|
||||
'strict:
|
||||
$( ($sk_name:expr, $sk_variant:ident, $sk_str:expr); )*
|
||||
'used:
|
||||
$( ($ukw_index: expr, $ukw_const: ident, $ukw_str: expr); )*
|
||||
'reserved:
|
||||
$( ($rk_name:expr, $rk_variant:ident, $rk_str:expr); )*
|
||||
$( ($rkw_index: expr, $rkw_const: ident, $rkw_str: expr); )*
|
||||
}
|
||||
) => {
|
||||
const STRICT_KEYWORD_START: ast::Name = first!($( ast::Name($sk_name), )*);
|
||||
const STRICT_KEYWORD_FINAL: ast::Name = last!($( ast::Name($sk_name), )*);
|
||||
const RESERVED_KEYWORD_START: ast::Name = first!($( ast::Name($rk_name), )*);
|
||||
const RESERVED_KEYWORD_FINAL: ast::Name = last!($( ast::Name($rk_name), )*);
|
||||
const USED_KEYWORD_START: ast::Name = first!($( ast::Name($ukw_index), )*);
|
||||
const USED_KEYWORD_FINAL: ast::Name = last!($( ast::Name($ukw_index), )*);
|
||||
const RESERVED_KEYWORD_START: ast::Name = first!($( ast::Name($rkw_index), )*);
|
||||
const RESERVED_KEYWORD_FINAL: ast::Name = last!($( ast::Name($rkw_index), )*);
|
||||
|
||||
pub mod special_idents {
|
||||
use ast;
|
||||
$(
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const $si_static: ast::Ident = ast::Ident {
|
||||
name: ast::Name($si_name),
|
||||
ctxt: ast::EMPTY_CTXT,
|
||||
};
|
||||
)*
|
||||
}
|
||||
|
||||
pub mod special_names {
|
||||
use ast;
|
||||
$(
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const $si_static: ast::Name = ast::Name($si_name);
|
||||
pub const $si_const: ast::Ident = ast::Ident::with_empty_ctxt(ast::Name($si_index));
|
||||
)*
|
||||
}
|
||||
|
||||
/// All the valid words that have meaning in the Rust language.
|
||||
///
|
||||
/// Rust keywords are either 'strict' or 'reserved'. Strict keywords may not
|
||||
/// appear as identifiers at all. Reserved keywords are not used anywhere in
|
||||
/// the language and may not appear as identifiers.
|
||||
/// Rust keywords are either 'used' in the language or 'reserved' for future use.
|
||||
pub mod keywords {
|
||||
pub use self::Keyword::*;
|
||||
use ast;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Keyword {
|
||||
$( $sk_variant, )*
|
||||
$( $rk_variant, )*
|
||||
}
|
||||
|
||||
impl Keyword {
|
||||
pub fn to_name(&self) -> ast::Name {
|
||||
match *self {
|
||||
$( $sk_variant => ast::Name($sk_name), )*
|
||||
$( $rk_variant => ast::Name($rk_name), )*
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Keyword {
|
||||
pub ident: ast::Ident,
|
||||
}
|
||||
$(
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const $ukw_const: Keyword = Keyword {
|
||||
ident: ast::Ident::with_empty_ctxt(ast::Name($ukw_index))
|
||||
};
|
||||
)*
|
||||
$(
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const $rkw_const: Keyword = Keyword {
|
||||
ident: ast::Ident::with_empty_ctxt(ast::Name($rkw_index))
|
||||
};
|
||||
)*
|
||||
}
|
||||
|
||||
fn mk_fresh_ident_interner() -> IdentInterner {
|
||||
let mut init_vec = Vec::new();
|
||||
$(init_vec.push($si_str);)*
|
||||
$(init_vec.push($sk_str);)*
|
||||
$(init_vec.push($rk_str);)*
|
||||
interner::StrInterner::prefill(&init_vec[..])
|
||||
interner::StrInterner::prefill(&[$($si_str,)* $($ukw_str,)* $($rkw_str,)*])
|
||||
}
|
||||
}}
|
||||
|
||||
// If the special idents get renumbered, remember to modify these two as appropriate
|
||||
pub const SELF_KEYWORD_NAME: ast::Name = ast::Name(SELF_KEYWORD_NAME_NUM);
|
||||
const STATIC_KEYWORD_NAME: ast::Name = ast::Name(STATIC_KEYWORD_NAME_NUM);
|
||||
pub const SUPER_KEYWORD_NAME: ast::Name = ast::Name(SUPER_KEYWORD_NAME_NUM);
|
||||
const SELF_TYPE_KEYWORD_NAME: ast::Name = ast::Name(SELF_TYPE_KEYWORD_NAME_NUM);
|
||||
|
||||
pub const SELF_KEYWORD_NAME_NUM: u32 = 1;
|
||||
const STATIC_KEYWORD_NAME_NUM: u32 = 2;
|
||||
const SUPER_KEYWORD_NAME_NUM: u32 = 3;
|
||||
const SELF_TYPE_KEYWORD_NAME_NUM: u32 = 10;
|
||||
|
||||
// NB: leaving holes in the ident table is bad! a different ident will get
|
||||
// interned with the id from the hole, but it will be between the min and max
|
||||
// of the reserved words, and thus tagged as "reserved".
|
||||
|
||||
declare_special_idents_and_keywords! {
|
||||
pub mod special_idents {
|
||||
// These ones are statics
|
||||
(0, invalid, "");
|
||||
(super::SELF_KEYWORD_NAME_NUM, self_, "self");
|
||||
(super::STATIC_KEYWORD_NAME_NUM, statik, "static");
|
||||
(super::SUPER_KEYWORD_NAME_NUM, super_, "super");
|
||||
(4, static_lifetime, "'static");
|
||||
|
||||
// for matcher NTs
|
||||
(5, tt, "tt");
|
||||
(6, matchers, "matchers");
|
||||
|
||||
// outside of libsyntax
|
||||
(7, clownshoe_abi, "__rust_abi");
|
||||
(8, opaque, "<opaque>");
|
||||
(9, __unused1, "<__unused1>");
|
||||
(super::SELF_TYPE_KEYWORD_NAME_NUM, type_self, "Self");
|
||||
(11, prelude_import, "prelude_import");
|
||||
(12, DEFAULT, "default");
|
||||
// Special identifiers
|
||||
(0, Invalid, "");
|
||||
(1, __Unused1, "<__unused1>");
|
||||
(2, __Unused2, "<__unused2>");
|
||||
(3, __Unused3, "<__unused3>");
|
||||
(4, __Unused4, "<__unused4>");
|
||||
(5, __Unused5, "<__unused5>");
|
||||
(6, Union, "union");
|
||||
(7, Default, "default");
|
||||
(8, StaticLifetime, "'static");
|
||||
}
|
||||
|
||||
pub mod keywords {
|
||||
// These ones are variants of the Keyword enum
|
||||
|
||||
'strict:
|
||||
// Keywords
|
||||
'used:
|
||||
(9, Static, "static");
|
||||
(10, Super, "super");
|
||||
(11, SelfValue, "self");
|
||||
(12, SelfType, "Self");
|
||||
(13, As, "as");
|
||||
(14, Break, "break");
|
||||
(15, Crate, "crate");
|
||||
|
@ -529,12 +483,7 @@ declare_special_idents_and_keywords! {
|
|||
(31, Pub, "pub");
|
||||
(32, Ref, "ref");
|
||||
(33, Return, "return");
|
||||
// Static and Self are also special idents (prefill de-dupes)
|
||||
(super::STATIC_KEYWORD_NAME_NUM, Static, "static");
|
||||
(super::SELF_KEYWORD_NAME_NUM, SelfValue, "self");
|
||||
(super::SELF_TYPE_KEYWORD_NAME_NUM, SelfType, "Self");
|
||||
(34, Struct, "struct");
|
||||
(super::SUPER_KEYWORD_NAME_NUM, Super, "super");
|
||||
(35, True, "true");
|
||||
(36, Trait, "trait");
|
||||
(37, Type, "type");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue