diff options
Diffstat (limited to 'xtask')
-rw-r--r-- | xtask/src/codegen/gen_syntax.rs | 98 |
1 files changed, 61 insertions, 37 deletions
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 75bcd1973..683901a0a 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs | |||
@@ -23,11 +23,11 @@ pub fn generate_syntax(mode: Mode) -> Result<()> { | |||
23 | update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; | 23 | update(syntax_kinds_file.as_path(), &syntax_kinds, mode)?; |
24 | 24 | ||
25 | let ast_nodes_file = project_root().join(codegen::AST_NODES); | 25 | let ast_nodes_file = project_root().join(codegen::AST_NODES); |
26 | let contents = generate_ast(KINDS_SRC, AST_SRC)?; | 26 | let contents = generate_nodes(KINDS_SRC, AST_SRC)?; |
27 | update(ast_nodes_file.as_path(), &contents, mode)?; | 27 | update(ast_nodes_file.as_path(), &contents, mode)?; |
28 | 28 | ||
29 | let ast_tokens_file = project_root().join(codegen::AST_TOKENS); | 29 | let ast_tokens_file = project_root().join(codegen::AST_TOKENS); |
30 | let contents = "//! Generated file, do not edit by hand, see `xtask/src/codegen`"; | 30 | let contents = generate_tokens(KINDS_SRC, AST_SRC)?; |
31 | update(ast_tokens_file.as_path(), &contents, mode)?; | 31 | update(ast_tokens_file.as_path(), &contents, mode)?; |
32 | 32 | ||
33 | Ok(()) | 33 | Ok(()) |
@@ -40,7 +40,62 @@ struct ElementKinds { | |||
40 | has_tokens: bool, | 40 | has_tokens: bool, |
41 | } | 41 | } |
42 | 42 | ||
43 | fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | 43 | fn generate_tokens(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { |
44 | let all_token_kinds: Vec<_> = kinds | ||
45 | .punct | ||
46 | .into_iter() | ||
47 | .map(|(_, kind)| kind) | ||
48 | .copied() | ||
49 | .map(|x| x.into()) | ||
50 | .chain( | ||
51 | kinds | ||
52 | .keywords | ||
53 | .into_iter() | ||
54 | .chain(kinds.contextual_keywords.into_iter()) | ||
55 | .map(|name| Cow::Owned(format!("{}_KW", to_upper_snake_case(&name)))), | ||
56 | ) | ||
57 | .chain(kinds.literals.into_iter().copied().map(|x| x.into())) | ||
58 | .chain(kinds.tokens.into_iter().copied().map(|x| x.into())) | ||
59 | .collect(); | ||
60 | let tokens = all_token_kinds.iter().map(|kind_str| { | ||
61 | let kind_str = &**kind_str; | ||
62 | let kind = format_ident!("{}", kind_str); | ||
63 | let name = format_ident!("{}", to_pascal_case(kind_str)); | ||
64 | quote! { | ||
65 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
66 | pub struct #name { | ||
67 | pub(crate) syntax: SyntaxToken, | ||
68 | } | ||
69 | |||
70 | impl std::fmt::Display for #name { | ||
71 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
72 | std::fmt::Display::fmt(&self.syntax, f) | ||
73 | } | ||
74 | } | ||
75 | |||
76 | impl AstToken for #name { | ||
77 | fn can_cast(kind: SyntaxKind) -> bool { | ||
78 | match kind { | ||
79 | #kind => true, | ||
80 | _ => false, | ||
81 | } | ||
82 | } | ||
83 | fn cast(syntax: SyntaxToken) -> Option<Self> { | ||
84 | if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } | ||
85 | } | ||
86 | fn syntax(&self) -> &SyntaxToken { &self.syntax } | ||
87 | } | ||
88 | } | ||
89 | }); | ||
90 | |||
91 | crate::reformat(quote! { | ||
92 | use crate::{SyntaxToken, SyntaxKind::{self, *}, ast::AstToken}; | ||
93 | |||
94 | #(#tokens)* | ||
95 | }) | ||
96 | } | ||
97 | |||
98 | fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | ||
44 | let all_token_kinds: Vec<_> = kinds | 99 | let all_token_kinds: Vec<_> = kinds |
45 | .punct | 100 | .punct |
46 | .into_iter() | 101 | .into_iter() |
@@ -98,37 +153,6 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
98 | element_kinds_map.insert(en.name.to_string(), element_kinds); | 153 | element_kinds_map.insert(en.name.to_string(), element_kinds); |
99 | } | 154 | } |
100 | 155 | ||
101 | let tokens = all_token_kinds.iter().map(|kind_str| { | ||
102 | let kind_str = &**kind_str; | ||
103 | let kind = format_ident!("{}", kind_str); | ||
104 | let name = format_ident!("{}", to_pascal_case(kind_str)); | ||
105 | quote! { | ||
106 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
107 | pub struct #name { | ||
108 | pub(crate) syntax: SyntaxToken, | ||
109 | } | ||
110 | |||
111 | impl std::fmt::Display for #name { | ||
112 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | ||
113 | std::fmt::Display::fmt(&self.syntax, f) | ||
114 | } | ||
115 | } | ||
116 | |||
117 | impl AstToken for #name { | ||
118 | fn can_cast(kind: SyntaxKind) -> bool { | ||
119 | match kind { | ||
120 | #kind => true, | ||
121 | _ => false, | ||
122 | } | ||
123 | } | ||
124 | fn cast(syntax: SyntaxToken) -> Option<Self> { | ||
125 | if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None } | ||
126 | } | ||
127 | fn syntax(&self) -> &SyntaxToken { &self.syntax } | ||
128 | } | ||
129 | } | ||
130 | }); | ||
131 | |||
132 | let nodes = grammar.nodes.iter().map(|node| { | 156 | let nodes = grammar.nodes.iter().map(|node| { |
133 | let name = format_ident!("{}", node.name); | 157 | let name = format_ident!("{}", node.name); |
134 | let kind = format_ident!("{}", to_upper_snake_case(&name.to_string())); | 158 | let kind = format_ident!("{}", to_upper_snake_case(&name.to_string())); |
@@ -301,13 +325,13 @@ fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
301 | } | 325 | } |
302 | 326 | ||
303 | let ast = quote! { | 327 | let ast = quote! { |
304 | #[allow(unused_imports)] | ||
305 | use crate::{ | 328 | use crate::{ |
306 | SyntaxNode, SyntaxToken, SyntaxElement, NodeOrToken, SyntaxKind::{self, *}, | 329 | SyntaxNode, SyntaxToken, SyntaxKind::{self, *}, |
307 | ast::{self, AstNode, AstToken, AstChildren, support}, | 330 | ast::{self, AstNode, AstToken, AstChildren, support}, |
308 | }; | 331 | }; |
309 | 332 | ||
310 | #(#tokens)* | 333 | use super::tokens::*; |
334 | |||
311 | #(#nodes)* | 335 | #(#nodes)* |
312 | #(#enums)* | 336 | #(#enums)* |
313 | }; | 337 | }; |