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