1
Fork 0

syntax: Make static/super/self/Self keywords + special ident cleanup

This commit is contained in:
Vadim Petrochenkov 2016-04-16 18:05:06 +03:00
parent 546c052d22
commit e2c821d35e
28 changed files with 138 additions and 188 deletions

View file

@ -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");