diff options
Diffstat (limited to 'xtask/src/codegen/gen_syntax.rs')
-rw-r--r-- | xtask/src/codegen/gen_syntax.rs | 87 |
1 files changed, 57 insertions, 30 deletions
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 45b788bdb..cafad8070 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs | |||
@@ -10,7 +10,7 @@ use std::{ | |||
10 | 10 | ||
11 | use proc_macro2::{Punct, Spacing}; | 11 | use proc_macro2::{Punct, Spacing}; |
12 | use quote::{format_ident, quote}; | 12 | use quote::{format_ident, quote}; |
13 | use ungrammar::{Grammar, Rule}; | 13 | use ungrammar::{rust_grammar, Grammar, Rule}; |
14 | 14 | ||
15 | use crate::{ | 15 | use crate::{ |
16 | ast_src::{AstEnumSrc, AstNodeSrc, AstSrc, Cardinality, Field, KindsSrc, KINDS_SRC}, | 16 | ast_src::{AstEnumSrc, AstNodeSrc, AstSrc, Cardinality, Field, KindsSrc, KINDS_SRC}, |
@@ -19,9 +19,7 @@ use crate::{ | |||
19 | }; | 19 | }; |
20 | 20 | ||
21 | pub fn generate_syntax(mode: Mode) -> Result<()> { | 21 | pub fn generate_syntax(mode: Mode) -> Result<()> { |
22 | let grammar = include_str!("rust.ungram") | 22 | let grammar = rust_grammar(); |
23 | .parse::<Grammar>() | ||
24 | .unwrap_or_else(|err| panic!("\n \x1b[91merror\x1b[0m: {}\n", err)); | ||
25 | let ast = lower(&grammar); | 23 | let ast = lower(&grammar); |
26 | 24 | ||
27 | let syntax_kinds_file = project_root().join(codegen::SYNTAX_KINDS); | 25 | let syntax_kinds_file = project_root().join(codegen::SYNTAX_KINDS); |
@@ -153,25 +151,10 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> Result<String> { | |||
153 | quote!(impl ast::#trait_name for #name {}) | 151 | quote!(impl ast::#trait_name for #name {}) |
154 | }); | 152 | }); |
155 | 153 | ||
156 | ( | 154 | let ast_node = if en.name == "Stmt" { |
155 | quote! {} | ||
156 | } else { | ||
157 | quote! { | 157 | quote! { |
158 | #[pretty_doc_comment_placeholder_workaround] | ||
159 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
160 | pub enum #name { | ||
161 | #(#variants(#variants),)* | ||
162 | } | ||
163 | |||
164 | #(#traits)* | ||
165 | }, | ||
166 | quote! { | ||
167 | #( | ||
168 | impl From<#variants> for #name { | ||
169 | fn from(node: #variants) -> #name { | ||
170 | #name::#variants(node) | ||
171 | } | ||
172 | } | ||
173 | )* | ||
174 | |||
175 | impl AstNode for #name { | 158 | impl AstNode for #name { |
176 | fn can_cast(kind: SyntaxKind) -> bool { | 159 | fn can_cast(kind: SyntaxKind) -> bool { |
177 | match kind { | 160 | match kind { |
@@ -196,6 +179,28 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> Result<String> { | |||
196 | } | 179 | } |
197 | } | 180 | } |
198 | } | 181 | } |
182 | } | ||
183 | }; | ||
184 | |||
185 | ( | ||
186 | quote! { | ||
187 | #[pretty_doc_comment_placeholder_workaround] | ||
188 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
189 | pub enum #name { | ||
190 | #(#variants(#variants),)* | ||
191 | } | ||
192 | |||
193 | #(#traits)* | ||
194 | }, | ||
195 | quote! { | ||
196 | #( | ||
197 | impl From<#variants> for #name { | ||
198 | fn from(node: #variants) -> #name { | ||
199 | #name::#variants(node) | ||
200 | } | ||
201 | } | ||
202 | )* | ||
203 | #ast_node | ||
199 | }, | 204 | }, |
200 | ) | 205 | ) |
201 | }) | 206 | }) |
@@ -476,7 +481,13 @@ impl Field { | |||
476 | }; | 481 | }; |
477 | format_ident!("{}_token", name) | 482 | format_ident!("{}_token", name) |
478 | } | 483 | } |
479 | Field::Node { name, .. } => format_ident!("{}", name), | 484 | Field::Node { name, .. } => { |
485 | if name == "type" { | ||
486 | format_ident!("ty") | ||
487 | } else { | ||
488 | format_ident!("{}", name) | ||
489 | } | ||
490 | } | ||
480 | } | 491 | } |
481 | } | 492 | } |
482 | fn ty(&self) -> proc_macro2::Ident { | 493 | fn ty(&self) -> proc_macro2::Ident { |
@@ -491,13 +502,7 @@ fn lower(grammar: &Grammar) -> AstSrc { | |||
491 | let mut res = AstSrc::default(); | 502 | let mut res = AstSrc::default(); |
492 | res.tokens = vec!["Whitespace".into(), "Comment".into(), "String".into(), "RawString".into()]; | 503 | res.tokens = vec!["Whitespace".into(), "Comment".into(), "String".into(), "RawString".into()]; |
493 | 504 | ||
494 | let nodes = grammar | 505 | let nodes = grammar.iter().collect::<Vec<_>>(); |
495 | .iter() | ||
496 | .filter(|&node| match grammar[node].rule { | ||
497 | Rule::Node(it) if it == node => false, | ||
498 | _ => true, | ||
499 | }) | ||
500 | .collect::<Vec<_>>(); | ||
501 | 506 | ||
502 | for &node in &nodes { | 507 | for &node in &nodes { |
503 | let name = grammar[node].name.clone(); | 508 | let name = grammar[node].name.clone(); |
@@ -531,6 +536,7 @@ fn lower_enum(grammar: &Grammar, rule: &Rule) -> Option<Vec<String>> { | |||
531 | for alternative in alternatives { | 536 | for alternative in alternatives { |
532 | match alternative { | 537 | match alternative { |
533 | Rule::Node(it) => variants.push(grammar[*it].name.clone()), | 538 | Rule::Node(it) => variants.push(grammar[*it].name.clone()), |
539 | Rule::Token(it) if grammar[*it].name == ";" => (), | ||
534 | _ => return None, | 540 | _ => return None, |
535 | } | 541 | } |
536 | } | 542 | } |
@@ -572,6 +578,24 @@ fn lower_rule(acc: &mut Vec<Field>, grammar: &Grammar, label: Option<&String>, r | |||
572 | } | 578 | } |
573 | Rule::Labeled { label: l, rule } => { | 579 | Rule::Labeled { label: l, rule } => { |
574 | assert!(label.is_none()); | 580 | assert!(label.is_none()); |
581 | let manually_implemented = matches!( | ||
582 | l.as_str(), | ||
583 | "lhs" | ||
584 | | "rhs" | ||
585 | | "then_branch" | ||
586 | | "else_branch" | ||
587 | | "start" | ||
588 | | "end" | ||
589 | | "op" | ||
590 | | "index" | ||
591 | | "base" | ||
592 | | "value" | ||
593 | | "trait" | ||
594 | | "self_ty" | ||
595 | ); | ||
596 | if manually_implemented { | ||
597 | return; | ||
598 | } | ||
575 | lower_rule(acc, grammar, Some(l), rule); | 599 | lower_rule(acc, grammar, Some(l), rule); |
576 | } | 600 | } |
577 | Rule::Seq(rules) | Rule::Alt(rules) => { | 601 | Rule::Seq(rules) | Rule::Alt(rules) => { |
@@ -687,6 +711,9 @@ fn extract_struct_trait(node: &mut AstNodeSrc, trait_name: &str, methods: &[&str | |||
687 | 711 | ||
688 | fn extract_enum_traits(ast: &mut AstSrc) { | 712 | fn extract_enum_traits(ast: &mut AstSrc) { |
689 | for enm in &mut ast.enums { | 713 | for enm in &mut ast.enums { |
714 | if enm.name == "Stmt" { | ||
715 | continue; | ||
716 | } | ||
690 | let nodes = &ast.nodes; | 717 | let nodes = &ast.nodes; |
691 | let mut variant_traits = enm | 718 | let mut variant_traits = enm |
692 | .variants | 719 | .variants |