diff options
author | Aleksey Kladov <[email protected]> | 2020-04-09 16:58:15 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-04-09 16:58:15 +0100 |
commit | 4a063e651f0ec0da852ce1f87589d5c0a893c59d (patch) | |
tree | 1206b6185253043900f325b620997a7a648f82cb /xtask/src/codegen | |
parent | c80795e27491527487f97368be54b4467eb8b41e (diff) |
Move the rest of the tokens to generated/tokens
Diffstat (limited to 'xtask/src/codegen')
-rw-r--r-- | xtask/src/codegen/gen_syntax.rs | 170 |
1 files changed, 90 insertions, 80 deletions
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 683901a0a..9801a3dba 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs | |||
@@ -5,7 +5,7 @@ | |||
5 | 5 | ||
6 | use std::{ | 6 | use std::{ |
7 | borrow::Cow, | 7 | borrow::Cow, |
8 | collections::{BTreeSet, HashMap, HashSet}, | 8 | collections::{BTreeSet, HashSet}, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | use proc_macro2::{Punct, Spacing}; | 11 | use proc_macro2::{Punct, Spacing}; |
@@ -57,6 +57,7 @@ fn generate_tokens(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
57 | .chain(kinds.literals.into_iter().copied().map(|x| x.into())) | 57 | .chain(kinds.literals.into_iter().copied().map(|x| x.into())) |
58 | .chain(kinds.tokens.into_iter().copied().map(|x| x.into())) | 58 | .chain(kinds.tokens.into_iter().copied().map(|x| x.into())) |
59 | .collect(); | 59 | .collect(); |
60 | |||
60 | let tokens = all_token_kinds.iter().map(|kind_str| { | 61 | let tokens = all_token_kinds.iter().map(|kind_str| { |
61 | let kind_str = &**kind_str; | 62 | let kind_str = &**kind_str; |
62 | let kind = format_ident!("{}", kind_str); | 63 | let kind = format_ident!("{}", kind_str); |
@@ -88,10 +89,67 @@ fn generate_tokens(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
88 | } | 89 | } |
89 | }); | 90 | }); |
90 | 91 | ||
92 | let enums = grammar.token_enums.iter().map(|en| { | ||
93 | let variants = en.variants.iter().map(|var| format_ident!("{}", var)).collect::<Vec<_>>(); | ||
94 | let name = format_ident!("{}", en.name); | ||
95 | let kinds = variants | ||
96 | .iter() | ||
97 | .map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string()))) | ||
98 | .collect::<Vec<_>>(); | ||
99 | assert!(en.traits.is_empty()); | ||
100 | |||
101 | quote! { | ||
102 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
103 | pub enum #name { | ||
104 | #(#variants(#variants),)* | ||
105 | } | ||
106 | |||
107 | #( | ||
108 | impl From<#variants> for #name { | ||
109 | fn from(node: #variants) -> #name { | ||
110 | #name::#variants(node) | ||
111 | } | ||
112 | } | ||
113 | )* | ||
114 | |||
115 | impl std::fmt::Display for #name { | ||
116 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
117 | std::fmt::Display::fmt(self.syntax(), f) | ||
118 | } | ||
119 | } | ||
120 | |||
121 | impl AstToken for #name { | ||
122 | fn can_cast(kind: SyntaxKind) -> bool { | ||
123 | match kind { | ||
124 | #(#kinds)|* => true, | ||
125 | _ => false, | ||
126 | } | ||
127 | } | ||
128 | fn cast(syntax: SyntaxToken) -> Option<Self> { | ||
129 | let res = match syntax.kind() { | ||
130 | #( | ||
131 | #kinds => #name::#variants(#variants { syntax }), | ||
132 | )* | ||
133 | _ => return None, | ||
134 | }; | ||
135 | Some(res) | ||
136 | } | ||
137 | fn syntax(&self) -> &SyntaxToken { | ||
138 | match self { | ||
139 | #( | ||
140 | #name::#variants(it) => &it.syntax, | ||
141 | )* | ||
142 | } | ||
143 | } | ||
144 | } | ||
145 | } | ||
146 | }); | ||
147 | |||
91 | crate::reformat(quote! { | 148 | crate::reformat(quote! { |
92 | use crate::{SyntaxToken, SyntaxKind::{self, *}, ast::AstToken}; | 149 | use crate::{SyntaxToken, SyntaxKind::{self, *}, ast::AstToken}; |
93 | 150 | ||
94 | #(#tokens)* | 151 | #(#tokens)* |
152 | #(#enums)* | ||
95 | }) | 153 | }) |
96 | } | 154 | } |
97 | 155 | ||
@@ -113,44 +171,15 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
113 | .chain(kinds.tokens.into_iter().copied().map(|x| x.into())) | 171 | .chain(kinds.tokens.into_iter().copied().map(|x| x.into())) |
114 | .collect(); | 172 | .collect(); |
115 | 173 | ||
116 | let mut element_kinds_map = HashMap::new(); | 174 | let mut token_kinds = HashSet::new(); |
117 | for kind in &all_token_kinds { | 175 | for kind in &all_token_kinds { |
118 | let kind = &**kind; | 176 | let kind = &**kind; |
119 | let name = to_pascal_case(kind); | 177 | let name = to_pascal_case(kind); |
120 | element_kinds_map.insert( | 178 | token_kinds.insert(name); |
121 | name, | ||
122 | ElementKinds { | ||
123 | kinds: Some(format_ident!("{}", kind)).into_iter().collect(), | ||
124 | has_nodes: false, | ||
125 | has_tokens: true, | ||
126 | }, | ||
127 | ); | ||
128 | } | 179 | } |
129 | 180 | ||
130 | for kind in kinds.nodes { | 181 | for en in grammar.token_enums { |
131 | let name = to_pascal_case(kind); | 182 | token_kinds.insert(en.name.to_string()); |
132 | element_kinds_map.insert( | ||
133 | name, | ||
134 | ElementKinds { | ||
135 | kinds: Some(format_ident!("{}", *kind)).into_iter().collect(), | ||
136 | has_nodes: true, | ||
137 | has_tokens: false, | ||
138 | }, | ||
139 | ); | ||
140 | } | ||
141 | |||
142 | for en in grammar.enums { | ||
143 | let mut element_kinds: ElementKinds = Default::default(); | ||
144 | for variant in en.variants { | ||
145 | if let Some(variant_element_kinds) = element_kinds_map.get(*variant) { | ||
146 | element_kinds.kinds.extend(variant_element_kinds.kinds.iter().cloned()); | ||
147 | element_kinds.has_tokens |= variant_element_kinds.has_tokens; | ||
148 | element_kinds.has_nodes |= variant_element_kinds.has_nodes; | ||
149 | } else { | ||
150 | panic!("Enum variant has type that does not exist or was not declared before the enum: {}", *variant); | ||
151 | } | ||
152 | } | ||
153 | element_kinds_map.insert(en.name.to_string(), element_kinds); | ||
154 | } | 183 | } |
155 | 184 | ||
156 | let nodes = grammar.nodes.iter().map(|node| { | 185 | let nodes = grammar.nodes.iter().map(|node| { |
@@ -182,7 +211,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
182 | } | 211 | } |
183 | } | 212 | } |
184 | FieldSrc::Optional(_) | FieldSrc::Shorthand => { | 213 | FieldSrc::Optional(_) | FieldSrc::Shorthand => { |
185 | let is_token = element_kinds_map[&ty.to_string()].has_tokens; | 214 | let is_token = token_kinds.contains(&ty.to_string()); |
186 | if is_token { | 215 | if is_token { |
187 | quote! { | 216 | quote! { |
188 | pub fn #method_name(&self) -> Option<#ty> { | 217 | pub fn #method_name(&self) -> Option<#ty> { |
@@ -245,48 +274,6 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
245 | quote!(impl ast::#trait_name for #name {}) | 274 | quote!(impl ast::#trait_name for #name {}) |
246 | }); | 275 | }); |
247 | 276 | ||
248 | let element_kinds = &element_kinds_map[&en.name.to_string()]; | ||
249 | assert!( | ||
250 | element_kinds.has_nodes ^ element_kinds.has_tokens, | ||
251 | "{}: {:#?}", | ||
252 | name, | ||
253 | element_kinds | ||
254 | ); | ||
255 | let specific_ast_trait = { | ||
256 | let (ast_trait, syntax_type) = if element_kinds.has_tokens { | ||
257 | (quote!(AstToken), quote!(SyntaxToken)) | ||
258 | } else { | ||
259 | (quote!(AstNode), quote!(SyntaxNode)) | ||
260 | }; | ||
261 | |||
262 | quote! { | ||
263 | impl #ast_trait for #name { | ||
264 | fn can_cast(kind: SyntaxKind) -> bool { | ||
265 | match kind { | ||
266 | #(#kinds)|* => true, | ||
267 | _ => false, | ||
268 | } | ||
269 | } | ||
270 | fn cast(syntax: #syntax_type) -> Option<Self> { | ||
271 | let res = match syntax.kind() { | ||
272 | #( | ||
273 | #kinds => #name::#variants(#variants { syntax }), | ||
274 | )* | ||
275 | _ => return None, | ||
276 | }; | ||
277 | Some(res) | ||
278 | } | ||
279 | fn syntax(&self) -> &#syntax_type { | ||
280 | match self { | ||
281 | #( | ||
282 | #name::#variants(it) => &it.syntax, | ||
283 | )* | ||
284 | } | ||
285 | } | ||
286 | } | ||
287 | } | ||
288 | }; | ||
289 | |||
290 | quote! { | 277 | quote! { |
291 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 278 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
292 | pub enum #name { | 279 | pub enum #name { |
@@ -307,7 +294,30 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
307 | } | 294 | } |
308 | } | 295 | } |
309 | 296 | ||
310 | #specific_ast_trait | 297 | impl AstNode for #name { |
298 | fn can_cast(kind: SyntaxKind) -> bool { | ||
299 | match kind { | ||
300 | #(#kinds)|* => true, | ||
301 | _ => false, | ||
302 | } | ||
303 | } | ||
304 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
305 | let res = match syntax.kind() { | ||
306 | #( | ||
307 | #kinds => #name::#variants(#variants { syntax }), | ||
308 | )* | ||
309 | _ => return None, | ||
310 | }; | ||
311 | Some(res) | ||
312 | } | ||
313 | fn syntax(&self) -> &SyntaxNode { | ||
314 | match self { | ||
315 | #( | ||
316 | #name::#variants(it) => &it.syntax, | ||
317 | )* | ||
318 | } | ||
319 | } | ||
320 | } | ||
311 | 321 | ||
312 | #(#traits)* | 322 | #(#traits)* |
313 | } | 323 | } |
@@ -326,8 +336,8 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
326 | 336 | ||
327 | let ast = quote! { | 337 | let ast = quote! { |
328 | use crate::{ | 338 | use crate::{ |
329 | SyntaxNode, SyntaxToken, SyntaxKind::{self, *}, | 339 | SyntaxNode, SyntaxKind::{self, *}, |
330 | ast::{self, AstNode, AstToken, AstChildren, support}, | 340 | ast::{self, AstNode, AstChildren, support}, |
331 | }; | 341 | }; |
332 | 342 | ||
333 | use super::tokens::*; | 343 | use super::tokens::*; |