Update ast gen yaml to better special child build; fix as_span moving issue.
This commit is contained in:
parent
e578250ee6
commit
1f5d17ef79
@ -36,8 +36,8 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
MemberChildBuild::Boolean(_) => None,
|
MemberChildBuild::Boolean(_) => None,
|
||||||
MemberChildBuild::Special(_) => None,
|
|
||||||
},
|
},
|
||||||
|
StructChild::Special(_) => None,
|
||||||
})
|
})
|
||||||
.filter(Option::is_some)
|
.filter(Option::is_some)
|
||||||
.map(Option::unwrap)
|
.map(Option::unwrap)
|
||||||
|
|||||||
@ -1,8 +1,44 @@
|
|||||||
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
use crate::deserialize::util::{make_build_fn_name, make_build_pair};
|
||||||
use crate::spec::struct_spec::{MemberChildBuild, NodeMemberBuild, SpecialMemberBuild, StructChild, StructSpec, VecChild, VecChildBuild};
|
use crate::spec::struct_spec::{MemberChildBuild, NodeMemberBuild, SpecialChild, SpecialChildKind, StructChild, StructSpec, VecChild, VecChildBuild};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
|
|
||||||
|
fn make_preamble(spec: &StructSpec, pair_ident: &Ident) -> TokenStream {
|
||||||
|
if spec.children().any(StructChild::is_special) {
|
||||||
|
quote! {
|
||||||
|
let as_span = #pair_ident.as_span();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
quote! {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_special_children(spec: &StructSpec) -> Vec<TokenStream> {
|
||||||
|
spec.children()
|
||||||
|
.map(StructChild::unwrap_special)
|
||||||
|
.filter(Option::is_some)
|
||||||
|
.map(Option::unwrap)
|
||||||
|
.map(|special_child| {
|
||||||
|
let child_ident = format_ident!("{}", special_child.name());
|
||||||
|
match special_child.kind() {
|
||||||
|
SpecialChildKind::FileId => {
|
||||||
|
quote! {
|
||||||
|
let #child_ident = file_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SpecialChildKind::Range => {
|
||||||
|
quote! {
|
||||||
|
let #child_ident = Range {
|
||||||
|
start: as_span.start(),
|
||||||
|
end: as_span.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
}
|
||||||
|
|
||||||
fn make_vec_child_holder(vec_child: &VecChild) -> TokenStream {
|
fn make_vec_child_holder(vec_child: &VecChild) -> TokenStream {
|
||||||
let child_ident = format_ident!("{}", vec_child.name());
|
let child_ident = format_ident!("{}", vec_child.name());
|
||||||
match vec_child.build() {
|
match vec_child.build() {
|
||||||
@ -44,8 +80,8 @@ fn make_child_holder(child_spec: &StructChild) -> Option<TokenStream> {
|
|||||||
Some(make_node_child_holder(member_child.name(), node_child))
|
Some(make_node_child_holder(member_child.name(), node_child))
|
||||||
}
|
}
|
||||||
MemberChildBuild::Boolean(_) => Some(make_boolean_child_holder(member_child.name())),
|
MemberChildBuild::Boolean(_) => Some(make_boolean_child_holder(member_child.name())),
|
||||||
MemberChildBuild::Special(_) => None,
|
|
||||||
},
|
},
|
||||||
|
StructChild::Special(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -111,9 +147,9 @@ fn make_rule_matcher(child_spec: &StructChild) -> Option<TokenStream> {
|
|||||||
Rule::#rule_ident => { #action }
|
Rule::#rule_ident => { #action }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
MemberChildBuild::Special(_) => None
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
StructChild::Special(_) => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,6 +182,11 @@ fn make_boolean_member_child_arg(name: &str) -> TokenStream {
|
|||||||
quote! { #child_ident }
|
quote! { #child_ident }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_special_child_arg(special_child: &SpecialChild) -> TokenStream {
|
||||||
|
let child_ident = format_ident!("{}", special_child.name());
|
||||||
|
quote! { #child_ident }
|
||||||
|
}
|
||||||
|
|
||||||
fn make_child_arg(child_spec: &StructChild, pair_ident: &Ident) -> Option<TokenStream> {
|
fn make_child_arg(child_spec: &StructChild, pair_ident: &Ident) -> Option<TokenStream> {
|
||||||
match child_spec {
|
match child_spec {
|
||||||
StructChild::SkipChild(_) => None,
|
StructChild::SkipChild(_) => None,
|
||||||
@ -159,22 +200,8 @@ fn make_child_arg(child_spec: &StructChild, pair_ident: &Ident) -> Option<TokenS
|
|||||||
MemberChildBuild::Boolean(_) => {
|
MemberChildBuild::Boolean(_) => {
|
||||||
Some(make_boolean_member_child_arg(member_child.name()))
|
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(),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
StructChild::Special(special_child) => Some(make_special_child_arg(special_child)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,6 +225,10 @@ pub fn make_struct_build_fn(build_spec: &StructSpec) -> TokenStream {
|
|||||||
let build_fn_ident = format_ident!("{}", make_build_fn_name(build_spec.build()));
|
let build_fn_ident = format_ident!("{}", make_build_fn_name(build_spec.build()));
|
||||||
let pair_ident = format_ident!("{}", make_build_pair(build_spec.build()));
|
let pair_ident = format_ident!("{}", make_build_pair(build_spec.build()));
|
||||||
let return_type_ident = format_ident!("{}", build_spec.build());
|
let return_type_ident = format_ident!("{}", build_spec.build());
|
||||||
|
|
||||||
|
let preamble = make_preamble(build_spec, &pair_ident);
|
||||||
|
|
||||||
|
let special_children = make_special_children(build_spec);
|
||||||
|
|
||||||
let child_holders = build_spec
|
let child_holders = build_spec
|
||||||
.children()
|
.children()
|
||||||
@ -224,6 +255,10 @@ pub fn make_struct_build_fn(build_spec: &StructSpec) -> TokenStream {
|
|||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
fn #build_fn_ident(file_id: usize, #pair_ident: Pair<Rule>) -> #return_type_ident {
|
fn #build_fn_ident(file_id: usize, #pair_ident: Pair<Rule>) -> #return_type_ident {
|
||||||
|
#preamble
|
||||||
|
|
||||||
|
#(#special_children;)*
|
||||||
|
|
||||||
#(#child_holders;)*
|
#(#child_holders;)*
|
||||||
|
|
||||||
#iter_stream
|
#iter_stream
|
||||||
|
|||||||
@ -56,12 +56,6 @@ fn deserialize_member_build(child_name: &str, rule: &str, props: &Yaml) -> Membe
|
|||||||
} else {
|
} else {
|
||||||
panic!("Expected 'on' in 'boolean' in 'build' in {}", child_name);
|
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 {
|
} else {
|
||||||
panic!(
|
panic!(
|
||||||
"Expected one of 'node', 'boolean', or 'special' in 'build' in {}",
|
"Expected one of 'node', 'boolean', or 'special' in 'build' in {}",
|
||||||
@ -98,6 +92,14 @@ fn deserialize_member_child(child_name: &str, props: &Yaml) -> StructChild {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_special_child(name: &str, props: &Yaml) -> StructChild {
|
||||||
|
match props["kind"].as_str().unwrap() {
|
||||||
|
"file_id" => StructChild::Special(SpecialChild::new(name, SpecialChildKind::FileId)),
|
||||||
|
"range" => StructChild::Special(SpecialChild::new(name, SpecialChildKind::Range)),
|
||||||
|
_ => panic!("Invalid special child kind {} in {}", props["kind"].as_str().unwrap(), name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn deserialize_hash_child(name: &str, props: &Yaml) -> StructChild {
|
fn deserialize_hash_child(name: &str, props: &Yaml) -> StructChild {
|
||||||
if props["skip"].is_hash() {
|
if props["skip"].is_hash() {
|
||||||
deserialize_skip_child(&props["skip"])
|
deserialize_skip_child(&props["skip"])
|
||||||
@ -105,6 +107,8 @@ fn deserialize_hash_child(name: &str, props: &Yaml) -> StructChild {
|
|||||||
deserialize_vec_child(name, &props["vec"])
|
deserialize_vec_child(name, &props["vec"])
|
||||||
} else if props["member"].is_hash() {
|
} else if props["member"].is_hash() {
|
||||||
deserialize_member_child(name, &props["member"])
|
deserialize_member_child(name, &props["member"])
|
||||||
|
} else if props["special"].is_hash() {
|
||||||
|
deserialize_special_child(name, &props["special"])
|
||||||
} else {
|
} else {
|
||||||
panic!("Expected 'skip' or 'vec' in 'member' in {}", name);
|
panic!("Expected 'skip' or 'vec' in 'member' in {}", name);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -231,8 +231,8 @@ fn make_struct_p2_impl(struct_build_spec: &StructSpec) -> TokenStream {
|
|||||||
writer.writeln_indented(&format!(#format_string, self.#child_ident()))?;
|
writer.writeln_indented(&format!(#format_string, self.#child_ident()))?;
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
MemberChildBuild::Special(_) => None
|
|
||||||
},
|
},
|
||||||
|
StructChild::Special(_) => None
|
||||||
})
|
})
|
||||||
.filter(Option::is_some)
|
.filter(Option::is_some)
|
||||||
.map(Option::unwrap)
|
.map(Option::unwrap)
|
||||||
|
|||||||
@ -26,6 +26,25 @@ pub enum StructChild {
|
|||||||
SkipChild(SkipChild),
|
SkipChild(SkipChild),
|
||||||
VecChild(VecChild),
|
VecChild(VecChild),
|
||||||
MemberChild(MemberChild),
|
MemberChild(MemberChild),
|
||||||
|
Special(SpecialChild),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StructChild {
|
||||||
|
pub fn is_special(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
StructChild::Special(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unwrap_special(&self) -> Option<&SpecialChild> {
|
||||||
|
match self {
|
||||||
|
StructChild::Special(special_child) => {
|
||||||
|
Some(special_child)
|
||||||
|
},
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SkipChild {
|
pub struct SkipChild {
|
||||||
@ -160,7 +179,6 @@ impl MemberChild {
|
|||||||
pub enum MemberChildBuild {
|
pub enum MemberChildBuild {
|
||||||
Node(NodeMemberBuild),
|
Node(NodeMemberBuild),
|
||||||
Boolean(BooleanMemberBuild),
|
Boolean(BooleanMemberBuild),
|
||||||
Special(SpecialMemberBuild),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -215,7 +233,30 @@ pub enum BooleanMemberBuildOn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum SpecialMemberBuild {
|
pub struct SpecialChild {
|
||||||
|
name: String,
|
||||||
|
kind: SpecialChildKind,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SpecialChild {
|
||||||
|
pub fn new(name: &str, kind: SpecialChildKind) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name.to_string(),
|
||||||
|
kind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kind(&self) -> &SpecialChildKind {
|
||||||
|
&self.kind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum SpecialChildKind {
|
||||||
FileId,
|
FileId,
|
||||||
Range,
|
Range,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::spec::struct_spec::{
|
use crate::spec::struct_spec::{
|
||||||
MemberChild, MemberChildBuild, SpecialMemberBuild, StructChild, StructSpec, VecChild,
|
MemberChild, MemberChildBuild, SpecialChild, SpecialChildKind, StructChild, StructSpec,
|
||||||
VecChildBuild,
|
VecChild, VecChildBuild,
|
||||||
};
|
};
|
||||||
use proc_macro2::{Ident, TokenStream};
|
use proc_macro2::{Ident, TokenStream};
|
||||||
use quote::{format_ident, quote};
|
use quote::{format_ident, quote};
|
||||||
@ -76,22 +76,26 @@ 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 {
|
fn make_special_child_accessors(special_child: &SpecialChild) -> TokenStream {
|
||||||
self.file_id
|
let child_ident = format_ident!("{}", special_child.name());
|
||||||
}
|
match special_child.kind() {
|
||||||
|
SpecialChildKind::FileId => {
|
||||||
|
quote! {
|
||||||
|
pub fn #child_ident(&self) -> usize {
|
||||||
|
self.#child_ident
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SpecialMemberBuild::Range => {
|
}
|
||||||
quote! {
|
SpecialChildKind::Range => {
|
||||||
pub fn range(&self) -> Range<usize> {
|
quote! {
|
||||||
self.range
|
pub fn #child_ident(&self) -> Range<usize> {
|
||||||
}
|
self.#child_ident
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,6 +104,7 @@ fn make_accessors(child: &StructChild) -> Option<TokenStream> {
|
|||||||
StructChild::SkipChild(_) => None,
|
StructChild::SkipChild(_) => None,
|
||||||
StructChild::VecChild(vec_child) => Some(make_vec_child_accessors(vec_child)),
|
StructChild::VecChild(vec_child) => Some(make_vec_child_accessors(vec_child)),
|
||||||
StructChild::MemberChild(member_child) => Some(make_member_child_accessors(member_child)),
|
StructChild::MemberChild(member_child) => Some(make_member_child_accessors(member_child)),
|
||||||
|
StructChild::Special(special_child) => Some(make_special_child_accessors(special_child)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,6 +113,7 @@ fn make_member_ident(child: &StructChild) -> Option<Ident> {
|
|||||||
StructChild::SkipChild(_) => None,
|
StructChild::SkipChild(_) => None,
|
||||||
StructChild::VecChild(vec_child) => Some(format_ident!("{}", vec_child.name())),
|
StructChild::VecChild(vec_child) => Some(format_ident!("{}", vec_child.name())),
|
||||||
StructChild::MemberChild(member_child) => Some(format_ident!("{}", member_child.name())),
|
StructChild::MemberChild(member_child) => Some(format_ident!("{}", member_child.name())),
|
||||||
|
StructChild::Special(special_child) => Some(format_ident!("{}", special_child.name())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,10 +141,6 @@ fn make_member_child_type_ident(member_child: &MemberChild) -> TokenStream {
|
|||||||
MemberChildBuild::Boolean(_) => {
|
MemberChildBuild::Boolean(_) => {
|
||||||
quote! { bool }
|
quote! { bool }
|
||||||
}
|
}
|
||||||
MemberChildBuild::Special(special_member_build) => match special_member_build {
|
|
||||||
SpecialMemberBuild::FileId => quote! { usize },
|
|
||||||
SpecialMemberBuild::Range => quote! { Range<usize> },
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,6 +158,17 @@ fn make_member_child_annotated_member(member_child: &MemberChild) -> TokenStream
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_special_child_annotated_member(special_child: &SpecialChild) -> TokenStream {
|
||||||
|
let child_ident = format_ident!("{}", special_child.name());
|
||||||
|
let child_type_ident = match special_child.kind() {
|
||||||
|
SpecialChildKind::FileId => quote! { usize },
|
||||||
|
SpecialChildKind::Range => quote! { Range<usize> },
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
#child_ident: #child_type_ident
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn make_annotated_member(child: &StructChild) -> Option<TokenStream> {
|
fn make_annotated_member(child: &StructChild) -> Option<TokenStream> {
|
||||||
match child {
|
match child {
|
||||||
StructChild::SkipChild(_) => None,
|
StructChild::SkipChild(_) => None,
|
||||||
@ -163,6 +176,9 @@ fn make_annotated_member(child: &StructChild) -> Option<TokenStream> {
|
|||||||
StructChild::MemberChild(member_child) => {
|
StructChild::MemberChild(member_child) => {
|
||||||
Some(make_member_child_annotated_member(member_child))
|
Some(make_member_child_annotated_member(member_child))
|
||||||
}
|
}
|
||||||
|
StructChild::Special(special_child) => {
|
||||||
|
Some(make_special_child_annotated_member(special_child))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -88,6 +88,7 @@ $defs:
|
|||||||
- $ref: "#/$defs/StructChildSkipHash"
|
- $ref: "#/$defs/StructChildSkipHash"
|
||||||
- $ref: "#/$defs/StructChildVecHash"
|
- $ref: "#/$defs/StructChildVecHash"
|
||||||
- $ref: "#/$defs/StructChildMemberHash"
|
- $ref: "#/$defs/StructChildMemberHash"
|
||||||
|
- $ref: "#/$defs/StructChildSpecialHash"
|
||||||
StructChildSkipHash:
|
StructChildSkipHash:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
@ -148,7 +149,6 @@ $defs:
|
|||||||
oneOf:
|
oneOf:
|
||||||
- $ref: "#/$defs/StructChildMemberBuildNodeHash"
|
- $ref: "#/$defs/StructChildMemberBuildNodeHash"
|
||||||
- $ref: "#/$defs/StructChildMemberBuildBooleanHash"
|
- $ref: "#/$defs/StructChildMemberBuildBooleanHash"
|
||||||
- $ref: "#/$defs/StructChildMemberBuildSpecialHash"
|
|
||||||
StructChildMemberBuildNodeHash:
|
StructChildMemberBuildNodeHash:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
@ -191,7 +191,7 @@ $defs:
|
|||||||
- rule_present
|
- rule_present
|
||||||
required:
|
required:
|
||||||
- on
|
- on
|
||||||
StructChildMemberBuildSpecialHash:
|
StructChildSpecialHash:
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
description: A special member to be built.
|
description: A special member to be built.
|
||||||
|
|||||||
@ -215,15 +215,11 @@ UseStatement:
|
|||||||
member:
|
member:
|
||||||
rule: UseStatementSuffix
|
rule: UseStatementSuffix
|
||||||
- file_id:
|
- file_id:
|
||||||
member:
|
special:
|
||||||
build:
|
kind: file_id
|
||||||
special:
|
|
||||||
kind: file_id
|
|
||||||
- range:
|
- range:
|
||||||
member:
|
special:
|
||||||
build:
|
kind: range
|
||||||
special:
|
|
||||||
kind: range
|
|
||||||
UseStatementPrefix:
|
UseStatementPrefix:
|
||||||
struct:
|
struct:
|
||||||
children:
|
children:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user