aboutsummaryrefslogtreecommitdiff
path: root/xtask/src
diff options
context:
space:
mode:
Diffstat (limited to 'xtask/src')
-rw-r--r--xtask/src/codegen/gen_syntax.rs98
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
43fn generate_ast(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { 43fn 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
98fn 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 };