blob: 1ed2c3e9568ac3bc7695be80496fda0dd8266429 [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;
9
10#[derive(Clone)]
11pub struct Ident {
12 pub sym: Symbol,
13 pub span: Span,
14}
David Tolnay42f50292016-09-04 13:54:21 -070015
16impl Ident {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070017 pub fn new(sym: Symbol, span: Span) -> Self {
18 Ident {
19 sym: sym,
20 span: span,
21 }
David Tolnay42f50292016-09-04 13:54:21 -070022 }
23}
24
25impl<'a> From<&'a str> for Ident {
26 fn from(s: &str) -> Self {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070027 Ident::new(s.into(), Span::default())
David Tolnay42f50292016-09-04 13:54:21 -070028 }
29}
30
David Tolnayf733f7e2016-11-25 10:36:25 -080031impl<'a> From<Cow<'a, str>> for Ident {
32 fn from(s: Cow<'a, str>) -> Self {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070033 Ident::new(s[..].into(), Span::default())
David Tolnayf733f7e2016-11-25 10:36:25 -080034 }
35}
36
David Tolnay42f50292016-09-04 13:54:21 -070037impl From<String> for Ident {
38 fn from(s: String) -> Self {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070039 Ident::new(s[..].into(), Span::default())
David Tolnay42f50292016-09-04 13:54:21 -070040 }
41}
42
David Tolnayc1683102016-09-27 08:17:58 -070043impl From<usize> for Ident {
44 fn from(u: usize) -> Self {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070045 Ident::new(u.to_string()[..].into(), Span::default())
David Tolnayc1683102016-09-27 08:17:58 -070046 }
47}
48
David Tolnay26469072016-09-04 13:59:48 -070049impl AsRef<str> for Ident {
50 fn as_ref(&self) -> &str {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070051 self.sym.as_str()
David Tolnay42f50292016-09-04 13:54:21 -070052 }
53}
54
55impl Display for Ident {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070056 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
57 self.sym.as_str().fmt(formatter)
58 }
59}
60
61impl fmt::Debug for Ident {
62 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
63 fmt::Debug::fmt(self.sym.as_str(), formatter)
David Tolnay42f50292016-09-04 13:54:21 -070064 }
65}
David Tolnayb79ee962016-09-04 09:39:20 -070066
David Tolnaydaaf7742016-10-03 11:11:43 -070067impl<T: ?Sized> PartialEq<T> for Ident
68 where T: AsRef<str>
69{
David Tolnay55337722016-09-11 12:58:56 -070070 fn eq(&self, other: &T) -> bool {
Alex Crichtonccbb45d2017-05-23 10:58:24 -070071 self.as_ref() == other.as_ref()
72 }
73}
74
75impl Eq for Ident {}
76
77impl PartialOrd for Ident {
78 fn partial_cmp(&self, other: &Ident) -> Option<Ordering> {
79 Some(self.cmp(other))
80 }
81}
82
83impl Ord for Ident {
84 fn cmp(&self, other: &Ident) -> Ordering {
85 self.as_ref().cmp(other.as_ref())
86 }
87}
88
89impl Hash for Ident {
90 fn hash<H: Hasher>(&self, h: &mut H) {
91 self.as_ref().hash(h)
David Tolnay55337722016-09-11 12:58:56 -070092 }
David Tolnayb79ee962016-09-04 09:39:20 -070093}
94
David Tolnay86eca752016-09-04 11:26:41 -070095#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -070096pub mod parsing {
97 use super::*;
Michael Layzell416724e2017-05-24 21:12:34 -040098 use synom::{TokenTree, TokenKind, IResult};
99 #[cfg(feature = "full")]
100 use lit::parsing::int;
David Tolnay9d8f1972016-09-04 11:58:48 -0700101
Michael Layzell416724e2017-05-24 21:12:34 -0400102 pub fn ident(input: &[TokenTree]) -> IResult<&[TokenTree], Ident> {
103 if let IResult::Done(rest, id) = word(input) {
104 match id.as_ref() {
105 // From https://doc.rust-lang.org/grammar.html#keywords
106 "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const" | "continue" |
107 "crate" | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" |
108 "if" | "impl" | "in" | "let" | "loop" | "macro" | "match" | "mod" | "move" |
109 "mut" | "offsetof" | "override" | "priv" | "proc" | "pub" | "pure" | "ref" |
110 "return" | "Self" | "self" | "sizeof" | "static" | "struct" | "super" | "trait" |
111 "true" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" |
112 "while" | "yield" => IResult::Error,
113 _ => IResult::Done(rest, id),
114 }
115 } else {
116 IResult::Error
David Tolnay05f462f2016-10-24 22:19:42 -0700117 }
118 }
119
Michael Layzell416724e2017-05-24 21:12:34 -0400120 pub fn word(input: &[TokenTree]) -> IResult<&[TokenTree], Ident> {
121 if let Some(&TokenTree { kind: TokenKind::Word(ref id), .. }) = input.first() {
122 // Check if this word is _actually_ a lifetime, and treat that differently
123 if id.chars().next().unwrap() == '\'' {
124 IResult::Error
125 } else {
126 IResult::Done(&input[1..], Ident(id.to_string()))
David Tolnaye26baba2016-10-24 22:05:57 -0700127 }
Michael Layzell416724e2017-05-24 21:12:34 -0400128 } else {
129 IResult::Error
David Tolnaye26baba2016-10-24 22:05:57 -0700130 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700131 }
David Tolnay39039442016-10-30 11:25:21 -0700132
David Tolnayb19657b2016-10-30 12:48:32 -0700133 #[cfg(feature = "full")]
Michael Layzell416724e2017-05-24 21:12:34 -0400134 named!(pub wordlike -> Ident, alt!(
135 word
136 |
137 int => { |d| format!("{}", d).into() }
138 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700139}
David Tolnay26469072016-09-04 13:59:48 -0700140
141#[cfg(feature = "printing")]
142mod printing {
143 use super::*;
144 use quote::{Tokens, ToTokens};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700145 use proc_macro2::{TokenTree, TokenKind};
David Tolnay26469072016-09-04 13:59:48 -0700146
147 impl ToTokens for Ident {
148 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700149 tokens.append(TokenTree {
150 span: self.span.0,
151 kind: TokenKind::Word(self.sym),
152 })
David Tolnay26469072016-09-04 13:59:48 -0700153 }
154 }
155}