blob: afc8a3a46ddd87741886214abde3c74413db1d23 [file] [log] [blame]
David Tolnayf733f7e2016-11-25 10:36:25 -08001use std::borrow::Cow;
Alex Crichtonccbb45d2017-05-23 10:58:24 -07002use std::cmp::Ordering;
David Tolnay42f50292016-09-04 13:54:21 -07003use std::fmt::{self, Display};
Alex Crichtonccbb45d2017-05-23 10:58:24 -07004use std::hash::{Hash, Hasher};
David Tolnay42f50292016-09-04 13:54:21 -07005
Alex Crichtonccbb45d2017-05-23 10:58:24 -07006use proc_macro2::Symbol;
7
8use Span;
Alex Crichton954046c2017-05-30 21:49:42 -07009use tokens;
Alex Crichtonccbb45d2017-05-23 10:58:24 -070010
Alex Crichtonbc983d42017-06-02 13:18:52 -070011#[derive(Clone, Debug)]
Alex Crichtonccbb45d2017-05-23 10:58:24 -070012pub struct Ident {
13 pub sym: Symbol,
14 pub span: Span,
15}
David Tolnay42f50292016-09-04 13:54:21 -070016
17impl Ident {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070018 pub fn new(sym: Symbol, span: Span) -> Self {
19 Ident {
20 sym: sym,
21 span: span,
22 }
David Tolnay42f50292016-09-04 13:54:21 -070023 }
24}
25
26impl<'a> From<&'a str> for Ident {
27 fn from(s: &str) -> Self {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070028 Ident::new(s.into(), Span::default())
David Tolnay42f50292016-09-04 13:54:21 -070029 }
30}
31
Alex Crichton954046c2017-05-30 21:49:42 -070032impl From<tokens::Self_> for Ident {
33 fn from(tok: tokens::Self_) -> Self {
34 Ident::new("self".into(), tok.0)
35 }
36}
37
38impl From<tokens::CapSelf> for Ident {
39 fn from(tok: tokens::CapSelf) -> Self {
40 Ident::new("Self".into(), tok.0)
41 }
42}
43
44impl From<tokens::Super> for Ident {
45 fn from(tok: tokens::Super) -> Self {
46 Ident::new("super".into(), tok.0)
47 }
48}
49
David Tolnayf733f7e2016-11-25 10:36:25 -080050impl<'a> From<Cow<'a, str>> for Ident {
51 fn from(s: Cow<'a, str>) -> Self {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070052 Ident::new(s[..].into(), Span::default())
David Tolnayf733f7e2016-11-25 10:36:25 -080053 }
54}
55
David Tolnay42f50292016-09-04 13:54:21 -070056impl From<String> for Ident {
57 fn from(s: String) -> Self {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070058 Ident::new(s[..].into(), Span::default())
David Tolnay42f50292016-09-04 13:54:21 -070059 }
60}
61
David Tolnayc1683102016-09-27 08:17:58 -070062impl From<usize> for Ident {
63 fn from(u: usize) -> Self {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070064 Ident::new(u.to_string()[..].into(), Span::default())
David Tolnayc1683102016-09-27 08:17:58 -070065 }
66}
67
David Tolnay26469072016-09-04 13:59:48 -070068impl AsRef<str> for Ident {
69 fn as_ref(&self) -> &str {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070070 self.sym.as_str()
David Tolnay42f50292016-09-04 13:54:21 -070071 }
72}
73
74impl Display for Ident {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070075 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
76 self.sym.as_str().fmt(formatter)
77 }
78}
79
David Tolnaydaaf7742016-10-03 11:11:43 -070080impl<T: ?Sized> PartialEq<T> for Ident
81 where T: AsRef<str>
82{
David Tolnay55337722016-09-11 12:58:56 -070083 fn eq(&self, other: &T) -> bool {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070084 self.as_ref() == other.as_ref()
85 }
86}
87
88impl Eq for Ident {}
89
90impl PartialOrd for Ident {
91 fn partial_cmp(&self, other: &Ident) -> Option<Ordering> {
92 Some(self.cmp(other))
93 }
94}
95
96impl Ord for Ident {
97 fn cmp(&self, other: &Ident) -> Ordering {
98 self.as_ref().cmp(other.as_ref())
99 }
100}
101
102impl Hash for Ident {
103 fn hash<H: Hasher>(&self, h: &mut H) {
104 self.as_ref().hash(h)
David Tolnay55337722016-09-11 12:58:56 -0700105 }
David Tolnayb79ee962016-09-04 09:39:20 -0700106}
107
David Tolnay86eca752016-09-04 11:26:41 -0700108#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700109pub mod parsing {
110 use super::*;
Michael Layzell92639a52017-06-01 00:07:44 -0400111 use synom::{Synom, PResult, Cursor, parse_error};
David Tolnay9d8f1972016-09-04 11:58:48 -0700112
Alex Crichton954046c2017-05-30 21:49:42 -0700113 impl Synom for Ident {
Michael Layzell92639a52017-06-01 00:07:44 -0400114 fn parse(input: Cursor) -> PResult<Self> {
Michael Layzell589a8f42017-06-02 19:47:01 -0400115 let (rest, span, sym) = match input.word() {
116 Some(word) => word,
Michael Layzell92639a52017-06-01 00:07:44 -0400117 _ => return parse_error(),
Alex Crichton954046c2017-05-30 21:49:42 -0700118 };
Michael Layzell589a8f42017-06-02 19:47:01 -0400119 if sym.as_str().starts_with('\'') {
Michael Layzell92639a52017-06-01 00:07:44 -0400120 return parse_error();
Alex Crichton954046c2017-05-30 21:49:42 -0700121 }
Michael Layzell589a8f42017-06-02 19:47:01 -0400122 match sym.as_str() {
Michael Layzell416724e2017-05-24 21:12:34 -0400123 // From https://doc.rust-lang.org/grammar.html#keywords
124 "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const" | "continue" |
125 "crate" | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" |
126 "if" | "impl" | "in" | "let" | "loop" | "macro" | "match" | "mod" | "move" |
127 "mut" | "offsetof" | "override" | "priv" | "proc" | "pub" | "pure" | "ref" |
128 "return" | "Self" | "self" | "sizeof" | "static" | "struct" | "super" | "trait" |
129 "true" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" |
Michael Layzell92639a52017-06-01 00:07:44 -0400130 "while" | "yield" => return parse_error(),
Alex Crichton954046c2017-05-30 21:49:42 -0700131 _ => {}
Michael Layzell416724e2017-05-24 21:12:34 -0400132 }
Alex Crichton954046c2017-05-30 21:49:42 -0700133
Michael Layzell589a8f42017-06-02 19:47:01 -0400134 Ok((rest, Ident {
135 span: Span(span),
136 sym: sym,
Michael Layzell92639a52017-06-01 00:07:44 -0400137 }))
Alex Crichton954046c2017-05-30 21:49:42 -0700138 }
139
140 fn description() -> Option<&'static str> {
141 Some("identifier")
David Tolnay05f462f2016-10-24 22:19:42 -0700142 }
143 }
David Tolnayb79ee962016-09-04 09:39:20 -0700144}
David Tolnay26469072016-09-04 13:59:48 -0700145
146#[cfg(feature = "printing")]
147mod printing {
148 use super::*;
149 use quote::{Tokens, ToTokens};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700150 use proc_macro2::{TokenTree, TokenKind};
David Tolnay26469072016-09-04 13:59:48 -0700151
152 impl ToTokens for Ident {
153 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700154 tokens.append(TokenTree {
155 span: self.span.0,
156 kind: TokenKind::Word(self.sym),
157 })
David Tolnay26469072016-09-04 13:59:48 -0700158 }
159 }
160}