blob: 8f698be4964fc8f2f7745766e53d8fee97dfb480 [file] [log] [blame]
David Tolnayf733f7e2016-11-25 10:36:25 -08001use std::borrow::Cow;
David Tolnay42f50292016-09-04 13:54:21 -07002use std::fmt::{self, Display};
David Tolnay42f50292016-09-04 13:54:21 -07003
David Tolnayd23b2472017-04-02 21:31:48 -07004#[derive(Debug, Clone, Eq, Hash, Ord, PartialOrd)]
David Tolnay42f50292016-09-04 13:54:21 -07005pub struct Ident(String);
6
7impl Ident {
8 pub fn new<T: Into<Ident>>(t: T) -> Self {
9 t.into()
10 }
11}
12
13impl<'a> From<&'a str> for Ident {
14 fn from(s: &str) -> Self {
15 Ident(s.to_owned())
16 }
17}
18
David Tolnayf733f7e2016-11-25 10:36:25 -080019impl<'a> From<Cow<'a, str>> for Ident {
20 fn from(s: Cow<'a, str>) -> Self {
21 Ident(s.into_owned())
22 }
23}
24
David Tolnay42f50292016-09-04 13:54:21 -070025impl From<String> for Ident {
26 fn from(s: String) -> Self {
27 Ident(s)
28 }
29}
30
David Tolnayc1683102016-09-27 08:17:58 -070031impl From<usize> for Ident {
32 fn from(u: usize) -> Self {
33 Ident(u.to_string())
34 }
35}
36
David Tolnay26469072016-09-04 13:59:48 -070037impl AsRef<str> for Ident {
38 fn as_ref(&self) -> &str {
David Tolnay42f50292016-09-04 13:54:21 -070039 &self.0
40 }
41}
42
43impl Display for Ident {
44 fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
45 self.0.fmt(formatter)
46 }
47}
David Tolnayb79ee962016-09-04 09:39:20 -070048
David Tolnaydaaf7742016-10-03 11:11:43 -070049impl<T: ?Sized> PartialEq<T> for Ident
50 where T: AsRef<str>
51{
David Tolnay55337722016-09-11 12:58:56 -070052 fn eq(&self, other: &T) -> bool {
53 self.0 == other.as_ref()
54 }
David Tolnayb79ee962016-09-04 09:39:20 -070055}
56
David Tolnay86eca752016-09-04 11:26:41 -070057#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -070058pub mod parsing {
59 use super::*;
David Tolnay5fe14fc2017-01-27 16:22:08 -080060 use synom::IResult;
61 use synom::space::skip_whitespace;
David Tolnaye26baba2016-10-24 22:05:57 -070062 use unicode_xid::UnicodeXID;
David Tolnay9d8f1972016-09-04 11:58:48 -070063
David Tolnay05f462f2016-10-24 22:19:42 -070064 pub fn ident(input: &str) -> IResult<&str, Ident> {
65 let (rest, id) = match word(input) {
66 IResult::Done(rest, id) => (rest, id),
67 IResult::Error => return IResult::Error,
68 };
69
70 match id.as_ref() {
71 // From https://doc.rust-lang.org/grammar.html#keywords
72 "abstract" | "alignof" | "as" | "become" | "box" | "break" | "const" | "continue" |
73 "crate" | "do" | "else" | "enum" | "extern" | "false" | "final" | "fn" | "for" |
74 "if" | "impl" | "in" | "let" | "loop" | "macro" | "match" | "mod" | "move" |
75 "mut" | "offsetof" | "override" | "priv" | "proc" | "pub" | "pure" | "ref" |
76 "return" | "Self" | "self" | "sizeof" | "static" | "struct" | "super" | "trait" |
77 "true" | "type" | "typeof" | "unsafe" | "unsized" | "use" | "virtual" | "where" |
78 "while" | "yield" => IResult::Error,
79 _ => IResult::Done(rest, id),
80 }
81 }
82
83 pub fn word(mut input: &str) -> IResult<&str, Ident> {
David Tolnaye26baba2016-10-24 22:05:57 -070084 input = skip_whitespace(input);
85
86 let mut chars = input.char_indices();
87 match chars.next() {
88 Some((_, ch)) if UnicodeXID::is_xid_start(ch) || ch == '_' => {}
89 _ => return IResult::Error,
90 }
91
David Tolnay02a8d472017-02-19 12:59:44 -080092 for (i, ch) in chars {
David Tolnaye26baba2016-10-24 22:05:57 -070093 if !UnicodeXID::is_xid_continue(ch) {
94 return IResult::Done(&input[i..], input[..i].into());
95 }
96 }
97
98 IResult::Done("", input.into())
David Tolnay9d8f1972016-09-04 11:58:48 -070099 }
David Tolnay39039442016-10-30 11:25:21 -0700100
David Tolnayb19657b2016-10-30 12:48:32 -0700101 #[cfg(feature = "full")]
David Tolnay39039442016-10-30 11:25:21 -0700102 pub fn wordlike(mut input: &str) -> IResult<&str, Ident> {
103 input = skip_whitespace(input);
104
105 for (i, ch) in input.char_indices() {
106 if !UnicodeXID::is_xid_start(ch) && !UnicodeXID::is_xid_continue(ch) {
107 return if i == 0 {
David Tolnay05120ef2017-03-12 18:29:26 -0700108 IResult::Error
109 } else {
110 IResult::Done(&input[i..], input[..i].into())
111 };
David Tolnay39039442016-10-30 11:25:21 -0700112 }
113 }
114
115 IResult::Done("", input.into())
116 }
David Tolnayb79ee962016-09-04 09:39:20 -0700117}
David Tolnay26469072016-09-04 13:59:48 -0700118
119#[cfg(feature = "printing")]
120mod printing {
121 use super::*;
122 use quote::{Tokens, ToTokens};
123
124 impl ToTokens for Ident {
125 fn to_tokens(&self, tokens: &mut Tokens) {
126 tokens.append(self.as_ref())
127 }
128 }
129}