@@ -3,7 +3,9 @@ use quote::quote;
33use std:: sync:: atomic:: { AtomicUsize , Ordering } ;
44use syn:: Lifetime ;
55
6- use crate :: ast:: { Content , Field , Node , Template } ;
6+ use crate :: ast:: {
7+ Capture , Cardinality , Content , Field , Node , Pattern , Replacement , Rule , Template ,
8+ } ;
79
810struct LoweringContext < ' a > {
911 /// Enclosing optional-field label to exit when a computed value is absent.
@@ -16,6 +18,209 @@ fn fresh_fallible_label() -> Lifetime {
1618 Lifetime :: new ( & format ! ( "'__yeast_field_{n}" ) , Span :: call_site ( ) )
1719}
1820
21+ #[ derive( Clone ) ]
22+ struct BoundCapture {
23+ capture : Capture ,
24+ cardinality : Cardinality ,
25+ }
26+
27+ impl Rule {
28+ pub ( crate ) fn lower ( & self ) -> TokenStream {
29+ let query = self . pattern . lower ( ) ;
30+ let captures = self . pattern . captures ( ) ;
31+ let ( raw_captures, translated_captures) : ( Vec < _ > , Vec < _ > ) =
32+ captures. iter ( ) . partition ( |capture| capture. capture . raw ) ;
33+ let raw_capture_names = raw_captures
34+ . iter ( )
35+ . map ( |capture| capture. capture . name . to_string ( ) )
36+ . collect :: < Vec < _ > > ( ) ;
37+ let raw_bindings = capture_bindings ( raw_captures. into_iter ( ) ) ;
38+ let translated_bindings = capture_bindings ( translated_captures. into_iter ( ) ) ;
39+ let replacement = self . replacement . lower ( ) ;
40+ let guard = self
41+ . guard
42+ . clone ( )
43+ . unwrap_or_else ( || syn:: parse_quote!( true ) ) ;
44+ let ctx = Ident :: new ( "ctx" , Span :: call_site ( ) ) ;
45+
46+ quote ! {
47+ {
48+ let __query = #query;
49+ yeast:: Rule :: guarded(
50+ __query,
51+ Box :: new( |__ast: & yeast:: Ast , __captures: & yeast:: captures:: Captures , __user_ctx: & mut _| {
52+ #( #raw_bindings) *
53+ #( #translated_bindings) *
54+ let ast = __ast;
55+ let #ctx = __user_ctx;
56+ Ok ( #guard)
57+ } ) ,
58+ Box :: new( |__ast: & mut yeast:: Ast , mut __captures: yeast:: captures:: Captures , __source_range: Option <yeast:: Range >, __user_ctx: & mut _, __translator: yeast:: TranslatorHandle <' _, _>| {
59+ let __skip: & [ & str ] = & [ #( #raw_capture_names) , * ] ;
60+ __translator. auto_translate_captures( & mut __captures, __ast, __user_ctx, __skip) ?;
61+ #( #raw_bindings) *
62+ #( #translated_bindings) *
63+ let mut #ctx = yeast:: build:: BuildCtx :: with_translator( __ast, & __captures, __source_range, __user_ctx, __translator) ;
64+ let __result: Vec <yeast:: Id > = { #replacement } ;
65+ let __result = #ctx. finish_rule( __result) ;
66+ Ok ( __result)
67+ } ) ,
68+ )
69+ }
70+ }
71+ }
72+ }
73+
74+ impl Replacement {
75+ fn lower ( & self ) -> TokenStream {
76+ match self {
77+ Replacement :: Templates ( templates) => Template :: lower_list ( templates) ,
78+ Replacement :: Rust { body, .. } => {
79+ let body = rust_block ( body) ;
80+ quote ! {
81+ let __value = #body;
82+ let mut __ids: Vec <yeast:: Id > = Vec :: new( ) ;
83+ yeast:: IntoFieldIds :: extend_into( __value, & mut __ids) ;
84+ __ids
85+ }
86+ }
87+ }
88+ }
89+ }
90+
91+ impl Pattern {
92+ pub ( crate ) fn lower ( & self ) -> TokenStream {
93+ match self {
94+ Pattern :: Any { match_unnamed } => {
95+ quote ! { yeast:: query:: QueryNode :: Any { match_unnamed: #match_unnamed } }
96+ }
97+ Pattern :: Node { kind, fields } => {
98+ let fields = fields. iter ( ) . map ( |( name, pattern) | {
99+ let elements = pattern. lower_list ( ) ;
100+ quote ! { ( #name, vec![ #( #elements) , * ] ) }
101+ } ) ;
102+ quote ! {
103+ yeast:: query:: QueryNode :: Node {
104+ kind: #kind,
105+ children: vec![ #( #fields) , * ] ,
106+ }
107+ }
108+ }
109+ Pattern :: Unnamed ( kind) => {
110+ quote ! { yeast:: query:: QueryNode :: UnnamedNode { kind: #kind } }
111+ }
112+ Pattern :: Capture { capture, pattern } => {
113+ let name = capture. name . to_string ( ) ;
114+ let pattern = pattern. lower ( ) ;
115+ quote ! {
116+ yeast:: query:: QueryNode :: Capture {
117+ capture: #name,
118+ node: Box :: new( #pattern) ,
119+ }
120+ }
121+ }
122+ Pattern :: Sequence ( _) | Pattern :: Repeated { .. } => {
123+ unreachable ! ( "sequence and repeated patterns cannot match a single node" )
124+ }
125+ }
126+ }
127+
128+ fn lower_list ( & self ) -> Vec < TokenStream > {
129+ match self {
130+ Pattern :: Sequence ( patterns) => patterns. iter ( ) . flat_map ( Pattern :: lower_list) . collect ( ) ,
131+ Pattern :: Repeated {
132+ pattern,
133+ cardinality,
134+ } => {
135+ let children = pattern. lower_list ( ) ;
136+ let repetition = match ( cardinality. multiple , cardinality. required ) {
137+ ( true , false ) => quote ! { yeast:: query:: Rep :: ZeroOrMore } ,
138+ ( true , true ) => quote ! { yeast:: query:: Rep :: OneOrMore } ,
139+ ( false , false ) => quote ! { yeast:: query:: Rep :: ZeroOrOne } ,
140+ ( false , true ) => unreachable ! ( "single patterns are not wrapped as repeated" ) ,
141+ } ;
142+ vec ! [ quote! {
143+ yeast:: query:: QueryListElem :: Repeated {
144+ children: vec![ #( #children) , * ] ,
145+ rep: #repetition,
146+ }
147+ } ]
148+ }
149+ pattern => {
150+ let pattern = pattern. lower ( ) ;
151+ vec ! [ quote! { yeast:: query:: QueryListElem :: SingleNode ( #pattern) } ]
152+ }
153+ }
154+ }
155+ fn captures ( & self ) -> Vec < BoundCapture > {
156+ let mut captures = Vec :: new ( ) ;
157+ self . collect_captures ( Cardinality :: SINGLE , & mut captures) ;
158+ captures
159+ }
160+
161+ fn collect_captures ( & self , cardinality : Cardinality , captures : & mut Vec < BoundCapture > ) {
162+ match self {
163+ Pattern :: Any { .. } | Pattern :: Unnamed ( _) => { }
164+ Pattern :: Node { fields, .. } => {
165+ for ( _, pattern) in fields {
166+ pattern. collect_captures ( cardinality, captures) ;
167+ }
168+ }
169+ Pattern :: Capture { capture, pattern } => {
170+ pattern. collect_captures ( cardinality, captures) ;
171+ captures. push ( BoundCapture {
172+ capture : capture. clone ( ) ,
173+ cardinality,
174+ } ) ;
175+ }
176+ Pattern :: Sequence ( patterns) => {
177+ for pattern in patterns {
178+ pattern. collect_captures ( cardinality, captures) ;
179+ }
180+ }
181+ Pattern :: Repeated {
182+ pattern,
183+ cardinality : repeated,
184+ } => {
185+ pattern. collect_captures ( combine_cardinality ( cardinality, * repeated) , captures) ;
186+ }
187+ }
188+ }
189+ }
190+
191+ fn combine_cardinality ( parent : Cardinality , child : Cardinality ) -> Cardinality {
192+ Cardinality {
193+ multiple : parent. multiple || child. multiple ,
194+ required : parent. required && child. required ,
195+ }
196+ }
197+
198+ fn capture_bindings < ' a > ( captures : impl Iterator < Item = & ' a BoundCapture > ) -> Vec < TokenStream > {
199+ captures
200+ . map ( |capture| {
201+ let name_string = capture. capture . name . to_string ( ) ;
202+ let name = Ident :: new ( & name_string, Span :: call_site ( ) ) ;
203+ match ( capture. cardinality . multiple , capture. cardinality . required ) {
204+ ( true , _) => {
205+ quote ! {
206+ let #name: Vec <yeast:: Id > = __captures. get_all( #name_string) ;
207+ }
208+ }
209+ ( false , false ) => {
210+ quote ! {
211+ let #name: Option <yeast:: Id > = __captures. get_opt( #name_string) ;
212+ }
213+ }
214+ ( false , true ) => {
215+ quote ! {
216+ let #name: yeast:: Id = __captures. get_var( #name_string) . unwrap( ) ;
217+ }
218+ }
219+ }
220+ } )
221+ . collect ( )
222+ }
223+
19224impl Template {
20225 pub ( crate ) fn lower_root ( & self ) -> TokenStream {
21226 self . lower ( & LoweringContext {
0 commit comments