1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
14 use util::interner::Interner;
18 use core::hashmap::HashSet;
41 /* Expression-operator symbols. */
56 /* Structural symbols */
78 LIT_INT(i64, ast::int_ty),
79 LIT_UINT(u64, ast::uint_ty),
80 LIT_INT_UNSUFFIXED(i64),
81 LIT_FLOAT(ast::ident, ast::float_ty),
82 LIT_FLOAT_UNSUFFIXED(ast::ident),
86 // an identifier contains an "is_mod_name" boolean,
87 // indicating whether :: follows this token with no
88 // whitespace in between.
89 IDENT(ast::ident, bool),
93 /* For interpolation */
94 INTERPOLATED(nonterminal),
96 DOC_COMMENT(ast::ident),
103 /// For interpolation during macro expansion.
104 pub enum nonterminal {
111 nt_ident(ast::ident, bool),
113 nt_tt( @ast::token_tree), //needs @ed to break a circularity
114 nt_matchers(~[ast::matcher])
117 pub fn binop_to_str(o: binop) -> ~str {
132 pub fn to_str(in: @ident_interner, t: &Token) -> ~str {
145 BINOP(op) => binop_to_str(op),
146 BINOPEQ(op) => binop_to_str(op) + ~"=",
148 /* Structural symbols */
170 LIT_INT(c, ast::ty_char) => {
171 ~"'" + char::escape_default(c as char) + ~"'"
174 i.to_str() + ast_util::int_ty_to_str(t)
177 u.to_str() + ast_util::uint_ty_to_str(t)
179 LIT_INT_UNSUFFIXED(i) => { i.to_str() }
181 let mut body = copy *in.get(s);
182 if body.ends_with(~".") {
183 body = body + ~"0"; // `10.f` is not a float literal
185 body + ast_util::float_ty_to_str(t)
187 LIT_FLOAT_UNSUFFIXED(s) => {
188 let mut body = copy *in.get(s);
189 if body.ends_with(~".") {
190 body = body + ~"0"; // `10.f` is not a float literal
194 LIT_STR(s) => { ~"\"" + str::escape_default(*in.get(s)) + ~"\"" }
196 /* Name components */
197 IDENT(s, _) => copy *in.get(s),
198 LIFETIME(s) => fmt!("'%s", *in.get(s)),
202 DOC_COMMENT(s) => copy *in.get(s),
204 INTERPOLATED(ref nt) => {
206 &nt_expr(e) => ::print::pprust::expr_to_str(e, in),
208 ~"an interpolated " +
210 nt_item(*) => ~"item",
211 nt_block(*) => ~"block",
212 nt_stmt(*) => ~"statement",
213 nt_pat(*) => ~"pattern",
214 nt_expr(*) => fail!(~"should have been handled above"),
216 nt_ident(*) => ~"identifier",
217 nt_path(*) => ~"path",
219 nt_matchers(*) => ~"matcher sequence"
227 pub fn can_begin_expr(t: &Token) -> bool {
235 LIT_INT(_, _) => true,
236 LIT_UINT(_, _) => true,
237 LIT_INT_UNSUFFIXED(_) => true,
238 LIT_FLOAT(_, _) => true,
239 LIT_FLOAT_UNSUFFIXED(_) => true,
244 BINOP(MINUS) => true,
247 BINOP(OR) => true, // in lambda syntax
248 OROR => true, // in lambda syntax
250 INTERPOLATED(nt_expr(*))
251 | INTERPOLATED(nt_ident(*))
252 | INTERPOLATED(nt_block(*))
253 | INTERPOLATED(nt_path(*)) => true,
258 /// what's the opposite delimiter?
259 pub fn flip_delimiter(t: &token::Token) -> token::Token {
263 LBRACKET => RBRACKET,
266 RBRACKET => LBRACKET,
273 pub fn is_lit(t: &Token) -> bool {
275 LIT_INT(_, _) => true,
276 LIT_UINT(_, _) => true,
277 LIT_INT_UNSUFFIXED(_) => true,
278 LIT_FLOAT(_, _) => true,
279 LIT_FLOAT_UNSUFFIXED(_) => true,
285 pub fn is_ident(t: &Token) -> bool {
286 match *t { IDENT(_, _) => true, _ => false }
289 pub fn is_ident_or_path(t: &Token) -> bool {
291 IDENT(_, _) | INTERPOLATED(nt_path(*)) => true,
296 pub fn is_plain_ident(t: &Token) -> bool {
297 match *t { IDENT(_, false) => true, _ => false }
300 pub fn is_bar(t: &Token) -> bool {
301 match *t { BINOP(OR) | OROR => true, _ => false }
305 pub mod special_idents {
308 pub static underscore : ident = ident { repr: 0, ctxt: 0};
309 pub static anon : ident = ident { repr: 1, ctxt: 0};
310 pub static invalid : ident = ident { repr: 2, ctxt: 0}; // ''
311 pub static unary : ident = ident { repr: 3, ctxt: 0};
312 pub static not_fn : ident = ident { repr: 4, ctxt: 0};
313 pub static idx_fn : ident = ident { repr: 5, ctxt: 0};
314 pub static unary_minus_fn : ident = ident { repr: 6, ctxt: 0};
315 pub static clownshoes_extensions : ident = ident { repr: 7, ctxt: 0};
317 pub static self_ : ident = ident { repr: 8, ctxt: 0}; // 'self'
319 /* for matcher NTs */
320 pub static item : ident = ident { repr: 9, ctxt: 0};
321 pub static block : ident = ident { repr: 10, ctxt: 0};
322 pub static stmt : ident = ident { repr: 11, ctxt: 0};
323 pub static pat : ident = ident { repr: 12, ctxt: 0};
324 pub static expr : ident = ident { repr: 13, ctxt: 0};
325 pub static ty : ident = ident { repr: 14, ctxt: 0};
326 pub static ident : ident = ident { repr: 15, ctxt: 0};
327 pub static path : ident = ident { repr: 16, ctxt: 0};
328 pub static tt : ident = ident { repr: 17, ctxt: 0};
329 pub static matchers : ident = ident { repr: 18, ctxt: 0};
331 pub static str : ident = ident { repr: 19, ctxt: 0}; // for the type
333 /* outside of libsyntax */
334 pub static ty_visitor : ident = ident { repr: 20, ctxt: 0};
335 pub static arg : ident = ident { repr: 21, ctxt: 0};
336 pub static descrim : ident = ident { repr: 22, ctxt: 0};
337 pub static clownshoe_abi : ident = ident { repr: 23, ctxt: 0};
338 pub static clownshoe_stack_shim : ident = ident { repr: 24, ctxt: 0};
339 pub static tydesc : ident = ident { repr: 25, ctxt: 0};
340 pub static main : ident = ident { repr: 26, ctxt: 0};
341 pub static opaque : ident = ident { repr: 27, ctxt: 0};
342 pub static blk : ident = ident { repr: 28, ctxt: 0};
343 pub static static : ident = ident { repr: 29, ctxt: 0};
344 pub static intrinsic : ident = ident { repr: 30, ctxt: 0};
345 pub static clownshoes_foreign_mod: ident = ident { repr: 31, ctxt: 0};
346 pub static unnamed_field: ident = ident { repr: 32, ctxt: 0};
347 pub static c_abi: ident = ident { repr: 33, ctxt: 0};
348 pub static type_self: ident = ident { repr: 34, ctxt: 0}; // `Self`
351 pub struct StringRef<'self>(&'self str);
353 impl<'self> Equiv<@~str> for StringRef<'self> {
355 fn equiv(&self, other: &@~str) -> bool { str::eq_slice(**self, **other) }
358 impl<'self> to_bytes::IterBytes for StringRef<'self> {
359 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
360 (**self).iter_bytes(lsb0, f);
365 * Maps a token to a record specifying the corresponding binary
368 pub fn token_to_binop(tok: Token) -> Option<ast::binop> {
370 BINOP(STAR) => Some(ast::mul),
371 BINOP(SLASH) => Some(ast::quot),
372 BINOP(PERCENT) => Some(ast::rem),
373 BINOP(PLUS) => Some(ast::add),
374 BINOP(MINUS) => Some(ast::subtract),
375 BINOP(SHL) => Some(ast::shl),
376 BINOP(SHR) => Some(ast::shr),
377 BINOP(AND) => Some(ast::bitand),
378 BINOP(CARET) => Some(ast::bitxor),
379 BINOP(OR) => Some(ast::bitor),
384 EQEQ => Some(ast::eq),
386 ANDAND => Some(ast::and),
387 OROR => Some(ast::or),
392 pub struct ident_interner {
393 priv interner: Interner<@~str>,
396 pub impl ident_interner {
397 fn intern(&self, val: @~str) -> ast::ident {
398 ast::ident { repr: self.interner.intern(val), ctxt: 0 }
400 fn gensym(&self, val: @~str) -> ast::ident {
401 ast::ident { repr: self.interner.gensym(val), ctxt: 0 }
403 fn get(&self, idx: ast::ident) -> @~str {
404 self.interner.get(idx.repr)
406 fn len(&self) -> uint {
409 fn find_equiv<Q:Hash + IterBytes + Equiv<@~str>>(&self, val: &Q)
410 -> Option<ast::ident> {
411 match self.interner.find_equiv(val) {
412 Some(v) => Some(ast::ident { repr: v, ctxt: 0 }),
418 // return a fresh interner, preloaded with special identifiers.
419 // EFFECT: stores this interner in TLS
420 pub fn mk_fresh_ident_interner() -> @ident_interner {
421 // the indices here must correspond to the numbers in
431 @~"__extensions__", // 7
447 @~"__rust_abi", // 23
448 @~"__rust_stack_shim", // 24
455 @~"__foreign_mod__", // 31
461 let rv = @ident_interner {
462 interner: interner::Interner::prefill(init_vec)
465 task::local_data::local_data_set(interner_key!(), @rv);
470 // if an interner exists in TLS, return it. Otherwise, prepare a
472 pub fn mk_ident_interner() -> @ident_interner {
474 match task::local_data::local_data_get(interner_key!()) {
475 Some(interner) => *interner,
477 mk_fresh_ident_interner()
483 /* for when we don't care about the contents; doesn't interact with TLD or
485 pub fn mk_fake_ident_interner() -> @ident_interner {
486 @ident_interner { interner: interner::Interner::new() }
490 * All the valid words that have meaning in the Rust language.
492 * Rust keywords are either 'temporary', 'strict' or 'reserved'. Temporary
493 * keywords are contextual and may be used as identifiers anywhere. They are
494 * expected to disappear from the grammar soon. Strict keywords may not
495 * appear as identifiers at all. Reserved keywords are not used anywhere in
496 * the language and may not appear as identifiers.
498 pub fn keyword_table() -> HashSet<~str> {
499 let mut keywords = HashSet::new();
500 let mut tmp = temporary_keyword_table();
501 let mut strict = strict_keyword_table();
502 let mut reserved = reserved_keyword_table();
504 do tmp.consume |word| { keywords.insert(word); }
505 do strict.consume |word| { keywords.insert(word); }
506 do reserved.consume |word| { keywords.insert(word); }
510 /// Keywords that may be used as identifiers
511 pub fn temporary_keyword_table() -> HashSet<~str> {
512 let mut words = HashSet::new();
516 do vec::consume(keys) |_, s| {
522 /// Full keywords. May not appear anywhere else.
523 pub fn strict_keyword_table() -> HashSet<~str> {
524 let mut words = HashSet::new();
530 ~"else", ~"enum", ~"extern",
531 ~"false", ~"fn", ~"for",
533 ~"let", ~"__log", ~"loop",
534 ~"match", ~"mod", ~"mut",
536 ~"priv", ~"pub", ~"pure",
539 ~"true", ~"trait", ~"type",
543 do vec::consume(keys) |_, w| {
549 pub fn reserved_keyword_table() -> HashSet<~str> {
550 let mut words = HashSet::new();
554 do vec::consume(keys) |_, s| {
563 // indent-tabs-mode: nil
565 // buffer-file-coding-system: utf-8-unix