@@ -74,6 +74,47 @@ fn pdl_proc_macro(path: syn::LitStr, input: syn::ItemMod) -> TokenStream {
74
74
}
75
75
}
76
76
77
+ fn pdl_inline_proc_macro ( code : syn:: LitStr , input : syn:: ItemMod ) -> TokenStream {
78
+ // Load and parse the grammar.
79
+ let mut sources = pdl_compiler:: ast:: SourceDatabase :: new ( ) ;
80
+ let file = match pdl_compiler:: parser:: parse_inline ( & mut sources, "stdin" , code. value ( ) ) {
81
+ Ok ( file) => file,
82
+ Err ( err) => {
83
+ let mut buffer = termcolor:: Buffer :: no_color ( ) ;
84
+ term:: emit ( & mut buffer, & term:: Config :: default ( ) , & sources, & err)
85
+ . expect ( "could not emit parser diagnostics" ) ;
86
+ return syn:: Error :: new ( code. span ( ) , String :: from_utf8 ( buffer. into_inner ( ) ) . unwrap ( ) )
87
+ . to_compile_error ( ) ;
88
+ }
89
+ } ;
90
+
91
+ // Run the analyzer.
92
+ let analyzed_file = match pdl_compiler:: analyzer:: analyze ( & file) {
93
+ Ok ( file) => file,
94
+ Err ( diagnostics) => {
95
+ let mut buffer = termcolor:: Buffer :: no_color ( ) ;
96
+ diagnostics. emit ( & sources, & mut buffer) . expect ( "could not emit analyzer diagnostics" ) ;
97
+ return syn:: Error :: new ( code. span ( ) , String :: from_utf8 ( buffer. into_inner ( ) ) . unwrap ( ) )
98
+ . to_compile_error ( ) ;
99
+ }
100
+ } ;
101
+
102
+ // Generate the pdl backend implementation.
103
+ let parser = pdl_compiler:: backends:: rust:: generate_tokens ( & sources, & analyzed_file, & [ ] ) ;
104
+ let mod_ident = input. ident ;
105
+ let mod_attrs = input. attrs ;
106
+ let mod_vis = input. vis ;
107
+ let mod_items = input. content . map ( |( _, items) | items) . unwrap_or_default ( ) ;
108
+
109
+ quote ! {
110
+ #( #mod_attrs) *
111
+ #mod_vis mod #mod_ident {
112
+ #parser
113
+ #( #mod_items) *
114
+ }
115
+ }
116
+ }
117
+
77
118
/// The main method that's called by the proc macro
78
119
/// (a wrapper around `pest_generator::derive_parser`)
79
120
#[ proc_macro_attribute]
@@ -86,8 +127,21 @@ pub fn pdl(
86
127
pdl_proc_macro ( attr, input) . into ( )
87
128
}
88
129
130
+ /// The main method that's called by the proc macro
131
+ /// (a wrapper around `pest_generator::derive_parser`)
132
+ #[ proc_macro_attribute]
133
+ pub fn pdl_inline (
134
+ attr : proc_macro:: TokenStream ,
135
+ input : proc_macro:: TokenStream ,
136
+ ) -> proc_macro:: TokenStream {
137
+ let attr = parse_macro_input ! ( attr as syn:: LitStr ) ;
138
+ let input = parse_macro_input ! ( input as syn:: ItemMod ) ;
139
+ pdl_inline_proc_macro ( attr, input) . into ( )
140
+ }
141
+
89
142
#[ cfg( test) ]
90
143
mod test {
144
+ use super :: pdl_inline_proc_macro;
91
145
use super :: pdl_proc_macro;
92
146
use proc_macro2:: TokenStream ;
93
147
use quote:: quote;
@@ -167,4 +221,55 @@ mod test {
167
221
Some ( "error[E" )
168
222
) ) ;
169
223
}
224
+
225
+ #[ test]
226
+ fn test_derive_valid_inline ( ) {
227
+ assert ! ( !is_compile_error(
228
+ pdl_inline_proc_macro(
229
+ make_attr( quote! {
230
+ r#"
231
+ little_endian_packets
232
+ packet Prout {
233
+ x: 8,
234
+ }
235
+ "# } ) ,
236
+ make_input( quote! { mod Test { } } ) ,
237
+ ) ,
238
+ None
239
+ ) ) ;
240
+ }
241
+
242
+ #[ test]
243
+ fn test_derive_parser_error_inline ( ) {
244
+ assert ! ( is_compile_error(
245
+ pdl_inline_proc_macro(
246
+ make_attr( quote! {
247
+ r#"
248
+ little_endian_packets
249
+ enum A {
250
+ X = 0
251
+ }
252
+ "# } ) ,
253
+ make_input( quote! { mod Test { } } ) ,
254
+ ) ,
255
+ Some ( "error: failed to parse input file" )
256
+ ) ) ;
257
+ }
258
+
259
+ #[ test]
260
+ fn test_derive_analyzer_error_inline ( ) {
261
+ assert ! ( is_compile_error(
262
+ pdl_inline_proc_macro(
263
+ make_attr( quote! {
264
+ r#"
265
+ little_endian_packets
266
+ packet A {
267
+ x: Unknown,
268
+ }
269
+ "# } ) ,
270
+ make_input( quote! { mod Test { } } ) ,
271
+ ) ,
272
+ Some ( "error[E" )
273
+ ) ) ;
274
+ }
170
275
}
0 commit comments