1#![feature(
5 never_type,
6 coverage_attribute,
7 yeet_expr,
8 anonymous_lifetime_in_impl_trait,
9 decl_macro,
10 macro_metavar_expr
11)]
12
13use {
15 rustidy_format::{Format, Formattable},
16 rustidy_parse::{Parse, ParserTag},
17 rustidy_print::Print,
18 rustidy_util::{AstStr, Whitespace},
19};
20
21pub macro decl_tokens(
22 $ws:ident;
23 $token:ident;
24 $new:ident;
25
26 $(
27 $TokenName:ident = $Token:literal
28 $( , ends_with_xid_continue $ends_with_xid_continue:tt )?
29 $( , skip_if_tag $skip_if_tag:expr )?
30 $( , must_not_follow $( $must_not_follow:literal ),* $(,)? )?
31 ;
32 )*
33) {
34 $(
35 #[derive(PartialEq, Eq, Clone, Debug)]
36 #[derive(serde::Serialize, serde::Deserialize)]
37 #[derive(Parse, Formattable, Format, Print)]
38 #[parse(error(name = NotFound, fmt("Expected `{}`", $Token)))]
39 $(
40 #[parse(skip_if_tag = $skip_if_tag)]
41 )?
42 pub struct $TokenName {
43 pub $ws: Whitespace,
44
45 #[parse(try_update_with = Self::parse)]
46 #[format(str)]
47 pub $token: AstStr,
48 }
49
50 impl $TokenName {
51 pub fn $new() -> Self {
53 Self {
54 $ws: Whitespace::empty(),
55 $token: AstStr::new($Token)
56 }
57 }
58
59 fn parse(s: &mut &str) -> Result<(), <Self as Parse>::Error> {
60 *s = s.strip_prefix($Token).ok_or(<Self as Parse>::Error::NotFound)?;
61
62 $( ${ignore($ends_with_xid_continue)}
64 if s.starts_with(|ch: char| unicode_ident::is_xid_continue(ch))
65 {
66 return Err(<Self as Parse>::Error::NotFound);
67 }
68 )?
69
70 $(
71 $(
72 if s.starts_with($must_not_follow) {
73 return Err(<Self as Parse>::Error::NotFound);
74 }
75 )*
76 )?
77
78 Ok(())
79 }
80 }
81
82 #[expect(non_snake_case, reason = "This is a tuple constructor")]
83 pub const fn $TokenName($ws: Whitespace, $token: AstStr) -> $TokenName {
84 $TokenName {
85 $ws, $token
86 }
87 }
88
89 impl Default for $TokenName {
90 fn default() -> Self {
91 Self::$new()
92 }
93 }
94 )*
95}
96
97decl_tokens! {
98 ws;
99 token;
100 new;
101
102 InnerLineDoc = "//!";
103 OuterLineDoc = "///";
104 InnerBlockDoc = "/*!";
105 OuterBlockDoc = "/**";
106
107 Super = "super", ends_with_xid_continue ();
108 SelfLower = "self", ends_with_xid_continue ();
109 SelfUpper = "Self", ends_with_xid_continue ();
110 Crate = "crate", ends_with_xid_continue (), skip_if_tag ParserTag::SkipTokenCrate;
111 DollarCrate = "$crate", ends_with_xid_continue ();
112
113 As = "as", ends_with_xid_continue ();
114 Async = "async", ends_with_xid_continue ();
115 Attr = "attr", ends_with_xid_continue ();
116 Auto = "auto", ends_with_xid_continue ();
117 Await = "await", ends_with_xid_continue ();
118 Break = "break", ends_with_xid_continue ();
119 Const = "const", ends_with_xid_continue ();
120 Continue = "continue", ends_with_xid_continue ();
121 Derive = "derive", ends_with_xid_continue ();
122 Do = "do", ends_with_xid_continue ();
123 Dyn = "dyn", ends_with_xid_continue ();
124 Else = "else", ends_with_xid_continue ();
125 Enum = "enum", ends_with_xid_continue ();
126 Extern = "extern", ends_with_xid_continue ();
127 False = "false", ends_with_xid_continue ();
128 Fn = "fn", ends_with_xid_continue ();
129 For = "for", ends_with_xid_continue ();
130 If = "if", ends_with_xid_continue ();
131 Impl = "impl", ends_with_xid_continue ();
132 In = "in", ends_with_xid_continue ();
133 Let = "let", ends_with_xid_continue ();
134 Loop = "loop", ends_with_xid_continue ();
135 Macro = "macro", ends_with_xid_continue ();
136 MacroRules = "macro_rules", ends_with_xid_continue ();
137 Match = "match", ends_with_xid_continue ();
138 Mod = "mod", ends_with_xid_continue ();
139 Move = "move", ends_with_xid_continue ();
140 Mut = "mut", ends_with_xid_continue ();
141 Pub = "pub", ends_with_xid_continue ();
142 Raw = "raw", ends_with_xid_continue ();
143 Ref = "ref", ends_with_xid_continue ();
144 Return = "return", ends_with_xid_continue ();
145 Safe = "safe", ends_with_xid_continue ();
146 Static = "static", ends_with_xid_continue ();
147 Struct = "struct", ends_with_xid_continue ();
148 Trait = "trait", ends_with_xid_continue ();
149 True = "true", ends_with_xid_continue ();
150 Try = "try", ends_with_xid_continue ();
151 Type = "type", ends_with_xid_continue ();
152 Union = "union", ends_with_xid_continue ();
153 Unsafe = "unsafe", ends_with_xid_continue ();
154 Use = "use", ends_with_xid_continue ();
155 Where = "where", ends_with_xid_continue ();
156 While = "while", ends_with_xid_continue ();
157 Yeet = "yeet", ends_with_xid_continue ();
158
159 Block = "block", ends_with_xid_continue ();
161 Expr = "expr", ends_with_xid_continue ();
162 Expr2021 = "expr_2021", ends_with_xid_continue ();
163 Ident = "ident", ends_with_xid_continue ();
164 Item = "item", ends_with_xid_continue ();
165 Lifetime = "lifetime", ends_with_xid_continue ();
166 Literal = "literal", ends_with_xid_continue ();
167 Meta = "meta", ends_with_xid_continue ();
168 Pat = "pat", ends_with_xid_continue ();
169 PatParam = "pat_param", ends_with_xid_continue ();
170 Path = "path", ends_with_xid_continue ();
171 Stmt = "stmt", ends_with_xid_continue ();
172 Tt = "tt", ends_with_xid_continue ();
173 Ty = "ty", ends_with_xid_continue ();
174 Vis = "vis", ends_with_xid_continue ();
175
176 Eq = '=', must_not_follow '=', '>';
178 Lt = '<', must_not_follow '=';
181 Le = "<=";
182 EqEq = "==";
183 Ne = "!=";
184 Ge = ">=";
185 Gt = '>', must_not_follow '=';
186 AndAnd = "&&";
187 OrOr = "||";
188 Not = '!', must_not_follow '=';
189 Tilde = '~';
190 Plus = '+', skip_if_tag ParserTag::SkipTokenPlus, must_not_follow '=';
191 Minus = '-', must_not_follow '=', '>';
192 Star = '*', skip_if_tag ParserTag::SkipTokenStar, must_not_follow '=';
193 Slash = '/', must_not_follow '=';
194 Percent = '%', must_not_follow '=';
195 Caret = '^', must_not_follow '=';
196 And = '&', must_not_follow '&', '=';
197 AndTy = '&';
198 Or = '|', must_not_follow '|', '=';
199 Shl = "<<", must_not_follow '=';
200 Shr = ">>", must_not_follow '=';
201 PlusEq = "+=";
202 MinusEq = "-=";
203 StarEq = "*=";
204 SlashEq = "/=";
205 PercentEq = "%=";
206 CaretEq = "^=";
207 AndEq = "&=";
208 OrEq = "|=";
209 ShlEq = "<<=";
210 ShrEq = ">>=";
211 At = '@';
212 Dot = '.', must_not_follow '.';
213 DotDot = "..", must_not_follow '.', '=';
214 DotDotDot = "...";
215 DotDotEq = "..=";
216 Comma = ',';
217 Semi = ';';
218 Colon = ':', must_not_follow ':';
219 PathSep = "::";
220 RArrow = "->";
221 LArrow = "<-";
222 FatArrow = "=>";
223 Pound = '#';
224 Dollar = '$', skip_if_tag ParserTag::SkipTokenDollar;
225 Question = '?', skip_if_tag ParserTag::SkipTokenQuestion;
226 Underscore = '_';
227 Quote = '\'';
228 DoubleQuote = '"';
229
230 ParenOpen = '(', skip_if_tag ParserTag::SkipDelimiters;
231 ParenClose = ')', skip_if_tag ParserTag::SkipDelimiters;
232 BracketOpen = '[', skip_if_tag ParserTag::SkipDelimiters;
233 BracketClose = ']', skip_if_tag ParserTag::SkipDelimiters;
234 BracesOpen = '{', skip_if_tag ParserTag::SkipDelimiters;
235 BracesClose = '}', skip_if_tag ParserTag::SkipDelimiters;
236
237}