1use proc_macro::TokenStream;
2use proc_macro2::{Span, TokenStream as TokenStream2};
3use quote::quote;
4use syn::{parse_quote, Data, DataEnum, DataStruct, DeriveInput, Fields, Generics, Ident};
5
6#[proc_macro_derive(Grammar, attributes(grammar))]
20pub fn derive_grammar(input: TokenStream) -> TokenStream {
21 let mut input = syn::parse_macro_input!(input as DeriveInput);
22 for param in input.generics.type_params_mut() {
23 param.bounds.push(parse_quote!(::tygr::Grammar));
24 }
25 match impl_grammar(&input) {
26 Ok(tokens) => tokens.into(),
27 Err(err) => err.to_compile_error().into(),
28 }
29}
30
31#[proc_macro_derive(GrammarFromStr)]
37pub fn derive_grammar_from_str(input: TokenStream) -> TokenStream {
38 derive_convert(input, Convert::FromStr)
39}
40
41#[proc_macro_derive(GrammarFromOther)]
46pub fn derive_grammar_from_source(input: TokenStream) -> TokenStream {
47 derive_convert(input, Convert::From)
48}
49
50#[proc_macro_derive(GrammarTryFromOther)]
56pub fn derive_grammar_try_from_source(input: TokenStream) -> TokenStream {
57 derive_convert(input, Convert::TryFrom)
58}
59
60#[derive(Clone, Copy)]
61enum Convert {
62 FromStr,
63 From,
64 TryFrom,
65}
66
67fn derive_convert(input: TokenStream, convert: Convert) -> TokenStream {
68 let mut input = syn::parse_macro_input!(input as DeriveInput);
69 for param in input.generics.type_params_mut() {
70 param.bounds.push(parse_quote!(::tygr::Grammar));
71 }
72 match impl_convert(&input, convert) {
73 Ok(tokens) => tokens.into(),
74 Err(err) => err.to_compile_error().into(),
75 }
76}
77
78#[proc_macro]
87#[allow(non_snake_case)]
88pub fn StringEq(input: TokenStream) -> TokenStream {
89 let lit = syn::parse_macro_input!(input as syn::LitStr);
90 let value = lit.value();
91 let chars: Vec<char> = value.chars().collect();
92
93 if chars.is_empty() {
94 return syn::Error::new(
95 lit.span(),
96 "StringEq!() requires a non-empty string literal",
97 )
98 .to_compile_error()
99 .into();
100 }
101
102 let chain = build_nested_chain(&chars, |ch, rest| quote! { ::tygr::CharThen<#ch, #rest> });
103 quote! { ::tygr::StringEq<#chain> }.into()
104}
105
106fn build_nested_chain<F>(items: &[char], mapper: F) -> TokenStream2
108where
109 F: Fn(&char, TokenStream2) -> TokenStream2,
110{
111 items
112 .iter()
113 .rev()
114 .fold(quote! { () }, |rest, ch| mapper(ch, rest))
115}
116
117#[proc_macro]
118#[allow(non_snake_case)]
119pub fn StringEqCI(input: TokenStream) -> TokenStream {
120 let lit = syn::parse_macro_input!(input as syn::LitStr);
121 let value = lit.value();
122 let chars: Vec<char> = value.chars().collect();
123
124 if chars.is_empty() {
125 return syn::Error::new(
126 lit.span(),
127 "StringEqCI!() requires a non-empty string literal",
128 )
129 .to_compile_error()
130 .into();
131 }
132
133 let chain = build_nested_chain(&chars, |ch, rest| quote! { ::tygr::CharCIThen<#ch, #rest> });
134 quote! { ::tygr::StringEqCI<#chain> }.into()
135}
136
137#[derive(Clone)]
138struct Tag {
139 name: TokenStream2,
140 case: Option<TokenStream2>,
141}
142
143impl Tag {
144 fn new(name: TokenStream2, case: Option<TokenStream2>) -> Self {
145 Self { name, case }
146 }
147
148 fn as_constructor(&self) -> TokenStream2 {
149 let name = &self.name;
150 let case = if let Some(case) = &self.case {
151 quote! { :: #case }
152 } else {
153 quote! {}
154 };
155 quote! { #name #case }
156 }
157}
158
159fn with_node(inline: bool, body: TokenStream2) -> TokenStream2 {
160 if inline {
161 body
162 } else {
163 quote! {
164 let mut state = state.node(Self::NAME, pos);
165 #body
166 }
167 }
168}
169
170fn impl_grammar(input: &DeriveInput) -> syn::Result<TokenStream2> {
171 let ident = &input.ident;
172 let generics = &input.generics;
173 let GrammarAttr {
174 name,
175 hidden,
176 inline,
177 validated,
178 } = grammar_attr(input)?;
179 let name = name.unwrap_or_else(|| {
180 let ident = ident.to_string();
181 #[cfg(all(feature = "lower_bnf_name", not(feature = "upper_bnf_name")))]
182 let ident = ident.to_ascii_lowercase();
183 #[cfg(all(feature = "upper_bnf_name", not(feature = "lower_bnf_name")))]
184 let ident = ident.to_ascii_uppercase();
185 ident
186 });
187 match &input.data {
188 Data::Struct(data) => impl_struct(ident, generics, name, hidden, inline, validated, data),
189 Data::Enum(data) => impl_enum(ident, generics, name, hidden, inline, validated, data),
190 Data::Union(_) => Err(syn::Error::new_spanned(
191 ident,
192 "Grammar cannot be derived for unions",
193 )),
194 }
195}
196
197fn grammar_attr(input: &DeriveInput) -> syn::Result<GrammarAttr> {
198 for attr in &input.attrs {
199 if attr.path().is_ident("grammar") {
200 return attr.parse_args::<GrammarAttr>();
201 }
202 }
203 Ok(GrammarAttr::default())
204}
205
206#[derive(Default)]
207struct GrammarAttr {
208 name: Option<String>,
209 hidden: bool,
210 inline: bool,
211 validated: bool,
212}
213
214impl syn::parse::Parse for GrammarAttr {
215 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
216 let mut attr = GrammarAttr::default();
217
218 while !input.is_empty() {
219 let ident: syn::Ident = input.parse()?;
220 if ident == "name" {
221 let _: syn::Token![=] = input.parse()?;
222 let lit: syn::LitStr = input.parse()?;
223 attr.name = Some(lit.value());
224 } else if ident == "hidden" {
225 attr.hidden = true;
226 attr.inline = true;
229 } else if ident == "inline" {
230 attr.inline = true;
231 } else if ident == "validated" {
232 attr.validated = true;
233 } else {
234 return Err(syn::Error::new(
235 ident.span(),
236 "expected `name`, `hidden`, `inline`, or `validated`",
237 ));
238 }
239 if input.is_empty() {
240 break;
241 }
242 let _: syn::Token![,] = input.parse()?;
243 }
244
245 Ok(attr)
246 }
247}
248
249type ProcessedFields<'a> = Vec<(String, Ident, &'a syn::Type)>;
250
251fn components_and_xts(tag: TokenStream2, fields: &Fields) -> (TokenStream2, ProcessedFields<'_>) {
252 match fields {
253 Fields::Named(fields) => {
254 let fields: Vec<_> = fields
255 .named
256 .iter()
257 .map(|field| {
258 let x = field.ident.as_ref().unwrap().clone();
259 let t = &field.ty;
260 (x.to_string(), x, t)
261 })
262 .collect();
263 let xs = fields.iter().map(|(_, x, _)| x);
264 (quote! { #tag { #(#xs),* } }, fields)
265 }
266 Fields::Unnamed(fields) => {
267 let fields: Vec<_> = fields
268 .unnamed
269 .iter()
270 .enumerate()
271 .map(|(i, field)| {
272 let x = Ident::new(&format!("_f{i}"), Span::call_site());
273 let t = &field.ty;
274 (i.to_string(), x, t)
275 })
276 .collect();
277 let xs = fields.iter().map(|(_, x, _)| x);
278 (quote! { #tag ( #(#xs),* ) }, fields)
279 }
280 Fields::Unit => (quote! { #tag }, vec![]),
281 }
282}
283
284fn parse_at(validated: bool, fields: &ProcessedFields, constructor: &TokenStream2) -> TokenStream2 {
285 let steps: Vec<_> = fields
286 .iter()
287 .map(|(_, x, t)| {
288 quote! {
289 let (#x, pos) = <#t as ::tygr::Grammar>::parse_at(input, pos, state.reborrow())?;
290 }
291 })
292 .collect();
293 let (start_pos, validate) = if validated {
294 let trace = if cfg!(feature = "trace") {
295 quote! {
296 state.expect(pos, ::tygr::Expectation::Valid { pos: start_pos, be_valid });
297 }
298 } else if cfg!(feature = "trace_pos") {
299 quote! {
300 state.expect(pos);
301 }
302 } else {
303 quote! {}
304 };
305 (
306 quote! { let start_pos = pos; },
307 quote! {
308 if let Some(be_valid) = ::tygr::Validation::be_valid(::tygr::Validate::validate(&value)) {
309 #trace
310 return None
311 }
312 },
313 )
314 } else {
315 (quote! {}, quote! {})
316 };
317 quote! {
318 #start_pos
319 #(#steps)*
320 let value = #constructor;
321 #validate
322 Some((value, pos))
323 }
324}
325
326fn scan_at(validated: bool, fields: &ProcessedFields, constructor: &TokenStream2) -> TokenStream2 {
327 if validated {
328 let parse_at = parse_at(true, fields, constructor);
329 quote! { ({#parse_at}).map(|(_, pos)| pos) }
330 } else {
331 let steps: Vec<_> = fields
332 .iter()
333 .map(|(_, _, t)| {
334 quote! {
335 let pos = <#t as ::tygr::Grammar>::scan_at(input, pos, state.reborrow())?;
336 }
337 })
338 .collect();
339 quote! {
340 #(#steps)*
341 Some(pos)
342 }
343 }
344}
345
346fn print_steps(fields: &ProcessedFields) -> Vec<TokenStream2> {
347 fields
348 .iter()
349 .map(|(_, x, _)| {
350 quote! {
351 ::tygr::Grammar::print_to(#x, buf);
352 }
353 })
354 .collect()
355}
356
357fn to_bnf(fields: &ProcessedFields) -> TokenStream2 {
358 let ts = fields.iter().map(|(_, _, t)| quote! { #t });
359 quote! {
360 ::tygr::bnf::Expr::sequence(vec![
361 #(<#ts as ::tygr::Grammar>::to_bnf()),*
362 ])
363 }
364}
365
366fn fail_at(fields: &ProcessedFields) -> TokenStream2 {
370 let calls = fields.iter().map(|(_, _, t)| {
371 quote! { <#t as ::tygr::Grammar>::fail_at(pos, state.reborrow()) }
372 });
373 quote! {
374 #(#calls ||)* false
375 }
376}
377
378fn bnf_ref(grammar_name: &str, hidden: bool, to_bnf: TokenStream2, inline: bool) -> TokenStream2 {
379 if hidden {
380 quote! { ::tygr::bnf::Expr::empty() }
381 } else if inline {
382 to_bnf
383 } else {
384 quote! { ::tygr::bnf::Expr::RuleRef(#grammar_name.to_string()) }
385 }
386}
387
388struct FieldsInfo {
389 constructor: TokenStream2,
390 parse_at: TokenStream2,
391 scan_at: TokenStream2,
392 print_to: TokenStream2,
393 to_bnf: TokenStream2,
394 fail_at: TokenStream2,
395 first: TokenStream2,
396}
397
398impl FieldsInfo {
399 fn from(validated: bool, tag: Tag, fields: &Fields) -> Self {
400 let (constructor, fields) = components_and_xts(tag.as_constructor(), fields);
401 let print_steps = print_steps(&fields);
402 let parse_at = parse_at(validated, &fields, &constructor);
403 let scan_at = scan_at(validated, &fields, &constructor);
404 let mut first = quote! { ::tygr::OptionalFirst<::tygr::EmptyByteSet> };
405 for (_, _, t) in &fields {
406 first = quote! {
407 <#first as ::tygr::First>::Concat<#t>
408 }
409 }
410 Self {
411 parse_at: quote! { #parse_at },
412 scan_at: quote! { #scan_at },
413 print_to: quote! {#(#print_steps)*},
414 to_bnf: to_bnf(&fields),
415 fail_at: fail_at(&fields),
416 constructor,
417 first,
418 }
419 }
420}
421
422fn impl_convert(input: &DeriveInput, convert: Convert) -> syn::Result<TokenStream2> {
423 let ident = &input.ident;
424 let generics = &input.generics;
425 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
426 let self_ty = quote! { #ident #ty_generics };
427 let source = quote! { <#self_ty as ::tygr::GrammarFrom>::Source };
428 let trace = if cfg!(feature = "trace") {
430 quote! {
431 state.expect(
432 end,
433 ::tygr::Expectation::GrammarFrom(::std::string::ToString::to_string(&err)),
434 );
435 }
436 } else if cfg!(feature = "trace_pos") {
437 quote! {
438 state.expect(end);
439 }
440 } else {
441 quote! {}
442 };
443 let parse_at = match convert {
444 Convert::FromStr => quote! {
445 let end = <#source as ::tygr::Grammar>::scan_at(input, pos, state.reborrow())?;
446 match <#self_ty as ::core::str::FromStr>::from_str(&input[pos..end]) {
447 Ok(value) => Some((value, end)),
448 Err(err) => {
449 #trace
450 let _ = &err;
451 None
452 }
453 }
454 },
455 Convert::From => quote! {
456 let (source, end) = <#source as ::tygr::Grammar>::parse_at(input, pos, state.reborrow())?;
457 Some((<#self_ty as ::core::convert::From<#source>>::from(source), end))
458 },
459 Convert::TryFrom => quote! {
460 let (source, end) = <#source as ::tygr::Grammar>::parse_at(input, pos, state.reborrow())?;
461 match <#self_ty as ::core::convert::TryFrom<#source>>::try_from(source) {
462 Ok(value) => Some((value, end)),
463 Err(err) => {
464 #trace
465 let _ = &err;
466 None
467 }
468 }
469 },
470 };
471 let scan_at = match convert {
473 Convert::From => quote! {
474 <#source as ::tygr::Grammar>::scan_at(input, pos, state)
475 },
476 Convert::FromStr | Convert::TryFrom => quote! {
477 Self::parse_at(input, pos, state).map(|(_, end)| end)
478 },
479 };
480 Ok(quote! {
481 impl #impl_generics ::tygr::Grammar for #self_ty #where_clause {
482 type First = <#source as ::tygr::Grammar>::First;
483
484 #[inline]
485 fn parse_at(input: &str, pos: usize, #[allow(unused_mut)] mut state: ::tygr::State) -> Option<(Self, usize)> {
486 #parse_at
487 }
488
489 #[inline]
490 fn scan_at(input: &str, pos: usize, #[allow(unused_mut)] mut state: ::tygr::State) -> Option<usize> {
491 #scan_at
492 }
493
494 fn print_to(&self, buf: &mut ::std::string::String) {
495 <#self_ty as ::tygr::GrammarFrom>::print_to(self, buf);
496 }
497
498 fn to_bnf() -> ::tygr::bnf::Expr {
499 <#source as ::tygr::Grammar>::to_bnf()
500 }
501
502 fn fail_at(pos: usize, state: ::tygr::State) -> bool {
503 <#source as ::tygr::Grammar>::fail_at(pos, state)
504 }
505 }
506 })
507}
508
509fn impl_struct(
510 ident: &Ident,
511 generics: &Generics,
512 name: String,
513 hidden: bool,
514 inline: bool,
515 validated: bool,
516 data: &DataStruct,
517) -> syn::Result<TokenStream2> {
518 let tag = Tag::new(quote! { #ident }, None);
519 let fields = &data.fields;
520 let FieldsInfo {
521 constructor,
522 parse_at,
523 scan_at,
524 print_to,
525 to_bnf,
526 fail_at,
527 first,
528 } = FieldsInfo::from(validated, tag, fields);
529 let parse_at = with_node(inline, parse_at);
530 let scan_at = with_node(inline, scan_at);
531 let fail_at = with_node(inline, fail_at);
532 let bnf_ref = bnf_ref(&name, hidden, to_bnf.clone(), inline);
533 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
534 Ok(quote! {
535 impl #impl_generics ::tygr::Grammar for #ident #ty_generics #where_clause {
536 type First = #first;
537
538 #[inline]
539 fn parse_at(input: &str, pos: usize, #[allow(unused_mut)] mut state: ::tygr::State) -> Option<(Self, usize)> {
540 #parse_at
541 }
542
543 #[inline]
544 fn scan_at(input: &str, pos: usize, #[allow(unused_mut)] mut state: ::tygr::State) -> Option<usize> {
545 #scan_at
546 }
547
548 fn print_to(&self, buf: &mut ::std::string::String) {
549 let #constructor = &self;
550 #print_to
551 }
552
553 fn to_bnf() -> ::tygr::bnf::Expr {
554 #bnf_ref
555 }
556
557 fn fail_at(#[allow(unused_variables)] pos: usize, #[allow(unused_variables, unused_mut)] mut state: ::tygr::State) -> bool {
558 #fail_at
559 }
560 }
561
562 impl #impl_generics ::tygr::GrammarRule for #ident #ty_generics #where_clause {
563 const NAME: &'static str = #name;
564
565 fn to_bnf_def() -> ::tygr::bnf::Expr {
566 #to_bnf
567 }
568 }
569 })
570}
571
572fn impl_enum(
575 ident: &Ident,
576 generics: &Generics,
577 name: String,
578 hidden: bool,
579 inline: bool,
580 validated: bool,
581 data: &DataEnum,
582) -> syn::Result<TokenStream2> {
583 let mut each_constructor = vec![];
584 let mut each_parse_at = vec![];
585 let mut each_scan_at = vec![];
586 let mut each_print_to = vec![];
587 let mut each_to_bnf = vec![];
588 let mut each_fail_at = vec![];
589 let mut each_first = vec![];
590 for variant in &data.variants {
591 let variant_ident = &variant.ident;
592 let tag = Tag::new(quote! { #ident }, Some(quote! {#variant_ident}));
593 let FieldsInfo {
594 constructor,
595 parse_at,
596 scan_at,
597 print_to,
598 to_bnf,
599 fail_at,
600 first,
601 } = FieldsInfo::from(validated, tag, &variant.fields);
602 each_constructor.push(constructor);
603 each_parse_at.push(parse_at);
604 each_scan_at.push(scan_at);
605 each_print_to.push(print_to);
606 each_to_bnf.push(to_bnf);
607 each_fail_at.push(fail_at);
608 each_first.push(first);
609 }
610 let fail_at_variants_body = {
614 let mut variants = each_fail_at.iter();
615 let first = variants.next().cloned().unwrap_or_else(|| quote! { false });
616 variants.fold(first, |acc, next| quote! { (#acc) & (#next) })
617 };
618 let to_bnf = quote! { ::tygr::bnf::Expr::alternation(vec![ #(#each_to_bnf),* ]) };
619 let bnf_ref = bnf_ref(&name, hidden, to_bnf.clone(), inline);
620 let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
621 let n = each_first.len();
622 let self_ty = quote! { #ident #ty_generics };
623 let parse_fn_ty = quote! {
624 fn(&str, usize, ::tygr::State<'_>) -> Option<(#self_ty, usize)>
625 };
626 let scan_fn_ty = quote! {
627 fn(&str, usize, ::tygr::State<'_>) -> Option<usize>
628 };
629 let case_fns: Vec<Ident> = (0..n)
630 .map(|k| Ident::new(&format!("parse_case_{k}"), Span::call_site()))
631 .collect();
632 let scan_fns: Vec<Ident> = (0..n)
633 .map(|k| Ident::new(&format!("scan_case_{k}"), Span::call_site()))
634 .collect();
635 let case_defs = case_fns.iter().zip(&each_parse_at).enumerate().map(|(k, (name, arm))| {
636 let next = if k + 1 < n {
637 let nx = &case_fns[k + 1];
638 quote! { Self::#nx(input, pos, state) }
639 } else {
640 quote! { None }
641 };
642 quote! {
643 #[inline]
644 fn #name(input: &str, pos: usize, #[allow(unused_variables, unused_mut)] mut state: ::tygr::State) -> Option<(Self, usize)> {
645 if let Some(result) = (|| { #arm })() { return Some(result); }
646 #next
647 }
648 }
649 });
650 let scan_case_defs = scan_fns
651 .iter()
652 .zip(&each_scan_at)
653 .enumerate()
654 .map(|(k, (name, arm))| {
655 let next = if k + 1 < n {
656 let nx = &scan_fns[k + 1];
657 quote! { Self::#nx(input, pos, state) }
658 } else {
659 quote! { None }
660 };
661 quote! {
662 #[inline]
663 fn #name(input: &str, pos: usize, #[allow(unused_variables, unused_mut)] mut state: ::tygr::State) -> Option<usize> {
664 if let Some(result) = (|| { #arm })() { return Some(result); }
665 #next
666 }
667 }
668 });
669 let build_table = |fn_ty: &TokenStream2, fns: &[Ident], miss: &TokenStream2| {
672 quote! {{
673 let parsers: [#fn_ty; #n] = [ #(<#self_ty>::#fns),* ];
674 let mut table: [#fn_ty; 257] = [#miss; 257];
678 let mut first = 0usize;
679 while first < 257 {
680 let mut case = 0usize;
681 while case < #n {
682 if CONTAINS_NIL[case] || (first <= 255 && CONTAINS_BYTE[case][first]) {
683 table[first] = parsers[case];
684 break;
685 }
686 case += 1;
687 }
688 first += 1;
689 }
690 table
691 }}
692 };
693 let parse_table = build_table(
694 &parse_fn_ty,
695 &case_fns,
696 "e! { <#self_ty>::parse_case_miss },
697 );
698 let scan_table = build_table(
699 &scan_fn_ty,
700 &scan_fns,
701 "e! { <#self_ty>::scan_case_miss },
702 );
703 const DISPATCH_THRESHOLD: usize = 4;
704 let fail_at_on_miss = if cfg!(feature = "trace_pos") {
708 quote! { Self::fail_at_variants(pos, state); }
709 } else {
710 quote! {}
711 };
712 let (dispatch_body, scan_dispatch_body, case_impls) = if n >= DISPATCH_THRESHOLD {
713 (
714 quote! {
715 const CONTAINS_NIL: [bool; #n] = [ #(<#each_first as ::tygr::First>::CONTAINS_NIL),* ];
716 const CONTAINS_BYTE: [[bool; 256]; #n] = [ #(<#each_first as ::tygr::First>::CONTAINS_BYTE),* ];
717 const DISPATCH: [#parse_fn_ty; 257] = #parse_table;
718 let first = input.as_bytes().get(pos).map(|&first| first as usize).unwrap_or(256);
719 DISPATCH[first](input, pos, state)
720 },
721 quote! {
722 const CONTAINS_NIL: [bool; #n] = [ #(<#each_first as ::tygr::First>::CONTAINS_NIL),* ];
723 const CONTAINS_BYTE: [[bool; 256]; #n] = [ #(<#each_first as ::tygr::First>::CONTAINS_BYTE),* ];
724 const DISPATCH: [#scan_fn_ty; 257] = #scan_table;
725 let first = input.as_bytes().get(pos).map(|&first| first as usize).unwrap_or(256);
726 DISPATCH[first](input, pos, state)
727 },
728 quote! {
729 #(#case_defs)*
730 #(#scan_case_defs)*
731
732 #[inline]
733 fn parse_case_miss(_input: &str, #[allow(unused_variables)] pos: usize, #[allow(unused_variables)] state: ::tygr::State) -> Option<(Self, usize)> {
734 #fail_at_on_miss
735 None
736 }
737
738 #[inline]
739 fn scan_case_miss(_input: &str, #[allow(unused_variables)] pos: usize, #[allow(unused_variables)] state: ::tygr::State) -> Option<usize> {
740 #fail_at_on_miss
741 None
742 }
743 },
744 )
745 } else {
746 (
747 quote! {
748 #( if let Some(result) = (|| { #each_parse_at })() { return Some(result); } )*
749 None
750 },
751 quote! {
752 #( if let Some(result) = (|| { #each_scan_at })() { return Some(result); } )*
753 None
754 },
755 quote! {},
756 )
757 };
758 let parse_body = with_node(inline, dispatch_body);
759 let scan_body = with_node(inline, scan_dispatch_body);
760 let fail_at = with_node(inline, quote! { Self::fail_at_variants(pos, state) });
761 let first = {
762 let mut the_first = quote! { ::tygr::EmptyByteSet };
763 for first in each_first {
764 the_first = quote! { <#the_first as ::tygr::First>::Union<#first> };
765 }
766 the_first
767 };
768 Ok(quote! {
769 impl #impl_generics #ident #ty_generics #where_clause {
770 #case_impls
771
772 #[inline]
773 fn parse_case_none(_input: &str, _pos: usize, _state: ::tygr::State) -> Option<(Self, usize)> {
774 None
775 }
776
777 #[inline]
778 fn fail_at_variants(#[allow(unused_variables)] pos: usize, #[allow(unused_variables, unused_mut)] mut state: ::tygr::State) -> bool {
779 #fail_at_variants_body
780 }
781 }
782
783 impl #impl_generics ::tygr::Grammar for #ident #ty_generics #where_clause {
784 type First = #first;
785
786 #[inline]
787 fn parse_at(input: &str, pos: usize, #[allow(unused_variables, unused_mut)] mut state: ::tygr::State) -> Option<(Self, usize)> {
788 #parse_body
789 }
790
791 #[inline]
792 fn scan_at(input: &str, pos: usize, #[allow(unused_variables, unused_mut)] mut state: ::tygr::State) -> Option<usize> {
793 #scan_body
794 }
795
796 fn print_to(&self, buf: &mut ::std::string::String) {
797 match self {
798 #(#each_constructor => { #each_print_to }),*
799 }
800 }
801
802 fn to_bnf() -> ::tygr::bnf::Expr {
803 #bnf_ref
804 }
805
806 fn fail_at(pos: usize, #[allow(unused_variables, unused_mut)] mut state: ::tygr::State) -> bool {
807 #fail_at
808 }
809 }
810
811 impl #impl_generics ::tygr::GrammarRule for #ident #ty_generics #where_clause {
812 const NAME: &'static str = #name;
813
814 fn to_bnf_def() -> ::tygr::bnf::Expr {
815 #to_bnf
816 }
817 }
818 })
819}