1use super::ToTokens;
2use super::lex::{Cursor, LexError, Scan};
3use crate::{Span, Spanner, TokenStream, TokenTree};
4
5macro_rules! define_keyword {
6 ($($name:ident[$is_method:ident, $as_method:ident] => $text:literal),+ $(,)?) => {
7 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
8 pub enum Keyword {
9 $($name($name),)*
10 }
11
12 impl Keyword {
13 #[inline]
14 pub fn as_str(&self) -> &'static str {
15 match self {
16 $(Self::$name(v) => v.as_str(),)*
17 }
18 }
19
20 #[inline]
21 pub fn span(&self) -> Span {
22 match self {
23 $(Self::$name(v) => v.span(),)*
24 }
25 }
26
27 #[inline]
28 pub fn set_span(&mut self, span: Span) {
29 match self {
30 $(Self::$name(v) => v.set_span(span),)*
31 }
32 }
33
34 #[inline]
35 pub fn from_str(text: &str, span: Span) -> Option<Self> {
36 match text {
37 $($text => Some(Self::$name($name::new(span))),)*
38 _ => None,
39 }
40 }
41
42 #[inline]
43 pub fn to_token_tree(&self) -> TokenTree {
44 TokenTree::Keyword(*self)
45 }
46
47 #[inline]
48 pub fn into_token_tree(self) -> TokenTree {
49 TokenTree::Keyword(self)
50 }
51 }
52
53 impl Scan for Keyword {
54 fn scan(cursor: Cursor<'_>) -> Result<(Cursor<'_>, Self), LexError> {
55 let (end, id) = super::Ident::scan(cursor)?;
56
57 if id.is_raw() {
58 return cursor.error().into();
59 }
60
61 match id.text() {
62 $($text => Ok((end, Self::$name($name::new(id.span())))),)*
63 _ => cursor.error().into(),
64 }
65 }
66 }
67
68 impl ToTokens for Keyword {
69 fn to_tokens(&self, tokens: &mut TokenStream) {
70 match self {
71 $(Self::$name(v) => v.to_tokens(tokens),)*
72 }
73 }
74 }
75
76 impl Spanner for Keyword {
77 fn span(&self) -> Span {
78 self.span()
79 }
80 }
81
82 impl std::fmt::Display for Keyword {
83 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
84 match self {
85 $(Self::$name(v) => v.fmt(f),)*
86 }
87 }
88 }
89
90 #[cfg(feature = "serde")]
91 impl serde::Serialize for Keyword {
92 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
93 where
94 S: serde::Serializer,
95 {
96 self.as_str().serialize(s)
97 }
98 }
99
100 $(
101 #[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash)]
102 pub struct $name {
103 span: Span,
104 }
105
106 impl $name {
107 pub const TEXT: &'static str = $text;
108
109 #[inline]
110 pub fn new(span: Span) -> Self {
111 Self { span }
112 }
113
114 #[inline]
115 pub fn span(&self) -> Span {
116 self.span
117 }
118
119 #[inline]
120 pub fn set_span(&mut self, span: Span) {
121 self.span = span;
122 }
123
124 #[inline]
125 pub fn as_str(&self) -> &'static str {
126 Self::TEXT
127 }
128 }
129
130 impl std::fmt::Display for $name {
131 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
132 f.write_str($text)
133 }
134 }
135
136 impl Scan for $name {
137 fn scan(cursor: Cursor<'_>) -> Result<(Cursor<'_>, Self), LexError> {
138 let (end, id) = super::Ident::scan(cursor)?;
139
140 if !id.is_raw() && id.text() == $text {
141 Ok((end, Self::new(id.span())))
142 } else {
143 cursor.error().into()
144 }
145 }
146 }
147
148 impl ToTokens for $name {
149 fn to_tokens(&self, tokens: &mut TokenStream) {
150 tokens.extend_one(TokenTree::Keyword(Keyword::$name(*self)));
151 }
152 }
153
154 impl Spanner for $name {
155 fn span(&self) -> Span {
156 self.span
157 }
158 }
159
160 impl From<$name> for Keyword {
161 fn from(value: $name) -> Self {
162 Self::$name(value)
163 }
164 }
165
166 #[cfg(feature = "serde")]
167 impl serde::Serialize for $name {
168 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
169 where
170 S: serde::Serializer,
171 {
172 self.as_str().serialize(s)
173 }
174 }
175 )+
176
177 impl TokenTree {
178 pub fn is_keyword(&self) -> bool {
179 matches!(self, Self::Keyword(_))
180 }
181
182 pub fn as_keyword(&self) -> Option<&Keyword> {
183 match self {
184 Self::Keyword(v) => Some(v),
185 _ => None,
186 }
187 }
188
189 $(
190 #[doc = concat!("**", stringify!($name), "** (\"", $text, "\")")]
191 pub fn $is_method(&self) -> bool {
192 matches!(self, Self::Keyword(Keyword::$name(_)))
193 }
194
195 #[doc = concat!("**", stringify!($name), "** (\"", $text, "\")")]
196 pub fn $as_method(&self) -> Option<&$name> {
197 match self {
198 Self::Keyword(Keyword::$name(v)) => Some(v),
199 _ => None,
200 }
201 }
202 )*
203 }
204 };
205}
206
207define_keyword! {
208 As[is_keyword_as, as_keyword_as] => "as",
209 Async[is_keyword_async, as_keyword_async] => "async",
210 Auto[is_keyword_auto, as_keyword_auto] => "auto",
211 Await[is_keyword_await, as_keyword_await] => "await",
212 Become[is_keyword_become, as_keyword_become] => "become",
213 Box[is_keyword_box, as_keyword_box] => "box",
214 Break[is_keyword_break, as_keyword_break] => "break",
215 Const[is_keyword_const, as_keyword_const] => "const",
216 Continue[is_keyword_continue, as_keyword_continue] => "continue",
217 Crate[is_keyword_crate, as_keyword_crate] => "crate",
218 Default[is_keyword_default, as_keyword_default] => "default",
219 Do[is_keyword_do, as_keyword_do] => "do",
220 Dyn[is_keyword_dyn, as_keyword_dyn] => "dyn",
221 Else[is_keyword_else, as_keyword_else] => "else",
222 Enum[is_keyword_enum, as_keyword_enum] => "enum",
223 Extern[is_keyword_extern, as_keyword_extern] => "extern",
224 Final[is_keyword_final, as_keyword_final] => "final",
225 Fn[is_keyword_fn, as_keyword_fn] => "fn",
226 For[is_keyword_for, as_keyword_for] => "for",
227 If[is_keyword_if, as_keyword_if] => "if",
228 Impl[is_keyword_impl, as_keyword_impl] => "impl",
229 In[is_keyword_in, as_keyword_in] => "in",
230 Let[is_keyword_let, as_keyword_let] => "let",
231 Loop[is_keyword_loop, as_keyword_loop] => "loop",
232 Macro[is_keyword_macro, as_keyword_macro] => "macro",
233 MacroRules[is_keyword_macro_rules, as_keyword_macro_rules] => "macro_rules",
234 Match[is_keyword_match, as_keyword_match] => "match",
235 Mod[is_keyword_mod, as_keyword_mod] => "mod",
236 Move[is_keyword_move, as_keyword_move] => "move",
237 Mut[is_keyword_mut, as_keyword_mut] => "mut",
238 Override[is_keyword_override, as_keyword_override] => "override",
239 Priv[is_keyword_priv, as_keyword_priv] => "priv",
240 Pub[is_keyword_pub, as_keyword_pub] => "pub",
241 Raw[is_keyword_raw, as_keyword_raw] => "raw",
242 Ref[is_keyword_ref, as_keyword_ref] => "ref",
243 Return[is_keyword_return, as_keyword_return] => "return",
244 SelfType[is_keyword_self_type, as_keyword_self_type] => "Self",
245 SelfValue[is_keyword_self_value, as_keyword_self_value] => "self",
246 Static[is_keyword_static, as_keyword_static] => "static",
247 Struct[is_keyword_struct, as_keyword_struct] => "struct",
248 Super[is_keyword_super, as_keyword_super] => "super",
249 Trait[is_keyword_trait, as_keyword_trait] => "trait",
250 Try[is_keyword_try, as_keyword_try] => "try",
251 Type[is_keyword_type, as_keyword_type] => "type",
252 Typeof[is_keyword_typeof, as_keyword_typeof] => "typeof",
253 Union[is_keyword_union, as_keyword_union] => "union",
254 Unsafe[is_keyword_unsafe, as_keyword_unsafe] => "unsafe",
255 Unsized[is_keyword_unsized, as_keyword_unsized] => "unsized",
256 Use[is_keyword_use, as_keyword_use] => "use",
257 Virtual[is_keyword_virtual, as_keyword_virtual] => "virtual",
258 Where[is_keyword_where, as_keyword_where] => "where",
259 While[is_keyword_while, as_keyword_while] => "while",
260 Yield[is_keyword_yield, as_keyword_yield] => "yield",
261}