diff options
Diffstat (limited to 'xtask')
-rw-r--r-- | xtask/src/codegen/gen_syntax.rs | 168 |
1 files changed, 28 insertions, 140 deletions
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index c730c75ee..2dfb68371 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs | |||
@@ -97,11 +97,13 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
97 | let name = format_ident!("{}", to_pascal_case(kind_str)); | 97 | let name = format_ident!("{}", to_pascal_case(kind_str)); |
98 | quote! { | 98 | quote! { |
99 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 99 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
100 | pub struct #name(SyntaxToken); | 100 | pub struct #name { |
101 | pub(crate) syntax: SyntaxToken, | ||
102 | } | ||
101 | 103 | ||
102 | impl std::fmt::Display for #name { | 104 | impl std::fmt::Display for #name { |
103 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | 105 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
104 | std::fmt::Display::fmt(self.syntax(), f) | 106 | std::fmt::Display::fmt(&self.syntax, f) |
105 | } | 107 | } |
106 | } | 108 | } |
107 | 109 | ||
@@ -112,29 +114,10 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
112 | _ => false, | 114 | _ => false, |
113 | } | 115 | } |
114 | } | 116 | } |
115 | fn cast_or_return(syntax: SyntaxToken) -> Result<Self, SyntaxToken> { | 117 | fn cast(syntax: SyntaxToken) -> Option<Self> { |
116 | if Self::can_cast(syntax.kind()) { Ok(Self(syntax)) } else { Err(syntax) } | 118 | if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } |
117 | } | ||
118 | fn syntax(&self) -> &SyntaxToken { &self.0 } | ||
119 | fn into_syntax(self) -> SyntaxToken { self.0 } | ||
120 | } | ||
121 | |||
122 | impl AstElement for #name { | ||
123 | fn can_cast_element(kind: SyntaxKind) -> bool { | ||
124 | match kind { | ||
125 | #kind => true, | ||
126 | _ => false, | ||
127 | } | ||
128 | } | ||
129 | fn cast_or_return_element(syntax: SyntaxElement) -> Result<Self, SyntaxElement> { | ||
130 | if Self::can_cast_element(syntax.kind()) { Ok(Self(syntax.into_token().unwrap())) } else { Err(syntax) } | ||
131 | } | ||
132 | fn syntax_element(&self) -> NodeOrToken<&SyntaxNode, &SyntaxToken> { | ||
133 | NodeOrToken::Token(&self.0) | ||
134 | } | ||
135 | fn into_syntax_element(self) -> SyntaxElement { | ||
136 | NodeOrToken::Token(self.0) | ||
137 | } | 119 | } |
120 | fn syntax(&self) -> &SyntaxToken { &self.syntax } | ||
138 | } | 121 | } |
139 | } | 122 | } |
140 | }); | 123 | }); |
@@ -156,28 +139,21 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
156 | FieldSrc::Optional(ty) | FieldSrc::Many(ty) => ty, | 139 | FieldSrc::Optional(ty) | FieldSrc::Many(ty) => ty, |
157 | FieldSrc::Shorthand => name, | 140 | FieldSrc::Shorthand => name, |
158 | }; | 141 | }; |
159 | let element_kinds = &element_kinds_map.get(*ty).unwrap_or_else(|| panic!("type not found: {}", *ty)); | 142 | |
160 | let iter = if !element_kinds.has_tokens { | ||
161 | format_ident!("AstChildren") | ||
162 | } else if !element_kinds.has_nodes { | ||
163 | format_ident!("AstChildTokens") | ||
164 | } else { | ||
165 | format_ident!("AstChildElements") | ||
166 | }; | ||
167 | let ty = format_ident!("{}", ty); | 143 | let ty = format_ident!("{}", ty); |
168 | 144 | ||
169 | match field { | 145 | match field { |
170 | FieldSrc::Many(_) => { | 146 | FieldSrc::Many(_) => { |
171 | quote! { | 147 | quote! { |
172 | pub fn #method_name(&self) -> #iter<#ty> { | 148 | pub fn #method_name(&self) -> AstChildren<#ty> { |
173 | #iter::new(&self.syntax) | 149 | AstChildren::new(&self.syntax) |
174 | } | 150 | } |
175 | } | 151 | } |
176 | } | 152 | } |
177 | FieldSrc::Optional(_) | FieldSrc::Shorthand => { | 153 | FieldSrc::Optional(_) | FieldSrc::Shorthand => { |
178 | quote! { | 154 | quote! { |
179 | pub fn #method_name(&self) -> Option<#ty> { | 155 | pub fn #method_name(&self) -> Option<#ty> { |
180 | #iter::new(&self.syntax).next() | 156 | AstChildren::new(&self.syntax).next() |
181 | } | 157 | } |
182 | } | 158 | } |
183 | } | 159 | } |
@@ -203,29 +179,10 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
203 | _ => false, | 179 | _ => false, |
204 | } | 180 | } |
205 | } | 181 | } |
206 | fn cast_or_return(syntax: SyntaxNode) -> Result<Self, SyntaxNode> { | 182 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
207 | if Self::can_cast(syntax.kind()) { Ok(Self { syntax }) } else { Err(syntax) } | 183 | if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } |
208 | } | 184 | } |
209 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 185 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
210 | fn into_syntax(self) -> SyntaxNode { self.syntax } | ||
211 | } | ||
212 | |||
213 | impl AstElement for #name { | ||
214 | fn can_cast_element(kind: SyntaxKind) -> bool { | ||
215 | match kind { | ||
216 | #kind => true, | ||
217 | _ => false, | ||
218 | } | ||
219 | } | ||
220 | fn cast_or_return_element(syntax: SyntaxElement) -> Result<Self, SyntaxElement> { | ||
221 | if Self::can_cast_element(syntax.kind()) { Ok(Self { syntax: syntax.into_node().unwrap() }) } else { Err(syntax) } | ||
222 | } | ||
223 | fn syntax_element(&self) -> NodeOrToken<&SyntaxNode, &SyntaxToken> { | ||
224 | NodeOrToken::Node(&self.syntax) | ||
225 | } | ||
226 | fn into_syntax_element(self) -> SyntaxElement { | ||
227 | NodeOrToken::Node(self.syntax) | ||
228 | } | ||
229 | } | 186 | } |
230 | 187 | ||
231 | #(#traits)* | 188 | #(#traits)* |
@@ -238,71 +195,16 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
238 | 195 | ||
239 | let enums = grammar.enums.iter().map(|en| { | 196 | let enums = grammar.enums.iter().map(|en| { |
240 | let variants = en.variants.iter().map(|var| format_ident!("{}", var)).collect::<Vec<_>>(); | 197 | let variants = en.variants.iter().map(|var| format_ident!("{}", var)).collect::<Vec<_>>(); |
241 | let element_kinds = &element_kinds_map[&en.name.to_string()]; | ||
242 | let name = format_ident!("{}", en.name); | 198 | let name = format_ident!("{}", en.name); |
243 | let kinds = en.variants | 199 | let kinds = variants |
244 | .iter() | 200 | .iter() |
245 | .map(|name| { | 201 | .map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string()))) |
246 | element_kinds_map[*name].kinds.iter().collect::<Vec<_>>() | ||
247 | }) | ||
248 | .collect::<Vec<_>>(); | 202 | .collect::<Vec<_>>(); |
249 | let traits = en.traits.iter().map(|trait_name| { | 203 | let traits = en.traits.iter().map(|trait_name| { |
250 | let trait_name = format_ident!("{}", trait_name); | 204 | let trait_name = format_ident!("{}", trait_name); |
251 | quote!(impl ast::#trait_name for #name {}) | 205 | quote!(impl ast::#trait_name for #name {}) |
252 | }); | 206 | }); |
253 | 207 | ||
254 | let all_kinds = &element_kinds.kinds; | ||
255 | |||
256 | let specific_ast_trait = if element_kinds.has_nodes != element_kinds.has_tokens { | ||
257 | let (ast_trait, syntax_type) = if element_kinds.has_tokens { | ||
258 | ( | ||
259 | quote!(AstToken), | ||
260 | quote!(SyntaxToken), | ||
261 | ) | ||
262 | } else { | ||
263 | ( | ||
264 | quote!(AstNode), | ||
265 | quote!(SyntaxNode), | ||
266 | ) | ||
267 | }; | ||
268 | |||
269 | quote! { | ||
270 | impl #ast_trait for #name { | ||
271 | fn can_cast(kind: SyntaxKind) -> bool { | ||
272 | match kind { | ||
273 | #(#all_kinds)|* => true, | ||
274 | _ => false, | ||
275 | } | ||
276 | } | ||
277 | #[allow(unreachable_patterns)] | ||
278 | fn cast_or_return(syntax: #syntax_type) -> Result<Self, #syntax_type> { | ||
279 | match syntax.kind() { | ||
280 | #( | ||
281 | #(#kinds)|* => #variants::cast_or_return(syntax).map(|x| #name::#variants(x)), | ||
282 | )* | ||
283 | _ => Err(syntax), | ||
284 | } | ||
285 | } | ||
286 | fn syntax(&self) -> &#syntax_type { | ||
287 | match self { | ||
288 | #( | ||
289 | #name::#variants(it) => it.syntax(), | ||
290 | )* | ||
291 | } | ||
292 | } | ||
293 | fn into_syntax(self) -> #syntax_type { | ||
294 | match self { | ||
295 | #( | ||
296 | #name::#variants(it) => it.into_syntax(), | ||
297 | )* | ||
298 | } | ||
299 | } | ||
300 | } | ||
301 | } | ||
302 | } else { | ||
303 | Default::default() | ||
304 | }; | ||
305 | |||
306 | quote! { | 208 | quote! { |
307 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 209 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
308 | pub enum #name { | 210 | pub enum #name { |
@@ -319,48 +221,34 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
319 | 221 | ||
320 | impl std::fmt::Display for #name { | 222 | impl std::fmt::Display for #name { |
321 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | 223 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { |
322 | match self { | 224 | std::fmt::Display::fmt(self.syntax(), f) |
323 | #( | ||
324 | #name::#variants(it) => std::fmt::Display::fmt(it, f), | ||
325 | )* | ||
326 | } | ||
327 | } | 225 | } |
328 | } | 226 | } |
329 | 227 | ||
330 | #specific_ast_trait | 228 | impl AstNode for #name { |
331 | 229 | fn can_cast(kind: SyntaxKind) -> bool { | |
332 | impl AstElement for #name { | ||
333 | fn can_cast_element(kind: SyntaxKind) -> bool { | ||
334 | match kind { | 230 | match kind { |
335 | #(#all_kinds)|* => true, | 231 | #(#kinds)|* => true, |
336 | _ => false, | 232 | _ => false, |
337 | } | 233 | } |
338 | } | 234 | } |
339 | #[allow(unreachable_patterns)] | 235 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
340 | fn cast_or_return_element(syntax: SyntaxElement) -> Result<Self, SyntaxElement> { | 236 | let res = match syntax.kind() { |
341 | match syntax.kind() { | ||
342 | #( | 237 | #( |
343 | #(#kinds)|* => #variants::cast_or_return_element(syntax).map(|x| #name::#variants(x)), | 238 | #kinds => #name::#variants(#variants { syntax }), |
344 | )* | 239 | )* |
345 | _ => Err(syntax), | 240 | _ => return None, |
346 | } | 241 | }; |
242 | Some(res) | ||
347 | } | 243 | } |
348 | fn syntax_element(&self) -> NodeOrToken<&SyntaxNode, &SyntaxToken> { | 244 | fn syntax(&self) -> &SyntaxNode { |
349 | match self { | 245 | match self { |
350 | #( | 246 | #( |
351 | #name::#variants(it) => it.syntax_element(), | 247 | #name::#variants(it) => &it.syntax, |
352 | )* | ||
353 | } | ||
354 | } | ||
355 | fn into_syntax_element(self) -> SyntaxElement { | ||
356 | match self { | ||
357 | #( | ||
358 | #name::#variants(it) => it.into_syntax_element(), | ||
359 | )* | 248 | )* |
360 | } | 249 | } |
361 | } | 250 | } |
362 | } | 251 | } |
363 | |||
364 | #(#traits)* | 252 | #(#traits)* |
365 | } | 253 | } |
366 | }); | 254 | }); |
@@ -380,7 +268,7 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
380 | #[allow(unused_imports)] | 268 | #[allow(unused_imports)] |
381 | use crate::{ | 269 | use crate::{ |
382 | SyntaxNode, SyntaxToken, SyntaxElement, NodeOrToken, SyntaxKind::{self, *}, | 270 | SyntaxNode, SyntaxToken, SyntaxElement, NodeOrToken, SyntaxKind::{self, *}, |
383 | ast::{self, AstNode, AstToken, AstElement, AstChildren, AstChildTokens, AstChildElements}, | 271 | ast::{self, AstNode, AstToken, AstChildren}, |
384 | }; | 272 | }; |
385 | 273 | ||
386 | #(#tokens)* | 274 | #(#tokens)* |