]> git.lizzy.rs Git - rust.git/blob - src/libsyntax/parse/token.rs
0327a3b80da87967f34524d4870d3eceb23c761b
[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: 0u, ctxt: 0};
309     pub static anon : ident = ident { repr: 1u, ctxt: 0};
310     pub static dtor : ident = ident { repr: 2u, ctxt: 0}; // 'drop', but that's
311                                                  // reserved
312     pub static invalid : ident = ident { repr: 3u, ctxt: 0}; // ''
313     pub static unary : ident = ident { repr: 4u, ctxt: 0};
314     pub static not_fn : ident = ident { repr: 5u, ctxt: 0};
315     pub static idx_fn : ident = ident { repr: 6u, ctxt: 0};
316     pub static unary_minus_fn : ident = ident { repr: 7u, ctxt: 0};
317     pub static clownshoes_extensions : ident = ident { repr: 8u, ctxt: 0};
318
319     pub static self_ : ident = ident { repr: 9u, ctxt: 0}; // 'self'
320
321     /* for matcher NTs */
322     pub static item : ident = ident { repr: 10u, ctxt: 0};
323     pub static block : ident = ident { repr: 11u, ctxt: 0};
324     pub static stmt : ident = ident { repr: 12u, ctxt: 0};
325     pub static pat : ident = ident { repr: 13u, ctxt: 0};
326     pub static expr : ident = ident { repr: 14u, ctxt: 0};
327     pub static ty : ident = ident { repr: 15u, ctxt: 0};
328     pub static ident : ident = ident { repr: 16u, ctxt: 0};
329     pub static path : ident = ident { repr: 17u, ctxt: 0};
330     pub static tt : ident = ident { repr: 18u, ctxt: 0};
331     pub static matchers : ident = ident { repr: 19u, ctxt: 0};
332
333     pub static str : ident = ident { repr: 20u, ctxt: 0}; // for the type
334
335     /* outside of libsyntax */
336     pub static ty_visitor : ident = ident { repr: 21u, ctxt: 0};
337     pub static arg : ident = ident { repr: 22u, ctxt: 0};
338     pub static descrim : ident = ident { repr: 23u, ctxt: 0};
339     pub static clownshoe_abi : ident = ident { repr: 24u, ctxt: 0};
340     pub static clownshoe_stack_shim : ident = ident { repr: 25u, ctxt: 0};
341     pub static tydesc : ident = ident { repr: 26u, ctxt: 0};
342     pub static literally_dtor : ident = ident { repr: 27u, ctxt: 0};
343     pub static main : ident = ident { repr: 28u, ctxt: 0};
344     pub static opaque : ident = ident { repr: 29u, ctxt: 0};
345     pub static blk : ident = ident { repr: 30u, ctxt: 0};
346     pub static static : ident = ident { repr: 31u, ctxt: 0};
347     pub static intrinsic : ident = ident { repr: 32u, ctxt: 0};
348     pub static clownshoes_foreign_mod: ident = ident { repr: 33u, ctxt: 0};
349     pub static unnamed_field: ident = ident { repr: 34u, ctxt: 0};
350     pub static c_abi: ident = ident { repr: 35u, ctxt: 0};
351     pub static type_self: ident = ident { repr: 36u, ctxt: 0};    // `Self`
352 }
353
354 pub struct StringRef<'self>(&'self str);
355
356 impl<'self> Equiv<@~str> for StringRef<'self> {
357     #[inline(always)]
358     fn equiv(&self, other: &@~str) -> bool { str::eq_slice(**self, **other) }
359 }
360
361 impl<'self> to_bytes::IterBytes for StringRef<'self> {
362     fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
363         (**self).iter_bytes(lsb0, f);
364     }
365 }
366
367 /**
368  * Maps a token to a record specifying the corresponding binary
369  * operator
370  */
371 pub fn token_to_binop(tok: Token) -> Option<ast::binop> {
372   match tok {
373       BINOP(STAR)    => Some(ast::mul),
374       BINOP(SLASH)   => Some(ast::quot),
375       BINOP(PERCENT) => Some(ast::rem),
376       BINOP(PLUS)    => Some(ast::add),
377       BINOP(MINUS)   => Some(ast::subtract),
378       BINOP(SHL)     => Some(ast::shl),
379       BINOP(SHR)     => Some(ast::shr),
380       BINOP(AND)     => Some(ast::bitand),
381       BINOP(CARET)   => Some(ast::bitxor),
382       BINOP(OR)      => Some(ast::bitor),
383       LT             => Some(ast::lt),
384       LE             => Some(ast::le),
385       GE             => Some(ast::ge),
386       GT             => Some(ast::gt),
387       EQEQ           => Some(ast::eq),
388       NE             => Some(ast::ne),
389       ANDAND         => Some(ast::and),
390       OROR           => Some(ast::or),
391       _              => None
392   }
393 }
394
395 pub struct ident_interner {
396     priv interner: Interner<@~str>,
397 }
398
399 pub impl ident_interner {
400     fn intern(&self, val: @~str) -> ast::ident {
401         ast::ident { repr: self.interner.intern(val), ctxt: 0 }
402     }
403     fn gensym(&self, val: @~str) -> ast::ident {
404         ast::ident { repr: self.interner.gensym(val), ctxt: 0 }
405     }
406     fn get(&self, idx: ast::ident) -> @~str {
407         self.interner.get(idx.repr)
408     }
409     fn len(&self) -> uint {
410         self.interner.len()
411     }
412     fn find_equiv<Q:Hash + IterBytes + Equiv<@~str>>(&self, val: &Q)
413                                                      -> Option<ast::ident> {
414         match self.interner.find_equiv(val) {
415             Some(v) => Some(ast::ident { repr: v, ctxt: 0 }),
416             None => None,
417         }
418     }
419 }
420
421 // return a fresh interner, preloaded with special identifiers.
422 // EFFECT: stores this interner in TLS
423 pub fn mk_fresh_ident_interner() -> @ident_interner {
424     // the indices here must correspond to the numbers in
425     // special_idents.
426     let init_vec = ~[
427         @~"_",                  // 0
428         @~"anon",               // 1
429         @~"drop",               // 2
430         @~"",                   // 3
431         @~"unary",              // 4
432         @~"!",                  // 5
433         @~"[]",                 // 6
434         @~"unary-",             // 7
435         @~"__extensions__",     // 8
436         @~"self",               // 9
437         @~"item",               // 10
438         @~"block",              // 11
439         @~"stmt",               // 12
440         @~"pat",                // 13
441         @~"expr",               // 14
442         @~"ty",                 // 15
443         @~"ident",              // 16
444         @~"path",               // 17
445         @~"tt",                 // 18
446         @~"matchers",           // 19
447         @~"str",                // 20
448         @~"TyVisitor",          // 21
449         @~"arg",                // 22
450         @~"descrim",            // 23
451         @~"__rust_abi",         // 24
452         @~"__rust_stack_shim",  // 25
453         @~"TyDesc",             // 26
454         @~"dtor",               // 27
455         @~"main",               // 28
456         @~"<opaque>",           // 29
457         @~"blk",                // 30
458         @~"static",             // 31
459         @~"intrinsic",          // 32
460         @~"__foreign_mod__",    // 33
461         @~"__field__",          // 34
462         @~"C",                  // 35
463         @~"Self",               // 36
464     ];
465
466     let rv = @ident_interner {
467         interner: interner::Interner::prefill(init_vec)
468     };
469     unsafe {
470         task::local_data::local_data_set(interner_key!(), @rv);
471     }
472     rv
473 }
474
475 // if an interner exists in TLS, return it. Otherwise, prepare a
476 // fresh one.
477 pub fn mk_ident_interner() -> @ident_interner {
478     unsafe {
479         match task::local_data::local_data_get(interner_key!()) {
480             Some(interner) => *interner,
481             None => {
482                 mk_fresh_ident_interner()
483             }
484         }
485     }
486 }
487
488 /* for when we don't care about the contents; doesn't interact with TLD or
489    serialization */
490 pub fn mk_fake_ident_interner() -> @ident_interner {
491     @ident_interner { interner: interner::Interner::new() }
492 }
493
494 /**
495  * All the valid words that have meaning in the Rust language.
496  *
497  * Rust keywords are either 'temporary', 'strict' or 'reserved'.  Temporary
498  * keywords are contextual and may be used as identifiers anywhere.  They are
499  * expected to disappear from the grammar soon.  Strict keywords may not
500  * appear as identifiers at all. Reserved keywords are not used anywhere in
501  * the language and may not appear as identifiers.
502  */
503 pub fn keyword_table() -> HashSet<~str> {
504     let mut keywords = HashSet::new();
505     let mut tmp = temporary_keyword_table();
506     let mut strict = strict_keyword_table();
507     let mut reserved = reserved_keyword_table();
508
509     do tmp.consume |word|      { keywords.insert(word); }
510     do strict.consume |word|   { keywords.insert(word); }
511     do reserved.consume |word| { keywords.insert(word); }
512     return keywords;
513 }
514
515 /// Keywords that may be used as identifiers
516 pub fn temporary_keyword_table() -> HashSet<~str> {
517     let mut words = HashSet::new();
518     let keys = ~[
519         ~"self", ~"static",
520     ];
521     do vec::consume(keys) |_, s| {
522         words.insert(s);
523     }
524     return words;
525 }
526
527 /// Full keywords. May not appear anywhere else.
528 pub fn strict_keyword_table() -> HashSet<~str> {
529     let mut words = HashSet::new();
530     let keys = ~[
531         ~"as",
532         ~"break",
533         ~"const", ~"copy",
534         ~"do", ~"drop",
535         ~"else", ~"enum", ~"extern",
536         ~"false", ~"fn", ~"for",
537         ~"if", ~"impl",
538         ~"let", ~"__log", ~"loop",
539         ~"match", ~"mod", ~"mut",
540         ~"once",
541         ~"priv", ~"pub", ~"pure",
542         ~"ref", ~"return",
543         ~"struct", ~"super",
544         ~"true", ~"trait", ~"type",
545         ~"unsafe", ~"use",
546         ~"while"
547     ];
548     do vec::consume(keys) |_, w| {
549         words.insert(w);
550     }
551     return words;
552 }
553
554 pub fn reserved_keyword_table() -> HashSet<~str> {
555     let mut words = HashSet::new();
556     let keys = ~[
557         ~"be"
558     ];
559     do vec::consume(keys) |_, s| {
560         words.insert(s);
561     }
562     return words;
563 }
564
565
566 // Local Variables:
567 // fill-column: 78;
568 // indent-tabs-mode: nil
569 // c-basic-offset: 4
570 // buffer-file-coding-system: utf-8-unix
571 // End: