aboutsummaryrefslogtreecommitdiff
path: root/xtask/src/codegen
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2020-04-09 16:58:15 +0100
committerAleksey Kladov <[email protected]>2020-04-09 16:58:15 +0100
commit4a063e651f0ec0da852ce1f87589d5c0a893c59d (patch)
tree1206b6185253043900f325b620997a7a648f82cb /xtask/src/codegen
parentc80795e27491527487f97368be54b4467eb8b41e (diff)
Move the rest of the tokens to generated/tokens
Diffstat (limited to 'xtask/src/codegen')
-rw-r--r--xtask/src/codegen/gen_syntax.rs170
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
6use std::{ 6use std::{
7 borrow::Cow, 7 borrow::Cow,
8 collections::{BTreeSet, HashMap, HashSet}, 8 collections::{BTreeSet, HashSet},
9}; 9};
10 10
11use proc_macro2::{Punct, Spacing}; 11use 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::*;