From 583136711adc3d32ec3ad9b8742842e3dd495752 Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Wed, 1 Oct 2025 13:45:49 -0500 Subject: [PATCH] Add (not working) support for Range and FileId in struct nodes. --- ast-generator/src/ast_node/struct_ast_node.rs | 1 + ast-generator/src/build_fn/struct_build_fn.rs | 85 ++++++++++++------- ast-generator/src/deserialize/struct_spec.rs | 26 +++--- ast-generator/src/pretty_print.rs | 1 + ast-generator/src/spec/struct_spec.rs | 37 +++++--- ast-generator/src/type_gen/struct_type.rs | 23 ++++- src/parser/ast.schema.yaml | 19 +++++ src/parser/ast.yaml | 10 +++ 8 files changed, 139 insertions(+), 63 deletions(-) diff --git a/ast-generator/src/ast_node/struct_ast_node.rs b/ast-generator/src/ast_node/struct_ast_node.rs index 37409fb..7ff4ff4 100644 --- a/ast-generator/src/ast_node/struct_ast_node.rs +++ b/ast-generator/src/ast_node/struct_ast_node.rs @@ -36,6 +36,7 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream { } } MemberChildBuild::Boolean(_) => None, + MemberChildBuild::Special(_) => None, }, }) .filter(Option::is_some) diff --git a/ast-generator/src/build_fn/struct_build_fn.rs b/ast-generator/src/build_fn/struct_build_fn.rs index 2f35b6a..2ce5585 100644 --- a/ast-generator/src/build_fn/struct_build_fn.rs +++ b/ast-generator/src/build_fn/struct_build_fn.rs @@ -1,8 +1,6 @@ use crate::deserialize::util::{make_build_fn_name, make_build_pair}; -use crate::spec::struct_spec::{ - MemberChildBuild, NodeMemberBuild, StructChild, StructSpec, VecChild, VecChildBuild, -}; -use proc_macro2::TokenStream; +use crate::spec::struct_spec::{MemberChildBuild, NodeMemberBuild, SpecialMemberBuild, StructChild, StructSpec, VecChild, VecChildBuild}; +use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; fn make_vec_child_holder(vec_child: &VecChild) -> TokenStream { @@ -46,6 +44,7 @@ fn make_child_holder(child_spec: &StructChild) -> Option { Some(make_node_child_holder(member_child.name(), node_child)) } MemberChildBuild::Boolean(_) => Some(make_boolean_child_holder(member_child.name())), + MemberChildBuild::Special(_) => None, }, } } @@ -83,32 +82,37 @@ fn make_boolean_member_child_match_action(name: &str) -> TokenStream { } } -fn make_match_action(child_spec: &StructChild) -> TokenStream { +fn make_rule_matcher(child_spec: &StructChild) -> Option { match child_spec { - StructChild::SkipChild(_) => quote! {}, - StructChild::VecChild(vec_child) => make_vec_child_match_action(vec_child), - StructChild::MemberChild(member_child) => match member_child.build() { - MemberChildBuild::Node(node_child) => { - make_node_member_child_match_action(member_child.name(), node_child) + StructChild::SkipChild(_) => None, + StructChild::VecChild(vec_child) => { + let rule_ident = format_ident!("{}", vec_child.rule()); + let action = make_vec_child_match_action(vec_child); + Some(quote! { + Rule::#rule_ident => { #action } + }) + } + StructChild::MemberChild(member_child) => { + match member_child.build() { + MemberChildBuild::Node(node_member_build) => { + let rule_ident = format_ident!("{}", member_child.rule()); + let action = make_node_member_child_match_action( + member_child.name(), + node_member_build + ); + Some(quote! { + Rule::#rule_ident => { #action } + }) + } + MemberChildBuild::Boolean(_) => { + let rule_ident = format_ident!("{}", member_child.rule()); + let action = make_boolean_member_child_match_action(member_child.name()); + Some(quote! { + Rule::#rule_ident => { #action } + }) + } + MemberChildBuild::Special(_) => None } - MemberChildBuild::Boolean(_) => { - make_boolean_member_child_match_action(member_child.name()) - } - }, - } -} - -fn make_rule_matcher(child_spec: &StructChild) -> TokenStream { - let rule_ident = match child_spec { - StructChild::SkipChild(skip_child) => format_ident!("{}", skip_child.rule()), - StructChild::VecChild(vec_child) => format_ident!("{}", vec_child.rule()), - StructChild::MemberChild(single_child) => format_ident!("{}", single_child.rule()), - }; - let action = make_match_action(child_spec); - - quote! { - Rule::#rule_ident => { - #action; } } } @@ -142,7 +146,7 @@ fn make_boolean_member_child_arg(name: &str) -> TokenStream { quote! { #child_ident } } -fn make_child_arg(child_spec: &StructChild) -> Option { +fn make_child_arg(child_spec: &StructChild, pair_ident: &Ident) -> Option { match child_spec { StructChild::SkipChild(_) => None, StructChild::VecChild(vec_child) => Some(make_vec_child_arg(vec_child)), @@ -154,16 +158,31 @@ fn make_child_arg(child_spec: &StructChild) -> Option { )), MemberChildBuild::Boolean(_) => { Some(make_boolean_member_child_arg(member_child.name())) - } + }, + MemberChildBuild::Special(special_member_build) => { + match special_member_build { + SpecialMemberBuild::FileId => { + Some(quote! { file_id }) + } + SpecialMemberBuild::Range => { + Some(quote! { + Range { + start: #pair_ident.as_span().start(), + end: #pair_ident.as_span().end(), + } + }) + } + } + }, }, } } -fn make_return_value_stream(build_spec: &StructSpec) -> TokenStream { +fn make_return_value_stream(build_spec: &StructSpec, pair_ident: &Ident) -> TokenStream { let type_ident = format_ident!("{}", build_spec.build()); let child_args = build_spec .children() - .map(|child| make_child_arg(child)) + .map(|child| make_child_arg(child, pair_ident)) .filter(|child_arg| child_arg.is_some()) .map(|child_arg| child_arg.unwrap()) .collect::>(); @@ -201,7 +220,7 @@ pub fn make_struct_build_fn(build_spec: &StructSpec) -> TokenStream { } }; - let new_stream = make_return_value_stream(build_spec); + let new_stream = make_return_value_stream(build_spec, &pair_ident); quote! { fn #build_fn_ident(file_id: usize, #pair_ident: Pair) -> #return_type_ident { diff --git a/ast-generator/src/deserialize/struct_spec.rs b/ast-generator/src/deserialize/struct_spec.rs index f8a1961..998492b 100644 --- a/ast-generator/src/deserialize/struct_spec.rs +++ b/ast-generator/src/deserialize/struct_spec.rs @@ -12,22 +12,12 @@ fn deserialize_skip_child(props: &Yaml) -> StructChild { fn deserialize_vec_child(child_name: &str, props: &Yaml) -> StructChild { let rule = props["rule"].as_str().unwrap(); - let kind = props["kind"].as_str() - .unwrap_or(rule); + let kind = props["kind"].as_str().unwrap_or(rule); if kind == "string" { - let build = VecChildBuild::String(VecChildStringBuild::new( - &make_build_fn_name(rule) - )); - StructChild::VecChild(VecChild::new( - child_name, - rule, - Box::new(build), - )) + let build = VecChildBuild::String(VecChildStringBuild::new(&make_build_fn_name(rule))); + StructChild::VecChild(VecChild::new(child_name, rule, Box::new(build))) } else { - let build = VecChildBuild::Node(VecChildNodeBuild::new( - rule, - &make_build_fn_name(rule) - )); + let build = VecChildBuild::Node(VecChildNodeBuild::new(rule, &make_build_fn_name(rule))); StructChild::VecChild(VecChild::new(child_name, rule, Box::new(build))) } } @@ -66,9 +56,15 @@ fn deserialize_member_build(child_name: &str, rule: &str, props: &Yaml) -> Membe } else { panic!("Expected 'on' in 'boolean' in 'build' in {}", child_name); } + } else if props["special"].is_hash() { + match props["special"]["kind"].as_str().unwrap() { + "file_id" => MemberChildBuild::Special(SpecialMemberBuild::FileId), + "range" => MemberChildBuild::Special(SpecialMemberBuild::Range), + _ => panic!(), + } } else { panic!( - "Expected either of 'node' or 'boolean' in 'build' in {}", + "Expected one of 'node', 'boolean', or 'special' in 'build' in {}", child_name ); } diff --git a/ast-generator/src/pretty_print.rs b/ast-generator/src/pretty_print.rs index c2eea13..af08ffe 100644 --- a/ast-generator/src/pretty_print.rs +++ b/ast-generator/src/pretty_print.rs @@ -231,6 +231,7 @@ fn make_struct_p2_impl(struct_build_spec: &StructSpec) -> TokenStream { writer.writeln_indented(&format!(#format_string, self.#child_ident()))?; }) } + MemberChildBuild::Special(_) => None }, }) .filter(Option::is_some) diff --git a/ast-generator/src/spec/struct_spec.rs b/ast-generator/src/spec/struct_spec.rs index 780e23a..0b6db54 100644 --- a/ast-generator/src/spec/struct_spec.rs +++ b/ast-generator/src/spec/struct_spec.rs @@ -48,7 +48,7 @@ impl SkipChild { pub struct VecChild { name: String, rule: String, - build: Box + build: Box, } impl VecChild { @@ -56,7 +56,7 @@ impl VecChild { Self { name: name.to_string(), rule: rule.to_string(), - build + build, } } @@ -69,7 +69,7 @@ impl VecChild { pub fn rule(&self) -> &str { &self.rule } - + pub fn build(&self) -> &VecChildBuild { &self.build } @@ -77,18 +77,20 @@ impl VecChild { pub enum VecChildBuild { String(VecChildStringBuild), - Node(VecChildNodeBuild) + Node(VecChildNodeBuild), } pub struct VecChildStringBuild { - with: String + with: String, } impl VecChildStringBuild { pub fn new(with: &str) -> Self { - Self { with: with.to_string() } + Self { + with: with.to_string(), + } } - + pub fn with(&self) -> &str { &self.with } @@ -96,21 +98,21 @@ impl VecChildStringBuild { pub struct VecChildNodeBuild { kind: String, - with: String + with: String, } impl VecChildNodeBuild { pub fn new(kind: &str, with: &str) -> Self { Self { kind: kind.to_string(), - with: with.to_string() + with: with.to_string(), } } - + pub fn kind(&self) -> &str { &self.kind } - + pub fn with(&self) -> &str { &self.with } @@ -158,6 +160,7 @@ impl MemberChild { pub enum MemberChildBuild { Node(NodeMemberBuild), Boolean(BooleanMemberBuild), + Special(SpecialMemberBuild), } #[derive(Debug)] @@ -200,7 +203,7 @@ impl BooleanMemberBuild { pub fn new(on: BooleanMemberBuildOn) -> Self { Self { on } } - + pub fn on(&self) -> &BooleanMemberBuildOn { &self.on } @@ -208,5 +211,11 @@ impl BooleanMemberBuild { #[derive(Debug)] pub enum BooleanMemberBuildOn { - RulePresent -} \ No newline at end of file + RulePresent, +} + +#[derive(Debug)] +pub enum SpecialMemberBuild { + FileId, + Range, +} diff --git a/ast-generator/src/type_gen/struct_type.rs b/ast-generator/src/type_gen/struct_type.rs index 9194981..55fa714 100644 --- a/ast-generator/src/type_gen/struct_type.rs +++ b/ast-generator/src/type_gen/struct_type.rs @@ -1,5 +1,6 @@ use crate::spec::struct_spec::{ - MemberChild, MemberChildBuild, StructChild, StructSpec, VecChild, VecChildBuild, + MemberChild, MemberChildBuild, SpecialMemberBuild, StructChild, StructSpec, VecChild, + VecChildBuild, }; use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; @@ -75,6 +76,22 @@ fn make_member_child_accessors(member_child: &MemberChild) -> TokenStream { } } } + MemberChildBuild::Special(special_member_build) => match special_member_build { + SpecialMemberBuild::FileId => { + quote! { + pub fn file_id(&self) -> usize { + self.file_id + } + } + } + SpecialMemberBuild::Range => { + quote! { + pub fn range(&self) -> Range { + self.range + } + } + } + }, } } @@ -118,6 +135,10 @@ fn make_member_child_type_ident(member_child: &MemberChild) -> TokenStream { MemberChildBuild::Boolean(_) => { quote! { bool } } + MemberChildBuild::Special(special_member_build) => match special_member_build { + SpecialMemberBuild::FileId => quote! { usize }, + SpecialMemberBuild::Range => quote! { Range }, + }, } } diff --git a/src/parser/ast.schema.yaml b/src/parser/ast.schema.yaml index 028638b..95126ea 100644 --- a/src/parser/ast.schema.yaml +++ b/src/parser/ast.schema.yaml @@ -148,6 +148,7 @@ $defs: oneOf: - $ref: "#/$defs/StructChildMemberBuildNodeHash" - $ref: "#/$defs/StructChildMemberBuildBooleanHash" + - $ref: "#/$defs/StructChildMemberBuildSpecialHash" StructChildMemberBuildNodeHash: type: object additionalProperties: false @@ -190,6 +191,24 @@ $defs: - rule_present required: - on + StructChildMemberBuildSpecialHash: + type: object + additionalProperties: false + description: A special member to be built. + properties: + special: + type: object + additionalProperties: false + properties: + kind: + type: string + enum: + - file_id + - range + required: + - kind + required: + - special # Leaf Struct Node LeafStructNodeDefinition: diff --git a/src/parser/ast.yaml b/src/parser/ast.yaml index 4e33e2a..e472297 100644 --- a/src/parser/ast.yaml +++ b/src/parser/ast.yaml @@ -214,6 +214,16 @@ UseStatement: - suffix: member: rule: UseStatementSuffix + - file_id: + member: + build: + special: + kind: file_id + - range: + member: + build: + special: + kind: range UseStatementPrefix: struct: children: