]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/parse/token.rs
syntax: remove parse::token::{dtor,literally_dtor}
[rust.git] / src / libsyntax / parse / token.rs
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.
4 //
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.
10
11 use ast;
12 use ast_util;
13 use parse::token;
14 use util::interner::Interner;
15 use util::interner;
16
17 use core::cmp::Equiv;
18 use core::hashmap::HashSet;
19 use core::to_bytes;
20
21 #[auto_encode]
22 #[auto_decode]
23 #[deriving(Eq)]
24 pub enum binop {
25     PLUS,
26     MINUS,
27     STAR,
28     SLASH,
29     PERCENT,
30     CARET,
31     AND,
32     OR,
33     SHL,
34     SHR,
35 }
36
37 #[auto_encode]
38 #[auto_decode]
39 #[deriving(Eq)]
40 pub enum Token {
41     /* Expression-operator symbols. */
42     EQ,
43     LT,
44     LE,
45     EQEQ,
46     NE,
47     GE,
48     GT,
49     ANDAND,
50     OROR,
51     NOT,
52     TILDE,
53     BINOP(binop),
54     BINOPEQ(binop),
55
56     /* Structural symbols */
57     AT,
58     DOT,
59     DOTDOT,
60     COMMA,
61     SEMI,
62     COLON,
63     MOD_SEP,
64     RARROW,
65     LARROW,
66     DARROW,
67     FAT_ARROW,
68     LPAREN,
69     RPAREN,
70     LBRACKET,
71     RBRACKET,
72     LBRACE,
73     RBRACE,
74     POUND,
75     DOLLAR,
76
77     /* Literals */
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),
83     LIT_STR(ast::ident),
84
85     /* Name components */
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),
90     UNDERSCORE,
91     LIFETIME(ast::ident),
92
93     /* For interpolation */
94     INTERPOLATED(nonterminal),
95
96     DOC_COMMENT(ast::ident),
97     EOF,
98 }
99
100 #[auto_encode]
101 #[auto_decode]
102 #[deriving(Eq)]
103 /// For interpolation during macro expansion.
104 pub enum nonterminal {
105     nt_item(@ast::item),
106     nt_block(ast::blk),
107     nt_stmt(@ast::stmt),
108     nt_pat( @ast::pat),
109     nt_expr(@ast::expr),
110     nt_ty(  @ast::Ty),
111     nt_ident(ast::ident, bool),
112     nt_path(@ast::Path),
113     nt_tt(  @ast::token_tree), //needs @ed to break a circularity
114     nt_matchers(~[ast::matcher])
115 }
116
117 pub fn binop_to_str(o: binop) -> ~str {
118     match o {
119       PLUS => ~"+",
120       MINUS => ~"-",
121       STAR => ~"*",
122       SLASH => ~"/",
123       PERCENT => ~"%",
124       CARET => ~"^",
125       AND => ~"&",
126       OR => ~"|",
127       SHL => ~"<<",
128       SHR => ~">>"
129     }
130 }
131
132 pub fn to_str(in: @ident_interner, t: &Token) -> ~str {
133     match *t {
134       EQ => ~"=",
135       LT => ~"<",
136       LE => ~"<=",
137       EQEQ => ~"==",
138       NE => ~"!=",
139       GE => ~">=",
140       GT => ~">",
141       NOT => ~"!",
142       TILDE => ~"~",
143       OROR => ~"||",
144       ANDAND => ~"&&",
145       BINOP(op) => binop_to_str(op),
146       BINOPEQ(op) => binop_to_str(op) + ~"=",
147
148       /* Structural symbols */
149       AT => ~"@",
150       DOT => ~".",
151       DOTDOT => ~"..",
152       COMMA => ~",",
153       SEMI => ~";",
154       COLON => ~":",
155       MOD_SEP => ~"::",
156       RARROW => ~"->",
157       LARROW => ~"<-",
158       DARROW => ~"<->",
159       FAT_ARROW => ~"=>",
160       LPAREN => ~"(",
161       RPAREN => ~")",
162       LBRACKET => ~"[",
163       RBRACKET => ~"]",
164       LBRACE => ~"{",
165       RBRACE => ~"}",
166       POUND => ~"#",
167       DOLLAR => ~"$",
168
169       /* Literals */
170       LIT_INT(c, ast::ty_char) => {
171         ~"'" + char::escape_default(c as char) + ~"'"
172       }
173       LIT_INT(i, t) => {
174           i.to_str() + ast_util::int_ty_to_str(t)
175       }
176       LIT_UINT(u, t) => {
177           u.to_str() + ast_util::uint_ty_to_str(t)
178       }
179       LIT_INT_UNSUFFIXED(i) => { i.to_str() }
180       LIT_FLOAT(s, t) => {
181         let mut body = copy *in.get(s);
182         if body.ends_with(~".") {
183             body = body + ~"0";  // `10.f` is not a float literal
184         }
185         body + ast_util::float_ty_to_str(t)
186       }
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
191         }
192         body
193       }
194       LIT_STR(s) => { ~"\"" + str::escape_default(*in.get(s)) + ~"\"" }
195
196       /* Name components */
197       IDENT(s, _) => copy *in.get(s),
198       LIFETIME(s) => fmt!("'%s", *in.get(s)),
199       UNDERSCORE => ~"_",
200
201       /* Other */
202       DOC_COMMENT(s) => copy *in.get(s),
203       EOF => ~"<eof>",
204       INTERPOLATED(ref nt) => {
205         match nt {
206             &nt_expr(e) => ::print::pprust::expr_to_str(e, in),
207             _ => {
208                 ~"an interpolated " +
209                     match (*nt) {
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"),
215                       nt_ty(*) => ~"type",
216                       nt_ident(*) => ~"identifier",
217                       nt_path(*) => ~"path",
218                       nt_tt(*) => ~"tt",
219                       nt_matchers(*) => ~"matcher sequence"
220                     }
221             }
222         }
223       }
224     }
225 }
226
227 pub fn can_begin_expr(t: &Token) -> bool {
228     match *t {
229       LPAREN => true,
230       LBRACE => true,
231       LBRACKET => true,
232       IDENT(_, _) => true,
233       UNDERSCORE => true,
234       TILDE => true,
235       LIT_INT(_, _) => true,
236       LIT_UINT(_, _) => true,
237       LIT_INT_UNSUFFIXED(_) => true,
238       LIT_FLOAT(_, _) => true,
239       LIT_FLOAT_UNSUFFIXED(_) => true,
240       LIT_STR(_) => true,
241       POUND => true,
242       AT => true,
243       NOT => true,
244       BINOP(MINUS) => true,
245       BINOP(STAR) => true,
246       BINOP(AND) => true,
247       BINOP(OR) => true, // in lambda syntax
248       OROR => true, // in lambda syntax
249       MOD_SEP => true,
250       INTERPOLATED(nt_expr(*))
251       | INTERPOLATED(nt_ident(*))
252       | INTERPOLATED(nt_block(*))
253       | INTERPOLATED(nt_path(*)) => true,
254       _ => false
255     }
256 }
257
258 /// what's the opposite delimiter?
259 pub fn flip_delimiter(t: &token::Token) -> token::Token {
260     match *t {
261       LPAREN => RPAREN,
262       LBRACE => RBRACE,
263       LBRACKET => RBRACKET,
264       RPAREN => LPAREN,
265       RBRACE => LBRACE,
266       RBRACKET => LBRACKET,
267       _ => fail!()
268     }
269 }
270
271
272
273 pub fn is_lit(t: &Token) -> bool {
274     match *t {
275       LIT_INT(_, _) => true,
276       LIT_UINT(_, _) => true,
277       LIT_INT_UNSUFFIXED(_) => true,
278       LIT_FLOAT(_, _) => true,
279       LIT_FLOAT_UNSUFFIXED(_) => true,
280       LIT_STR(_) => true,
281       _ => false
282     }
283 }
284
285 pub fn is_ident(t: &Token) -> bool {
286     match *t { IDENT(_, _) => true, _ => false }
287 }
288
289 pub fn is_ident_or_path(t: &Token) -> bool {
290     match *t {
291       IDENT(_, _) | INTERPOLATED(nt_path(*)) => true,
292       _ => false
293     }
294 }
295
296 pub fn is_plain_ident(t: &Token) -> bool {
297     match *t { IDENT(_, false) => true, _ => false }
298 }
299
300 pub fn is_bar(t: &Token) -> bool {
301     match *t { BINOP(OR) | OROR => true, _ => false }
302 }
303
304
305 pub mod special_idents {
306     use ast::ident;
307
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};
316
317     pub static self_ : ident = ident { repr: 8, ctxt: 0}; // 'self'
318
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};
330
331     pub static str : ident = ident { repr: 19, ctxt: 0}; // for the type
332
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`
349 }
350
351 pub struct StringRef<'self>(&'self str);
352
353 impl<'self> Equiv<@~str> for StringRef<'self> {
354     #[inline(always)]
355     fn equiv(&self, other: &@~str) -> bool { str::eq_slice(**self, **other) }
356 }
357
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);
361     }
362 }
363
364 /**
365  * Maps a token to a record specifying the corresponding binary
366  * operator
367  */
368 pub fn token_to_binop(tok: Token) -> Option<ast::binop> {
369   match tok {
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),
380       LT             => Some(ast::lt),
381       LE             => Some(ast::le),
382       GE             => Some(ast::ge),
383       GT             => Some(ast::gt),
384       EQEQ           => Some(ast::eq),
385       NE             => Some(ast::ne),
386       ANDAND         => Some(ast::and),
387       OROR           => Some(ast::or),
388       _              => None
389   }
390 }
391
392 pub struct ident_interner {
393     priv interner: Interner<@~str>,
394 }
395
396 pub impl ident_interner {
397     fn intern(&self, val: @~str) -> ast::ident {
398         ast::ident { repr: self.interner.intern(val), ctxt: 0 }
399     }
400     fn gensym(&self, val: @~str) -> ast::ident {
401         ast::ident { repr: self.interner.gensym(val), ctxt: 0 }
402     }
403     fn get(&self, idx: ast::ident) -> @~str {
404         self.interner.get(idx.repr)
405     }
406     fn len(&self) -> uint {
407         self.interner.len()
408     }
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 }),
413             None => None,
414         }
415     }
416 }
417
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
422     // special_idents.
423     let init_vec = ~[
424         @~"_",                  // 0
425         @~"anon",               // 1
426         @~"",                   // 2
427         @~"unary",              // 3
428         @~"!",                  // 4
429         @~"[]",                 // 5
430         @~"unary-",             // 6
431         @~"__extensions__",     // 7
432         @~"self",               // 8
433         @~"item",               // 9
434         @~"block",              // 10
435         @~"stmt",               // 11
436         @~"pat",                // 12
437         @~"expr",               // 13
438         @~"ty",                 // 14
439         @~"ident",              // 15
440         @~"path",               // 16
441         @~"tt",                 // 17
442         @~"matchers",           // 18
443         @~"str",                // 19
444         @~"TyVisitor",          // 20
445         @~"arg",                // 21
446         @~"descrim",            // 22
447         @~"__rust_abi",         // 23
448         @~"__rust_stack_shim",  // 24
449         @~"TyDesc",             // 25
450         @~"main",               // 26
451         @~"<opaque>",           // 27
452         @~"blk",                // 28
453         @~"static",             // 29
454         @~"intrinsic",          // 30
455         @~"__foreign_mod__",    // 31
456         @~"__field__",          // 32
457         @~"C",                  // 33
458         @~"Self",               // 34
459     ];
460
461     let rv = @ident_interner {
462         interner: interner::Interner::prefill(init_vec)
463     };
464     unsafe {
465         task::local_data::local_data_set(interner_key!(), @rv);
466     }
467     rv
468 }
469
470 // if an interner exists in TLS, return it. Otherwise, prepare a
471 // fresh one.
472 pub fn mk_ident_interner() -> @ident_interner {
473     unsafe {
474         match task::local_data::local_data_get(interner_key!()) {
475             Some(interner) => *interner,
476             None => {
477                 mk_fresh_ident_interner()
478             }
479         }
480     }
481 }
482
483 /* for when we don't care about the contents; doesn't interact with TLD or
484    serialization */
485 pub fn mk_fake_ident_interner() -> @ident_interner {
486     @ident_interner { interner: interner::Interner::new() }
487 }
488
489 /**
490  * All the valid words that have meaning in the Rust language.
491  *
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.
497  */
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();
503
504     do tmp.consume |word|      { keywords.insert(word); }
505     do strict.consume |word|   { keywords.insert(word); }
506     do reserved.consume |word| { keywords.insert(word); }
507     return keywords;
508 }
509
510 /// Keywords that may be used as identifiers
511 pub fn temporary_keyword_table() -> HashSet<~str> {
512     let mut words = HashSet::new();
513     let keys = ~[
514         ~"self", ~"static",
515     ];
516     do vec::consume(keys) |_, s| {
517         words.insert(s);
518     }
519     return words;
520 }
521
522 /// Full keywords. May not appear anywhere else.
523 pub fn strict_keyword_table() -> HashSet<~str> {
524     let mut words = HashSet::new();
525     let keys = ~[
526         ~"as",
527         ~"break",
528         ~"const", ~"copy",
529         ~"do", ~"drop",
530         ~"else", ~"enum", ~"extern",
531         ~"false", ~"fn", ~"for",
532         ~"if", ~"impl",
533         ~"let", ~"__log", ~"loop",
534         ~"match", ~"mod", ~"mut",
535         ~"once",
536         ~"priv", ~"pub", ~"pure",
537         ~"ref", ~"return",
538         ~"struct", ~"super",
539         ~"true", ~"trait", ~"type",
540         ~"unsafe", ~"use",
541         ~"while"
542     ];
543     do vec::consume(keys) |_, w| {
544         words.insert(w);
545     }
546     return words;
547 }
548
549 pub fn reserved_keyword_table() -> HashSet<~str> {
550     let mut words = HashSet::new();
551     let keys = ~[
552         ~"be"
553     ];
554     do vec::consume(keys) |_, s| {
555         words.insert(s);
556     }
557     return words;
558 }
559
560
561 // Local Variables:
562 // fill-column: 78;
563 // indent-tabs-mode: nil
564 // c-basic-offset: 4
565 // buffer-file-coding-system: utf-8-unix
566 // End: