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