blob: 3df1b61b521542360848147f2424361fb548a3ed [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::*;
David Tolnay5fe14fc2017-01-27 16:22:08 -080098 use synom::IResult;
99 use synom::space::skip_whitespace;
David Tolnaye26baba2016-10-24 22:05:57 -0700100 use unicode_xid::UnicodeXID;
David Tolnay9d8f1972016-09-04 11:58:48 -0700101
David Tolnay05f462f2016-10-24 22:19:42 -0700102 pub fn ident(input: &str) -> IResult<&str, Ident> {
103 let (rest, id) = match word(input) {
104 IResult::Done(rest, id) => (rest, id),
105 IResult::Error => return IResult::Error,
106 };
107
108 match id.as_ref() {
109 // From https://doc.rust-lang.org/grammar.html#keywords
110 "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const" | "continue" |
111 "crate" | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" |
112 "if" | "impl" | "in" | "let" | "loop" | "macro" | "match" | "mod" | "move" |
113 "mut" | "offsetof" | "override" | "priv" | "proc" | "pub" | "pure" | "ref" |
114 "return" | "Self" | "self" | "sizeof" | "static" | "struct" | "super" | "trait" |
115 "true" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" |
116 "while" | "yield" => IResult::Error,
117 _ => IResult::Done(rest, id),
118 }
119 }
120
121 pub fn word(mut input: &str) -> IResult<&str, Ident> {
David Tolnaye26baba2016-10-24 22:05:57 -0700122 input = skip_whitespace(input);
123
124 let mut chars = input.char_indices();
125 match chars.next() {
126 Some((_, ch)) if UnicodeXID::is_xid_start(ch) || ch == '_' => {}
127 _ => return IResult::Error,
128 }
129
David Tolnay02a8d472017-02-19 12:59:44 -0800130 for (i, ch) in chars {
David Tolnaye26baba2016-10-24 22:05:57 -0700131 if !UnicodeXID::is_xid_continue(ch) {
132 return IResult::Done(&input[i..], input[..i].into());
133 }
134 }
135
136 IResult::Done("", input.into())
David Tolnay9d8f1972016-09-04 11:58:48 -0700137 }
David Tolnay39039442016-10-30 11:25:21 -0700138
David Tolnayb19657b2016-10-30 12:48:32 -0700139 #[cfg(feature = "full")]
David Tolnay39039442016-10-30 11:25:21 -0700140 pub fn wordlike(mut input: &str) -> IResult<&str, Ident> {
141 input = skip_whitespace(input);
142
143 for (i, ch) in input.char_indices() {
144 if !UnicodeXID::is_xid_start(ch) && !UnicodeXID::is_xid_continue(ch) {
145 return if i == 0 {
David Tolnay05120ef2017-03-12 18:29:26 -0700146 IResult::Error
147 } else {
148 IResult::Done(&input[i..], input[..i].into())
149 };
David Tolnay39039442016-10-30 11:25:21 -0700150 }
151 }
152
153 IResult::Done("", input.into())
154 }
David Tolnayb79ee962016-09-04 09:39:20 -0700155}
David Tolnay26469072016-09-04 13:59:48 -0700156
157#[cfg(feature = "printing")]
158mod printing {
159 use super::*;
160 use quote::{Tokens, ToTokens};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700161 use proc_macro2::{TokenTree, TokenKind};
David Tolnay26469072016-09-04 13:59:48 -0700162
163 impl ToTokens for Ident {
164 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700165 tokens.append(TokenTree {
166 span: self.span.0,
167 kind: TokenKind::Word(self.sym),
168 })
David Tolnay26469072016-09-04 13:59:48 -0700169 }
170 }
171}