Add (not working) support for Range and FileId in struct nodes.
This commit is contained in:
parent
eaebf8c926
commit
583136711a
@ -36,6 +36,7 @@ pub fn make_struct_ast_node_impl(spec: &StructSpec) -> TokenStream {
|
||||
}
|
||||
}
|
||||
MemberChildBuild::Boolean(_) => None,
|
||||
MemberChildBuild::Special(_) => None,
|
||||
},
|
||||
})
|
||||
.filter(Option::is_some)
|
||||
|
||||
@ -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<TokenStream> {
|
||||
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<TokenStream> {
|
||||
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(_) => {
|
||||
make_boolean_member_child_match_action(member_child.name())
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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<TokenStream> {
|
||||
fn make_child_arg(child_spec: &StructChild, pair_ident: &Ident) -> Option<TokenStream> {
|
||||
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<TokenStream> {
|
||||
)),
|
||||
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::<Vec<_>>();
|
||||
@ -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<Rule>) -> #return_type_ident {
|
||||
|
||||
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -48,7 +48,7 @@ impl SkipChild {
|
||||
pub struct VecChild {
|
||||
name: String,
|
||||
rule: String,
|
||||
build: Box<VecChildBuild>
|
||||
build: Box<VecChildBuild>,
|
||||
}
|
||||
|
||||
impl VecChild {
|
||||
@ -56,7 +56,7 @@ impl VecChild {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
rule: rule.to_string(),
|
||||
build
|
||||
build,
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,16 +77,18 @@ 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 {
|
||||
@ -96,14 +98,14 @@ 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(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,6 +160,7 @@ impl MemberChild {
|
||||
pub enum MemberChildBuild {
|
||||
Node(NodeMemberBuild),
|
||||
Boolean(BooleanMemberBuild),
|
||||
Special(SpecialMemberBuild),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -208,5 +211,11 @@ impl BooleanMemberBuild {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BooleanMemberBuildOn {
|
||||
RulePresent
|
||||
RulePresent,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SpecialMemberBuild {
|
||||
FileId,
|
||||
Range,
|
||||
}
|
||||
@ -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<usize> {
|
||||
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<usize> },
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user