sv_parser_macros/
lib.rs

1#![recursion_limit = "128"]
2
3extern crate proc_macro;
4
5use crate::proc_macro::TokenStream;
6use quote::quote;
7use syn::Data::{Enum, Struct};
8use syn::{self, DeriveInput};
9
10#[proc_macro_derive(Node)]
11pub fn node_derive(input: TokenStream) -> TokenStream {
12    let ast = syn::parse(input).unwrap();
13    impl_node(&ast)
14}
15
16fn impl_node(ast: &DeriveInput) -> TokenStream {
17    let name = &ast.ident;
18
19    let next = match ast.data {
20        Enum(ref data) => {
21            let mut items = quote! {};
22            for v in &data.variants {
23                let ident = &v.ident;
24                let item = quote! {
25                    #name::#ident(x) => { x.into() },
26                };
27                items = quote! {
28                    #items
29                    #item
30                };
31            }
32
33            quote! {
34                match self {
35                    #items
36                }
37            }
38        }
39        Struct(_) => {
40            quote! {
41                (&(self.nodes)).into()
42            }
43        }
44        _ => {
45            quote! {
46                vec![].into()
47            }
48        }
49    };
50
51    let gen = quote! {
52        impl<'a> Node<'a> for #name {
53            fn next(&'a self) -> RefNodes<'a> {
54                #next
55            }
56        }
57
58        impl<'a> From<&'a #name> for RefNodes<'a> {
59            fn from(x: &'a #name) -> Self {
60                vec![RefNode::#name(x)].into()
61            }
62        }
63
64        impl From<#name> for AnyNode {
65            fn from(x: #name) -> Self {
66                AnyNode::#name(x)
67            }
68        }
69
70        impl<'a> From<&'a #name> for RefNode<'a> {
71            fn from(x: &'a #name) -> Self {
72                RefNode::#name(x)
73            }
74        }
75
76        impl core::convert::TryFrom<#name> for Locate {
77            type Error = ();
78            fn try_from(x: #name) -> Result<Self, Self::Error> {
79                Self::try_from(&x)
80            }
81        }
82
83        impl<'a> core::convert::TryFrom<&'a #name> for Locate {
84            type Error = ();
85            fn try_from(x: &'a #name) -> Result<Self, Self::Error> {
86                let mut locate: Option<Locate> = None;
87                for x in x {
88                    match x {
89                        RefNode::Locate(x) => if let Some(loc) = locate {
90                            assert_eq!(x.offset, loc.offset + loc.len);
91                            locate = Some(Locate { offset: loc.offset, line: loc.line, len: loc.len + x.len });
92                        } else {
93                            locate = Some(*x);
94                        },
95                        _ => (),
96                    }
97                }
98                locate.ok_or(())
99            }
100        }
101
102        impl<'a> IntoIterator for &'a #name {
103            type Item = RefNode<'a>;
104            type IntoIter = Iter<'a>;
105
106            fn into_iter(self) -> Self::IntoIter {
107                let mut nodes: RefNodes = self.into();
108                nodes.0.reverse();
109                Iter { next: nodes }
110            }
111        }
112    };
113    gen.into()
114}
115
116#[proc_macro_derive(AnyNode)]
117pub fn any_node_derive(input: TokenStream) -> TokenStream {
118    let ast = syn::parse(input).unwrap();
119    impl_any_node(&ast)
120}
121
122fn impl_any_node(ast: &DeriveInput) -> TokenStream {
123    let data = &match ast.data {
124        Enum(ref data) => data,
125        _ => unreachable!(),
126    };
127
128    let mut try_froms = quote! {};
129    let mut from_items = quote! {};
130    for v in &data.variants {
131        let ident = &v.ident;
132
133        try_froms = quote! {
134            #try_froms
135            impl TryFrom<AnyNode> for #ident  {
136                type Error = ();
137                fn try_from(x: AnyNode) -> Result<Self, Self::Error> {
138                    match x {
139                        AnyNode::#ident(x) => Ok(x),
140                        _ => Err(()),
141                    }
142                }
143            }
144        };
145
146        from_items = quote! {
147            #from_items
148            AnyNode::#ident(x) => RefNode::#ident(&x),
149        };
150    }
151
152    let gen = quote! {
153        #try_froms
154
155        impl<'a> From<&'a AnyNode> for RefNode<'a>  {
156            fn from(x: &'a AnyNode) -> Self {
157                match x {
158                    #from_items
159                }
160            }
161        }
162    };
163    gen.into()
164}
165
166#[proc_macro_derive(RefNode)]
167pub fn ref_node_derive(input: TokenStream) -> TokenStream {
168    let ast = syn::parse(input).unwrap();
169    impl_ref_node(&ast)
170}
171
172fn impl_ref_node(ast: &DeriveInput) -> TokenStream {
173    let data = &match ast.data {
174        Enum(ref data) => data,
175        _ => unreachable!(),
176    };
177
178    let mut next_items = quote! {};
179    let mut into_iter_items = quote! {};
180    for v in &data.variants {
181        let ident = &v.ident;
182        next_items = quote! {
183            #next_items
184            RefNode::#ident(x) => x.next(),
185        };
186        into_iter_items = quote! {
187            #into_iter_items
188            RefNode::#ident(x) => x.into_iter(),
189        };
190    }
191
192    let name = &ast.ident;
193    let gen = quote! {
194        impl<'a> #name<'a> {
195            fn next(&self) -> RefNodes<'a> {
196                match self {
197                    #next_items
198                }
199            }
200        }
201
202        impl<'a> IntoIterator for #name<'a> {
203            type Item = RefNode<'a>;
204            type IntoIter = Iter<'a>;
205
206            fn into_iter(self) -> Self::IntoIter {
207                match self {
208                    #into_iter_items
209                }
210            }
211        }
212    };
213    gen.into()
214}