Skip to main content

moxy_token/
keyword.rs

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}