1use std::{
2 any::type_name,
3 fmt::{self, Write},
4 hash::Hash,
5 marker::PhantomData,
6 path::Path,
7};
8
9use crate::{
10 LexerTypes, RecoveryKind, RustEdition, SerialisationFormat, Visibility,
11 ctbuilder::{FixIntConfig, VarIntConfig},
12};
13
14use cfgrammar::{
15 Location, RIdx, Span, Symbol,
16 header::{GrmtoolsSectionParser, Header, HeaderError, HeaderValue},
17 markmap::MergeError,
18 yacc::{
19 YaccGrammar, YaccGrammarError, YaccKind, YaccOriginalActionKind, ast::ASTWithValidityInfo,
20 },
21};
22
23use lrtable::{Minimiser, StateGraph, StateTable, StateTableError, from_yacc};
24use proc_macro2::{Literal, TokenStream};
25use quote::{ToTokens, TokenStreamExt, format_ident, quote};
26use syn::{Generics, parse_quote};
27use wincode::SchemaWrite;
28
29const ACTION_PREFIX: &str = "__gt_";
30const GLOBAL_PREFIX: &str = "__GT_";
31const ACTIONS_KIND: &str = "__GtActionsKind";
32const ACTIONS_KIND_PREFIX: &str = "Ak";
33const ACTIONS_KIND_HIDDEN: &str = "__GtActionsKindHidden";
34
35#[non_exhaustive]
36pub(crate) enum ParserSrcEnvError {
37 GrmtoolsSectionParseError(Vec<HeaderError<Span>>),
38 GrmtoolsSectionMergeError(MergeError<String, Box<HeaderValue<Location>>>),
39 GrmtoolsSectionLookupError(HeaderError<Location>),
40 MissingYaccKind,
41 MissingModName,
42}
43
44#[non_exhaustive]
45pub(crate) enum ParserBuildEnvError<LexerTypesT>
46where
47 LexerTypesT: LexerTypes,
48 usize: num_traits::AsPrimitive<LexerTypesT::StorageT>,
49{
50 StateTableError(StateTableError<LexerTypesT::StorageT>),
51 YaccGrammarErrors(Vec<YaccGrammarError>),
52 GrmtoolsSectionUnusedKeys(Vec<String>),
53 GrmtoolsSectionMissingRequiredKeys(Vec<String>),
54}
55
56#[non_exhaustive]
57pub(crate) enum CodegenError {
58 ProcMacro2Error(proc_macro2::LexError),
59 InvalidRustIdentifierModName(syn::Error, String),
60 InvalidParseGenerics(syn::Error),
61 WincodeError(wincode::WriteError),
62}
63
64impl From<Vec<HeaderError<Span>>> for ParserSrcEnvError {
65 fn from(it: Vec<HeaderError<Span>>) -> Self {
66 ParserSrcEnvError::GrmtoolsSectionParseError(it)
67 }
68}
69
70impl From<MergeError<String, Box<HeaderValue<Location>>>> for ParserSrcEnvError {
71 fn from(it: MergeError<String, Box<HeaderValue<Location>>>) -> Self {
72 ParserSrcEnvError::GrmtoolsSectionMergeError(it)
73 }
74}
75
76impl From<HeaderError<Location>> for ParserSrcEnvError {
77 fn from(it: HeaderError<Location>) -> Self {
78 ParserSrcEnvError::GrmtoolsSectionLookupError(it)
79 }
80}
81
82impl<LexerTypesT> From<Vec<YaccGrammarError>> for ParserBuildEnvError<LexerTypesT>
83where
84 LexerTypesT: LexerTypes,
85 usize: num_traits::AsPrimitive<LexerTypesT::StorageT>,
86{
87 fn from(it: Vec<YaccGrammarError>) -> Self {
88 ParserBuildEnvError::YaccGrammarErrors(it)
89 }
90}
91
92impl<LexerTypesT> From<StateTableError<LexerTypesT::StorageT>> for ParserBuildEnvError<LexerTypesT>
93where
94 LexerTypesT: LexerTypes,
95 usize: num_traits::AsPrimitive<LexerTypesT::StorageT>,
96{
97 fn from(it: StateTableError<LexerTypesT::StorageT>) -> Self {
98 ParserBuildEnvError::StateTableError(it)
99 }
100}
101
102impl From<proc_macro2::LexError> for CodegenError {
103 fn from(it: proc_macro2::LexError) -> Self {
104 CodegenError::ProcMacro2Error(it)
105 }
106}
107
108impl From<wincode::WriteError> for CodegenError {
109 fn from(it: wincode::WriteError) -> Self {
110 CodegenError::WincodeError(it)
111 }
112}
113
114impl fmt::Display for ParserSrcEnvError {
115 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116 f.write_str(&match self {
117 Self::GrmtoolsSectionParseError(errs) => errs
118 .iter()
119 .map(|e| e.to_string())
120 .collect::<Vec<_>>()
121 .join("\n"),
122 Self::GrmtoolsSectionMergeError(e) => e.to_string(),
123 Self::GrmtoolsSectionLookupError(e) => e.to_string(),
124 Self::MissingYaccKind => "Code generator cannot resolve yacc kind".to_string(),
125 Self::MissingModName => "Code generator requires a mod name".to_string(),
126 })
127 }
128}
129
130impl<LexerTypesT> fmt::Display for ParserBuildEnvError<LexerTypesT>
131where
132 LexerTypesT: LexerTypes,
133 usize: num_traits::AsPrimitive<LexerTypesT::StorageT>,
134{
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 f.write_str(&match self {
137 Self::StateTableError(e) => format!("{}", e).to_string(),
138 Self::YaccGrammarErrors(errs) => errs
139 .iter()
140 .map(|e| e.to_string())
141 .collect::<Vec<_>>()
142 .join("\n"),
143 Self::GrmtoolsSectionUnusedKeys(keys) => {
144 format!("Unused keys in %grmtools section: {}", keys.join(", "))
145 }
146 Self::GrmtoolsSectionMissingRequiredKeys(keys) => format!(
147 "Required keys are missing from %grmtools section: {}",
148 keys.join(", ")
149 ),
150 })
151 }
152}
153impl fmt::Display for CodegenError {
154 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155 f.write_str(&match self {
156 Self::ProcMacro2Error(e) => e.to_string(),
157 Self::InvalidRustIdentifierModName(e, s) => format!(
158 "mod_name '{}' is not a valid rust identifier due to '{}'",
159 s, e
160 ),
161 Self::InvalidParseGenerics(e) => format!("Unable to parse %parse-generics '{e}'"),
162 Self::WincodeError(e) => format!("Unable to serialize parser {e}"),
163 })
164 }
165}
166
167pub(crate) struct ParserSrcEnv<'a, LexerTypesT>
168where
169 LexerTypesT: LexerTypes,
170 usize: num_traits::AsPrimitive<LexerTypesT::StorageT>,
171{
172 src: &'a str,
173 fallback_modname: Option<String>,
174 grammar_path_cache_entry: Option<String>,
175 header: Header<Location>,
176 phantom: PhantomData<LexerTypesT::StorageT>,
177}
178
179pub(crate) struct ParserBuildEnvArgs<'a> {
180 ast_with_validity_info: Option<&'a ASTWithValidityInfo>,
182 mod_name: Option<String>,
183 rust_edition: RustEdition,
184 visibility: Visibility,
185 error_on_conflicts: bool,
186 show_warnings: bool,
187 warnings_are_errors: bool,
188}
189
190pub(crate) struct ParserBuildEnv<'a, LexerTypesT>
191where
192 LexerTypesT: LexerTypes,
193 usize: num_traits::AsPrimitive<LexerTypesT::StorageT>,
194{
195 ast_with_validity_info: ASTWithValidityInfo,
196 recoverer: RecoveryKind,
197 serialisation_format: SerialisationFormat,
198 cache_args: ParserBuildEnvArgs<'a>,
200 phantom_storaget: PhantomData<LexerTypesT::StorageT>,
201 mod_name: String,
202 grammar_path: Option<String>,
203 header: Header<Location>,
204}
205
206pub(crate) struct ParserCodegen<LexerTypesT>
207where
208 LexerTypesT: LexerTypes,
209 usize: num_traits::AsPrimitive<LexerTypesT::StorageT>,
210{
211 grm: YaccGrammar<LexerTypesT::StorageT>,
212 stable: StateTable<LexerTypesT::StorageT>,
213 sgraph: StateGraph<LexerTypesT::StorageT>,
214 timestamp: String,
215}
216
217impl<'a> ParserBuildEnvArgs<'a> {
218 pub(crate) fn new() -> Self {
219 ParserBuildEnvArgs {
220 ast_with_validity_info: None,
221 mod_name: None,
222 visibility: Visibility::Private,
223 rust_edition: RustEdition::Rust2021,
224 error_on_conflicts: true,
225 show_warnings: true,
226 warnings_are_errors: true,
227 }
228 }
229
230 pub(crate) fn ast_with_validity_info(mut self, ast: Option<&'a ASTWithValidityInfo>) -> Self {
233 self.ast_with_validity_info = ast;
234 self
235 }
236
237 pub(crate) fn mod_name(mut self, mod_name: Option<&str>) -> Self {
238 self.mod_name = mod_name.map(|s| s.to_string());
239 self
240 }
241
242 pub(crate) fn rust_edition(mut self, rust_edition: RustEdition) -> Self {
243 self.rust_edition = rust_edition;
244 self
245 }
246 pub(crate) fn visibility(mut self, visibility: Visibility) -> Self {
247 self.visibility = visibility;
248 self
249 }
250 pub(crate) fn error_on_conflicts(mut self, error_on_conflicts: bool) -> Self {
251 self.error_on_conflicts = error_on_conflicts;
252 self
253 }
254 pub(crate) fn show_warnings(mut self, show_warnings: bool) -> Self {
255 self.show_warnings = show_warnings;
256 self
257 }
258 pub(crate) fn warnings_are_errors(mut self, warnings_are_errors: bool) -> Self {
259 self.warnings_are_errors = warnings_are_errors;
260 self
261 }
262}
263
264impl<'a, LexerTypesT> ParserSrcEnv<'a, LexerTypesT>
265where
266 LexerTypesT: LexerTypes,
267 usize: num_traits::AsPrimitive<LexerTypesT::StorageT>,
268{
269 pub(crate) fn new_with_header(
270 src: &'a str,
271 path: Option<&Path>,
272 header: Header<Location>,
273 ) -> ParserSrcEnv<'a, LexerTypesT> {
274 let fallback_modname = if let Some(path) = path {
275 let mut stem = path.to_str().unwrap();
280 loop {
281 let new_stem = Path::new(stem).file_stem().unwrap().to_str().unwrap();
282 if stem == new_stem {
283 break;
284 }
285 stem = new_stem;
286 }
287 Some(format!("{}_y", stem))
288 } else {
289 None
290 };
291 let grammar_path_cache_entry = path.map(|s| s.to_string_lossy().to_string());
292 ParserSrcEnv {
293 src,
294 fallback_modname,
295 grammar_path_cache_entry,
296 header,
297 phantom: PhantomData,
298 }
299 }
300
301 fn merge_headers(&mut self) -> Result<(), ParserSrcEnvError> {
302 let (parsed_header, _) = self.parse_header()?;
303 Ok(self.header.merge_from(parsed_header)?)
304 }
305
306 fn parse_header(&self) -> Result<(Header<Span>, usize), Vec<HeaderError<Span>>> {
307 GrmtoolsSectionParser::new(self.src, false).parse()
308 }
309
310 fn resolve_ast_with_validity_info(
313 &mut self,
314 from_ast: Option<&ASTWithValidityInfo>,
315 ) -> Result<ASTWithValidityInfo, ParserSrcEnvError> {
316 self.header.mark_used(&"cfgrammar.yacckind".to_string());
317 if let Some(ast) = from_ast {
318 Ok(ast.clone())
319 } else if let Some(yk) = self
320 .header
321 .get("cfgrammar.yacckind")
322 .map(|HeaderValue(_, val)| val)
323 .map(YaccKind::try_from)
324 .transpose()?
325 {
326 Ok(ASTWithValidityInfo::new(yk, self.src))
327 } else {
328 Err(ParserSrcEnvError::MissingYaccKind)?
329 }
330 }
331
332 fn resolve_recoverer(&mut self) -> Result<RecoveryKind, ParserSrcEnvError> {
335 self.header.mark_used(&"lrpar.recoverer".to_string());
336 let rk_val = self
337 .header
338 .get("lrpar.recoverer")
339 .map(|HeaderValue(_, rk_val)| rk_val);
340 if let Some(rk_val) = rk_val {
341 Ok(RecoveryKind::try_from(rk_val)?)
342 } else {
343 Ok(RecoveryKind::CPCTPlus)
345 }
346 }
347
348 fn resolve_serialisation_format(&mut self) -> Result<SerialisationFormat, ParserSrcEnvError> {
351 self.header
352 .mark_used(&"lrpar.serialisation_format".to_string());
353 if let Some(ec_val) = self
354 .header
355 .get("lrpar.serialisation_format")
356 .map(|HeaderValue(_, ec_val)| ec_val)
357 {
358 Ok(SerialisationFormat::try_from(ec_val)?)
359 } else {
360 Ok(SerialisationFormat::VariableSizedInteger)
361 }
362 }
363
364 fn resolve_mod_name(&self, args: &ParserBuildEnvArgs) -> Result<String, ParserSrcEnvError> {
367 match &args.mod_name {
368 Some(s) => Ok(s.to_owned()),
369 None => self
370 .fallback_modname
371 .as_ref()
372 .ok_or(ParserSrcEnvError::MissingModName)
373 .map(|s| s.to_string()),
374 }
375 }
376
377 pub(crate) fn build_env(
378 mut self,
379 args: ParserBuildEnvArgs<'a>,
380 ) -> Result<ParserBuildEnv<'a, LexerTypesT>, ParserSrcEnvError>
381 where
382 LexerTypesT: LexerTypes,
383 usize: num_traits::AsPrimitive<LexerTypesT::StorageT>,
384 {
385 self.merge_headers()?;
386 let ast_with_validity_info =
387 self.resolve_ast_with_validity_info(args.ast_with_validity_info)?;
388 let recoverer = self.resolve_recoverer()?;
389 let serialisation_format = self.resolve_serialisation_format()?;
390 let mod_name = self.resolve_mod_name(&args)?;
391 let grammar_path = self.grammar_path_cache_entry;
392
393 Ok(ParserBuildEnv {
394 ast_with_validity_info,
395 cache_args: args,
396 recoverer,
397 serialisation_format,
398 mod_name,
399 grammar_path,
400 header: self.header,
401 phantom_storaget: PhantomData,
402 })
403 }
404}
405
406impl<'a, LexerTypesT> ParserBuildEnv<'a, LexerTypesT>
407where
408 LexerTypesT: LexerTypes,
409 usize: num_traits::AsPrimitive<LexerTypesT::StorageT>,
410{
411 pub(crate) fn ast_with_validity_info(&self) -> &ASTWithValidityInfo {
412 &self.ast_with_validity_info
413 }
414
415 pub(crate) fn header_mut(&mut self) -> &mut Header<Location> {
416 &mut self.header
417 }
418
419 pub(crate) fn serialisation_format(&self) -> &SerialisationFormat {
420 &self.serialisation_format
421 }
422
423 pub(crate) fn derived_mod_name(&self) -> &str {
424 &self.mod_name
425 }
426
427 pub(crate) fn specified_mod_name(&self) -> Option<&str> {
428 self.cache_args.mod_name.as_deref()
429 }
430
431 pub(crate) fn recoverer(&self) -> RecoveryKind {
432 self.recoverer
433 }
434
435 pub(crate) fn rust_edition(&self) -> RustEdition {
436 self.cache_args.rust_edition
437 }
438
439 pub(crate) fn visibility(&self) -> &Visibility {
440 &self.cache_args.visibility
441 }
442
443 pub(crate) fn show_warnings(&self) -> bool {
444 self.cache_args.show_warnings
445 }
446
447 pub(crate) fn warnings_are_errors(&self) -> bool {
448 self.cache_args.warnings_are_errors
449 }
450
451 pub(crate) fn error_on_conflicts(&self) -> bool {
452 self.cache_args.error_on_conflicts
453 }
454
455 pub(crate) fn yacc_kind(&self) -> YaccKind {
456 self.ast_with_validity_info.yacc_kind()
457 }
458
459 pub(crate) fn check_unused_header_keys(&self) -> Result<(), ParserBuildEnvError<LexerTypesT>> {
460 let unused_keys = self.header.unused();
461 if !unused_keys.is_empty() {
462 return Err(ParserBuildEnvError::GrmtoolsSectionUnusedKeys(unused_keys));
463 }
464 let missing_keys = self
465 .header
466 .missing()
467 .iter()
468 .map(|s| s.to_string())
469 .collect::<Vec<_>>();
470 if !missing_keys.is_empty() {
471 Err(ParserBuildEnvError::GrmtoolsSectionMissingRequiredKeys(
472 missing_keys,
473 ))
474 } else {
475 Ok(())
476 }
477 }
478
479 pub(crate) fn code_generator(
480 &self,
481 timestamp: &str,
482 ) -> Result<ParserCodegen<LexerTypesT>, ParserBuildEnvError<LexerTypesT>> {
483 let grm = YaccGrammar::<LexerTypesT::StorageT>::new_from_ast_with_validity_info(
484 &self.ast_with_validity_info,
485 )?;
486 let (sgraph, stable) = from_yacc(&grm, Minimiser::Pager)?;
487 Ok(ParserCodegen {
488 grm,
489 stable,
490 sgraph,
491 timestamp: timestamp.to_string(),
492 })
493 }
494}
495
496impl<LexerTypesT> ParserCodegen<LexerTypesT>
497where
498 LexerTypesT: LexerTypes,
499 usize: num_traits::AsPrimitive<LexerTypesT::StorageT>,
500 LexerTypesT::StorageT: 'static
501 + fmt::Debug
502 + Hash
503 + num_traits::PrimInt
504 + SchemaWrite<FixIntConfig, Src = LexerTypesT::StorageT>
505 + SchemaWrite<VarIntConfig, Src = LexerTypesT::StorageT>
506 + num_traits::Unsigned,
507 LexerTypesT: LexerTypes,
508{
509 pub(crate) fn grm(&self) -> &YaccGrammar<LexerTypesT::StorageT> {
510 &self.grm
511 }
512
513 pub(crate) fn stable(&self) -> &StateTable<LexerTypesT::StorageT> {
514 &self.stable
515 }
516
517 pub(crate) fn sgraph(&self) -> &StateGraph<LexerTypesT::StorageT> {
518 &self.sgraph
519 }
520
521 pub(crate) fn finish(
522 self,
523 ) -> (
524 YaccGrammar<LexerTypesT::StorageT>,
525 StateGraph<LexerTypesT::StorageT>,
526 StateTable<LexerTypesT::StorageT>,
527 ) {
528 (self.grm, self.sgraph, self.stable)
529 }
530
531 pub(crate) fn generate(
532 &self,
533 build_env: &ParserBuildEnv<LexerTypesT>,
534 ) -> Result<String, CodegenError> {
535 let mod_name = build_env.derived_mod_name();
536 let visibility = build_env.visibility();
537 let user_actions = if let YaccKind::Original(YaccOriginalActionKind::UserAction)
538 | YaccKind::Grmtools = build_env.yacc_kind()
539 {
540 Some(self.gen_user_actions()?)
541 } else {
542 None
543 };
544 let rule_consts = self.gen_rule_consts()?;
545 let token_epp = self.gen_token_epp()?;
546 let parse_function = self.gen_parse_function(build_env)?;
547 let action_wrappers = match build_env.yacc_kind() {
548 YaccKind::Original(YaccOriginalActionKind::UserAction) | YaccKind::Grmtools => {
549 Some(self.gen_wrappers(build_env)?)
550 }
551 YaccKind::Original(YaccOriginalActionKind::NoAction)
552 | YaccKind::Original(YaccOriginalActionKind::GenericParseTree) => None,
553 _ => unreachable!(),
554 };
555
556 let additional_decls = if let YaccKind::Original(YaccOriginalActionKind::GenericParseTree) =
557 build_env.yacc_kind()
558 {
559 Some(quote! {
562 #[allow(unused_imports)]
563 pub use ::lrpar::parser::_deprecated_moved_::Node;
564 })
565 } else {
566 None
567 };
568
569 let mod_name = match syn::parse_str::<proc_macro2::Ident>(mod_name) {
570 Ok(s) => s,
571 Err(e) => {
572 return Err(CodegenError::InvalidRustIdentifierModName(
573 e,
574 mod_name.to_string(),
575 ));
576 }
577 };
578 let out_tokens = quote! {
579 #visibility mod #mod_name {
580 #user_actions
582 mod _parser_ {
583 #![allow(clippy::type_complexity)]
584 #![allow(clippy::unnecessary_wraps)]
585 #![deny(unsafe_code)]
586 #[allow(unused_imports)]
587 use super::*;
588 #additional_decls
589 #parse_function
590 #rule_consts
591 #token_epp
592 #action_wrappers
593 } #[allow(unused_imports)]
595 pub use _parser_::*;
596 #[allow(unused_imports)]
597 use ::lrpar::Lexeme;
598 } };
600 let unformatted = out_tokens.to_string();
602 Ok(syn::parse_str(&unformatted)
603 .map(|syntax_tree| prettyplease::unparse(&syntax_tree))
604 .unwrap_or(unformatted))
605 }
606
607 fn gen_cache(&self, build_env: &ParserBuildEnv<LexerTypesT>) -> TokenStream {
610 let grm = self.grm();
611 let build_time = &self.timestamp;
612 let grammar_path = &build_env.grammar_path;
613 let mod_name = QuoteOption(build_env.specified_mod_name());
614 let visibility = build_env.visibility().to_variant_tokens();
615 let rust_edition = build_env.rust_edition().to_variant_tokens();
616 let yacckind = build_env.yacc_kind();
617 let rule_map = grm
618 .iter_tidxs()
619 .map(|tidx| {
620 QuoteTuple((
621 usize::from(tidx),
622 grm.token_name(tidx).unwrap_or("<unknown>"),
623 ))
624 })
625 .collect::<Vec<_>>();
626 let derived_mod_name = build_env.derived_mod_name();
627 let serialisation_format = build_env.serialisation_format();
628 let recoverer = build_env.recoverer();
629 let error_on_conflicts = build_env.error_on_conflicts();
630 let show_warnings = build_env.show_warnings();
631 let warnings_are_errors = build_env.warnings_are_errors();
632 let cache_info = quote! {
633 BUILD_TIME = #build_time
634 DERIVED_MOD_NAME = #derived_mod_name
635 ENCODING_CONFIG = #serialisation_format
636 GRAMMAR_PATH = #grammar_path
637 MOD_NAME = #mod_name
638 RECOVERER = #recoverer
639 YACC_KIND = #yacckind
640 ERROR_ON_CONFLICTS = #error_on_conflicts
641 SHOW_WARNINGS = #show_warnings
642 WARNINGS_ARE_ERRORS = #warnings_are_errors
643 RUST_EDITION = #rust_edition
644 RULE_IDS_MAP = [#(#rule_map,)*]
645 VISIBILITY = #visibility
646 };
647 let cache_info_str = cache_info.to_string();
648 quote!(#cache_info_str)
649 }
650
651 pub(crate) fn cache_str(&self, build_env: &ParserBuildEnv<LexerTypesT>) -> String {
652 self.gen_cache(build_env).to_string()
653 }
654
655 fn gen_user_actions(&self) -> Result<TokenStream, CodegenError> {
657 let grm = self.grm();
658 let programs = grm
659 .programs()
660 .as_ref()
661 .map(|s| str::parse::<TokenStream>(s))
662 .transpose()?;
663 let mut action_fns = TokenStream::new();
664 let parsed_parse_generics = make_generics(grm.parse_generics().as_deref())?;
666 let (generics, _, where_clause) = parsed_parse_generics.split_for_impl();
667 let (parse_paramname, parse_paramdef, parse_param_unit);
668 match grm.parse_param() {
669 Some((name, tyname)) => {
670 parse_param_unit = tyname.trim() == "()";
671 parse_paramname = str::parse::<TokenStream>(name)?;
672 let ty = str::parse::<TokenStream>(tyname)?;
673 parse_paramdef = quote!(#parse_paramname: #ty);
674 }
675 None => {
676 parse_param_unit = true;
677 parse_paramname = quote!(());
678 parse_paramdef = quote! {_: ()};
679 }
680 };
681 for pidx in grm.iter_pidxs() {
682 if pidx == grm.start_prod() {
683 continue;
684 }
685
686 let mut args = Vec::with_capacity(grm.prod(pidx).len());
688 for i in 0..grm.prod(pidx).len() {
689 let argt = match grm.prod(pidx)[i] {
690 Symbol::Rule(ref_ridx) => {
691 let action_type = grm.actiontype(ref_ridx)
692 .as_ref()
693 .expect("actiontype should have been checked during complete_and_validate for this YaccKind");
694 str::parse::<TokenStream>(action_type)?
695 }
696 Symbol::Token(_) => {
697 let lexemet =
698 str::parse::<TokenStream>(type_name::<LexerTypesT::LexemeT>())?;
699 quote!(::std::result::Result<#lexemet, #lexemet>)
700 }
701 };
702 let arg = format_ident!("{}arg_{}", ACTION_PREFIX, i + 1);
703 args.push(quote!(mut #arg: #argt));
704 }
705
706 let returnt = {
710 let actiont = grm.actiontype(grm.prod_to_rule(pidx)).as_ref().unwrap();
711 if actiont == "()" {
712 None
713 } else {
714 let actiont = str::parse::<TokenStream>(actiont)?;
715 Some(quote!( -> #actiont))
716 }
717 };
718 let action_fn = format_ident!("{}action_{}", ACTION_PREFIX, usize::from(pidx));
719 let lexer_var = format_ident!("{}lexer", ACTION_PREFIX);
720 let span_var = format_ident!("{}span", ACTION_PREFIX);
721 let ridx_var = format_ident!("{}ridx", ACTION_PREFIX);
722 let storaget = str::parse::<TokenStream>(type_name::<LexerTypesT::StorageT>())?;
723 let lexertypest = str::parse::<TokenStream>(type_name::<LexerTypesT>())?;
724 let bind_parse_param = if !parse_param_unit {
725 Some(quote! {let _ = #parse_paramname;})
726 } else {
727 None
728 };
729
730 let pre_action = grm.action(pidx).as_ref().expect("action code should have been checked during complete_and_validate for this YaccKind");
733 let mut last = 0;
734 let mut outs = String::new();
735 loop {
736 match pre_action[last..].find('$') {
737 Some(off) => {
738 if pre_action[last + off..].starts_with("$$") {
739 outs.push_str(&pre_action[last..last + off + "$".len()]);
740 last = last + off + "$$".len();
741 } else if pre_action[last + off..].starts_with("$lexer") {
742 outs.push_str(&pre_action[last..last + off]);
743 write!(outs, "{prefix}lexer", prefix = ACTION_PREFIX).ok();
744 last = last + off + "$lexer".len();
745 } else if pre_action[last + off..].starts_with("$span") {
746 outs.push_str(&pre_action[last..last + off]);
747 write!(outs, "{prefix}span", prefix = ACTION_PREFIX).ok();
748 last = last + off + "$span".len();
749 } else if last + off + 1 < pre_action.len()
750 && pre_action[last + off + 1..].starts_with(|c: char| c.is_numeric())
751 {
752 outs.push_str(&pre_action[last..last + off]);
753 write!(outs, "{prefix}arg_", prefix = ACTION_PREFIX).ok();
754 last = last + off + "$".len();
755 } else {
756 unreachable!("action variables checked during complete_and_validate");
757 }
758 }
759 None => {
760 outs.push_str(&pre_action[last..]);
761 break;
762 }
763 }
764 }
765
766 let action_body = str::parse::<TokenStream>(&outs)?;
767 action_fns.extend(quote! {
768 #[allow(clippy::too_many_arguments)]
769 fn #action_fn #generics (
770 #ridx_var: ::cfgrammar::RIdx<#storaget>,
771 #lexer_var: &'lexer dyn ::lrpar::NonStreamingLexer<'input, #lexertypest>,
772 #span_var: ::cfgrammar::Span,
773 #parse_paramdef,
774 #(#args,)*
775 ) #returnt
776 #where_clause
777 {
778 #bind_parse_param
779 #action_body
780 }
781 })
782 }
783 Ok(quote! {
784 #programs
785 #action_fns
786 })
787 }
788
789 fn gen_rule_consts(&self) -> Result<TokenStream, proc_macro2::LexError> {
790 let grm = self.grm();
791 let mut toks = TokenStream::new();
792 for ridx in grm.iter_rules() {
793 if !grm.rule_to_prods(ridx).contains(&grm.start_prod()) {
794 let r_const = format_ident!("R_{}", grm.rule_name_str(ridx).to_ascii_uppercase());
795 let storage_ty = str::parse::<TokenStream>(type_name::<LexerTypesT::StorageT>())?;
796 let ridx = UnsuffixedUsize(usize::from(ridx));
797 toks.extend(quote! {
798 #[allow(dead_code)]
799 pub const #r_const: #storage_ty = #ridx;
800 });
801 }
802 }
803 Ok(toks)
804 }
805
806 fn gen_token_epp(&self) -> Result<TokenStream, proc_macro2::LexError> {
807 let grm = self.grm();
808 let mut tidxs = Vec::new();
809 for tidx in grm.iter_tidxs() {
810 tidxs.push(QuoteOption(grm.token_epp(tidx)));
811 }
812 let const_epp_ident = format_ident!("{}EPP", GLOBAL_PREFIX);
813 let storage_ty = str::parse::<TokenStream>(type_name::<LexerTypesT::StorageT>())?;
814 Ok(quote! {
815 const #const_epp_ident: &[::std::option::Option<&str>] = &[
816 #(#tidxs,)*
817 ];
818
819 #[allow(dead_code)]
822 pub fn token_epp<'a>(tidx: ::cfgrammar::TIdx<#storage_ty>) -> ::std::option::Option<&'a str> {
823 #const_epp_ident[usize::from(tidx)]
824 }
825 })
826 }
827
828 fn gen_parse_function(
830 &self,
831 build_env: &ParserBuildEnv<LexerTypesT>,
832 ) -> Result<TokenStream, CodegenError> {
833 let stable = self.stable();
834 let grm = self.grm();
835 let storaget = str::parse::<TokenStream>(type_name::<LexerTypesT::StorageT>())?;
836 let lexertypest = str::parse::<TokenStream>(type_name::<LexerTypesT>())?;
837 let recoverer = build_env.recoverer();
838 let run_parser = match build_env.yacc_kind() {
839 YaccKind::Original(YaccOriginalActionKind::GenericParseTree) => {
840 quote! {
841 ::lrpar::RTParserBuilder::new(grm, stable)
842 .recoverer(#recoverer)
843 .parse_map(
844 lexer,
845 &|lexeme| Node::Term{lexeme},
846 &|ridx, nodes| Node::Nonterm{ridx, nodes}
847 )
848 }
849 }
850 YaccKind::Original(YaccOriginalActionKind::NoAction) => {
851 quote! {
852 ::lrpar::RTParserBuilder::new(grm, stable)
853 .recoverer(#recoverer)
854 .parse_map(lexer, &|_| (), &|_, _| ()).1
855 }
856 }
857 YaccKind::Original(YaccOriginalActionKind::UserAction) | YaccKind::Grmtools => {
858 let actionskind = str::parse::<TokenStream>(ACTIONS_KIND)?;
859 let parsed_parse_generics = make_generics(grm.parse_generics().as_deref())?;
860 let (_, type_generics, _) = parsed_parse_generics.split_for_impl();
861 let (action_fn_parse_param, action_fn_parse_param_ty) = match grm.parse_param() {
864 Some((name, ty)) => {
865 let name = str::parse::<TokenStream>(name)?;
866 let ty = str::parse::<TokenStream>(ty)?;
867 (quote!(#name), quote!(#ty))
868 }
869 None => (quote!(()), quote!(())),
870 };
871 let wrappers = grm.iter_pidxs().map(|pidx| {
872 let pidx = usize::from(pidx);
873 format_ident!("{}wrapper_{}", ACTION_PREFIX, pidx)
874 });
875 let edition_lifetime = if build_env.rust_edition() != RustEdition::Rust2015 {
876 quote!('_,)
877 } else {
878 quote!()
879 };
880 let ridx = usize::from(self.user_start_ridx());
881 let action_ident = format_ident!("{}{}", ACTIONS_KIND_PREFIX, ridx);
882
883 quote! {
884 let actions: ::std::vec::Vec<
885 &dyn Fn(
886 ::cfgrammar::RIdx<#storaget>,
887 &'lexer dyn ::lrpar::NonStreamingLexer<'input, #lexertypest>,
888 ::cfgrammar::Span,
889 ::std::vec::Drain<#edition_lifetime ::lrpar::parser::AStackType<<#lexertypest as ::lrpar::LexerTypes>::LexemeT, #actionskind #type_generics>>,
890 #action_fn_parse_param_ty
891 ) -> #actionskind #type_generics
892 > = ::std::vec![#(&#wrappers,)*];
893 match ::lrpar::RTParserBuilder::new(grm, stable)
894 .recoverer(#recoverer)
895 .parse_actions(lexer, &actions, #action_fn_parse_param) {
896 (Some(#actionskind::#action_ident(x)), y) => (Some(x), y),
897 (None, y) => (None, y),
898 _ => unreachable!()
899 }
900 }
901 }
902 kind => panic!("YaccKind {:?} not supported", kind),
903 };
904
905 let parsed_parse_generics: Generics = match build_env.yacc_kind() {
906 YaccKind::Original(YaccOriginalActionKind::UserAction) | YaccKind::Grmtools => {
907 make_generics(grm.parse_generics().as_deref())?
908 }
909 _ => make_generics(None)?,
910 };
911 let (generics, _, where_clause) = parsed_parse_generics.split_for_impl();
912
913 let parse_fn_parse_param = match build_env.yacc_kind() {
915 YaccKind::Original(YaccOriginalActionKind::UserAction) | YaccKind::Grmtools => {
916 if let Some((name, tyname)) = grm.parse_param() {
917 let name = str::parse::<TokenStream>(name)?;
918 let tyname = str::parse::<TokenStream>(tyname)?;
919 Some(quote! {#name: #tyname})
920 } else {
921 None
922 }
923 }
924 _ => None,
925 };
926 let parse_fn_return_ty = match build_env.yacc_kind() {
927 YaccKind::Original(YaccOriginalActionKind::UserAction) | YaccKind::Grmtools => {
928 let actiont = grm
929 .actiontype(self.user_start_ridx())
930 .as_ref()
931 .map(|at| str::parse::<TokenStream>(at))
932 .transpose()?;
933 quote! {
934 (::std::option::Option<#actiont>, ::std::vec::Vec<::lrpar::LexParseError<#storaget, #lexertypest>>)
935 }
936 }
937 YaccKind::Original(YaccOriginalActionKind::GenericParseTree) => quote! {
938 (::std::option::Option<Node<<#lexertypest as ::lrpar::LexerTypes>::LexemeT, #storaget>>,
939 ::std::vec::Vec<::lrpar::LexParseError<#storaget, #lexertypest>>)
940 },
941 YaccKind::Original(YaccOriginalActionKind::NoAction) => quote! {
942 ::std::vec::Vec<::lrpar::LexParseError<#storaget, #lexertypest>>
943 },
944 _ => unreachable!(),
945 };
946
947 let serialisation_format = build_env.serialisation_format();
948 let (grm_data, stable_data): (Vec<u8>, Vec<u8>) = match serialisation_format {
950 SerialisationFormat::FixedSizeInteger => {
951 let config = wincode::config::Configuration::default().with_fixint_encoding();
952 let grm = wincode::config::serialize(grm, config)?;
953 let stable = wincode::config::serialize(stable, config)?;
954 (grm, stable)
955 }
956 SerialisationFormat::VariableSizedInteger => {
957 let config = wincode::config::Configuration::default().with_varint_encoding();
958 let grm = wincode::config::serialize(grm, config)?;
959 let stable = wincode::config::serialize(stable, config)?;
960 (grm, stable)
961 }
962 };
963 let serialisation_format_str = quote!(serialisation_format).to_string();
964 Ok(quote! {
965 const __GRM_DATA: &[u8] = &[#(#grm_data,)*];
966 const __STABLE_DATA: &[u8] = &[#(#stable_data,)*];
967 const __SERIALISATION_FORMAT: ::lrpar::ctbuilder::SerialisationFormat = #serialisation_format;
968
969 fn __lrpar_parser_data() -> &'static ::lrpar::ParserData<#storaget> {
970 static DATA: ::std::sync::OnceLock<::lrpar::ParserData<#storaget>>
971 = ::std::sync::OnceLock::new();
972 DATA.get_or_init(
973 || {
974 match __SERIALISATION_FORMAT {
977 ::lrpar::ctbuilder::SerialisationFormat::FixedSizeInteger => {
978 ::lrpar::ctbuilder::_reconstitute(__GRM_DATA, __STABLE_DATA, ::lrpar::ctbuilder::wincode::config::Configuration::default().with_fixint_encoding())
979 }
980 ::lrpar::ctbuilder::SerialisationFormat::VariableSizedInteger => {
981 ::lrpar::ctbuilder::_reconstitute(__GRM_DATA, __STABLE_DATA, ::lrpar::ctbuilder::wincode::config::Configuration::default().with_varint_encoding())
982 }
983 _ => {
984 panic!("Parser source was generated using unknown `SerialisationFormat`: {:?}", #serialisation_format_str)
985 }
986 }
987 }
988 )
989 }
990
991 #[allow(dead_code)]
992 pub fn parse #generics (
993 lexer: &'lexer dyn ::lrpar::NonStreamingLexer<'input, #lexertypest>,
994 #parse_fn_parse_param
995 ) -> #parse_fn_return_ty
996 #where_clause
997 {
998 let __data = __lrpar_parser_data();
999 let grm = __data.grm();
1000 let stable = __data.stable();
1001 #run_parser
1002 }
1003 })
1004 }
1005
1006 fn gen_wrappers(
1008 &self,
1009 build_env: &ParserBuildEnv<LexerTypesT>,
1010 ) -> Result<TokenStream, CodegenError> {
1011 let grm = self.grm();
1012 let parsed_parse_generics = make_generics(grm.parse_generics().as_deref())?;
1013 let (generics, type_generics, where_clause) = parsed_parse_generics.split_for_impl();
1014
1015 let (parse_paramname, parse_paramdef);
1016 match grm.parse_param() {
1017 Some((name, tyname)) => {
1018 parse_paramname = str::parse::<TokenStream>(name)?;
1019 let ty = str::parse::<TokenStream>(tyname)?;
1020 parse_paramdef = quote!(#parse_paramname: #ty);
1021 }
1022 None => {
1023 parse_paramname = quote!(());
1024 parse_paramdef = quote! {_: ()};
1025 }
1026 };
1027
1028 let mut wrappers = TokenStream::new();
1029 for pidx in grm.iter_pidxs() {
1030 let ridx = grm.prod_to_rule(pidx);
1031
1032 let wrapper_fn = format_ident!("{}wrapper_{}", ACTION_PREFIX, usize::from(pidx));
1036 let ridx_var = format_ident!("{}ridx", ACTION_PREFIX);
1037 let lexer_var = format_ident!("{}lexer", ACTION_PREFIX);
1038 let span_var = format_ident!("{}span", ACTION_PREFIX);
1039 let args_var = format_ident!("{}args", ACTION_PREFIX);
1040 let storaget = str::parse::<TokenStream>(type_name::<LexerTypesT::StorageT>())?;
1041 let lexertypest = str::parse::<TokenStream>(type_name::<LexerTypesT>())?;
1042 let actionskind = str::parse::<TokenStream>(ACTIONS_KIND)?;
1043 let edition_lifetime = if build_env.rust_edition() != RustEdition::Rust2015 {
1044 Some(quote!('_,))
1045 } else {
1046 None
1047 };
1048 let mut wrapper_fn_body = TokenStream::new();
1049 if grm.action(pidx).is_some() {
1050 for i in 0..grm.prod(pidx).len() {
1052 let arg = format_ident!("{}arg_{}", ACTION_PREFIX, i + 1);
1053 wrapper_fn_body.extend(match grm.prod(pidx)[i] {
1054 Symbol::Rule(ref_ridx) => {
1055 let ref_ridx = usize::from(ref_ridx);
1056 let actionvariant = format_ident!("{}{}", ACTIONS_KIND_PREFIX, ref_ridx);
1057 quote! {
1058 #[allow(clippy::let_unit_value)]
1059 let #arg = match #args_var.next().unwrap() {
1060 ::lrpar::parser::AStackType::ActionType(#actionskind::#type_generics::#actionvariant(x)) => x,
1061 _ => unreachable!()
1062 };
1063 }
1064 }
1065 Symbol::Token(_) => {
1066 quote! {
1067 let #arg = match #args_var.next().unwrap() {
1068 ::lrpar::parser::AStackType::Lexeme(l) => {
1069 if l.faulty() {
1070 Err(l)
1071 } else {
1072 Ok(l)
1073 }
1074 },
1075 ::lrpar::parser::AStackType::ActionType(_) => unreachable!()
1076 };
1077 }
1078 }
1079 })
1080 }
1081
1082 let args = (0..grm.prod(pidx).len())
1084 .map(|i| format_ident!("{}arg_{}", ACTION_PREFIX, i + 1))
1085 .collect::<Vec<_>>();
1086 let action_fn = format_ident!("{}action_{}", ACTION_PREFIX, usize::from(pidx));
1087 let actionsvariant = format_ident!("{}{}", ACTIONS_KIND_PREFIX, usize::from(ridx));
1088
1089 wrapper_fn_body.extend(match grm.actiontype(ridx) {
1090 Some(s) if s == "()" => {
1091 quote! {
1095 #action_fn(#ridx_var, #lexer_var, #span_var, #parse_paramname, #(#args,)*);
1096 #actionskind::#type_generics::#actionsvariant(())
1097 }
1098 }
1099 _ => {
1100 quote! {
1101 #actionskind::#type_generics::#actionsvariant(#action_fn(#ridx_var, #lexer_var, #span_var, #parse_paramname, #(#args,)*))
1102 }
1103 }
1104 })
1105 } else if pidx == grm.start_prod() {
1106 wrapper_fn_body.extend(quote!(unreachable!()));
1107 } else {
1108 unreachable!(
1109 "Production in rule '{}' must have an action body, which should have been handled by gen_user_actions.",
1110 grm.rule_name_str(grm.prod_to_rule(pidx))
1111 );
1112 };
1113
1114 let attrib = if pidx == grm.start_prod() {
1115 Some(quote!(#[allow(unused_variables)]))
1117 } else {
1118 None
1119 };
1120 wrappers.extend(quote! {
1121 #attrib
1122 fn #wrapper_fn #generics (
1123 #ridx_var: ::cfgrammar::RIdx<#storaget>,
1124 #lexer_var: &'lexer dyn ::lrpar::NonStreamingLexer<'input, #lexertypest>,
1125 #span_var: ::cfgrammar::Span,
1126 mut #args_var: ::std::vec::Drain<#edition_lifetime ::lrpar::parser::AStackType<<#lexertypest as ::lrpar::LexerTypes>::LexemeT, #actionskind #type_generics>>,
1127 #parse_paramdef
1128 ) -> #actionskind #type_generics
1129 #where_clause
1130 {
1131 #wrapper_fn_body
1132 }
1133 })
1134 }
1135 let mut actionskindvariants = Vec::new();
1136 let actionskindhidden = format_ident!("_{}", ACTIONS_KIND_HIDDEN);
1137 let actionskind = str::parse::<TokenStream>(ACTIONS_KIND).unwrap();
1138 let mut phantom_data_type = Vec::new();
1139 for ridx in grm.iter_rules() {
1140 if let Some(actiont) = grm.actiontype(ridx) {
1141 let actionskindvariant =
1142 format_ident!("{}{}", ACTIONS_KIND_PREFIX, usize::from(ridx));
1143 let actiont = str::parse::<TokenStream>(actiont).unwrap();
1144 actionskindvariants.push(quote! {
1145 #actionskindvariant(#actiont)
1146 })
1147 }
1148 }
1149 for lifetime in parsed_parse_generics.lifetimes() {
1150 let lifetime = &lifetime.lifetime;
1151 phantom_data_type.push(quote! { &#lifetime () });
1152 }
1153 for type_param in parsed_parse_generics.type_params() {
1154 let ident = &type_param.ident;
1155 phantom_data_type.push(quote! { #ident });
1156 }
1157 actionskindvariants.push(quote! {
1158 #actionskindhidden(::std::marker::PhantomData<(#(#phantom_data_type,)*)>)
1159 });
1160 wrappers.extend(quote! {
1161 #[allow(dead_code)]
1162 enum #actionskind #generics #where_clause {
1163 #(#actionskindvariants,)*
1164 }
1165 });
1166 Ok(wrappers)
1167 }
1168
1169 fn user_start_ridx(&self) -> RIdx<LexerTypesT::StorageT> {
1173 let grm = self.grm();
1174 debug_assert_eq!(grm.prod(grm.start_prod()).len(), 1);
1175 match grm.prod(grm.start_prod())[0] {
1176 Symbol::Rule(ridx) => ridx,
1177 _ => unreachable!(),
1178 }
1179 }
1180}
1181
1182struct QuoteOption<T>(Option<T>);
1188
1189impl<T: ToTokens> ToTokens for QuoteOption<T> {
1190 fn to_tokens(&self, tokens: &mut TokenStream) {
1191 tokens.append_all(match self.0 {
1192 Some(ref t) => quote! { ::std::option::Option::Some(#t) },
1193 None => quote! { ::std::option::Option::None },
1194 });
1195 }
1196}
1197
1198struct QuoteTuple<T>(T);
1201
1202impl<A: ToTokens, B: ToTokens> ToTokens for QuoteTuple<(A, B)> {
1203 fn to_tokens(&self, tokens: &mut TokenStream) {
1204 let (a, b) = &self.0;
1205 tokens.append_all(quote!((#a, #b)));
1206 }
1207}
1208
1209struct QuoteToString<'a>(&'a str);
1211
1212impl ToTokens for QuoteToString<'_> {
1213 fn to_tokens(&self, tokens: &mut TokenStream) {
1214 let x = &self.0;
1215 tokens.append_all(quote! { #x.to_string() });
1216 }
1217}
1218
1219struct UnsuffixedUsize(usize);
1224
1225impl ToTokens for UnsuffixedUsize {
1226 fn to_tokens(&self, tokens: &mut TokenStream) {
1227 tokens.append(Literal::usize_unsuffixed(self.0))
1228 }
1229}
1230
1231impl RustEdition {
1232 fn to_variant_tokens(self) -> TokenStream {
1233 match self {
1234 RustEdition::Rust2015 => quote!(::lrpar::RustEdition::Rust2015),
1235 RustEdition::Rust2018 => quote!(::lrpar::RustEdition::Rust2018),
1236 RustEdition::Rust2021 => quote!(::lrpar::RustEdition::Rust2021),
1237 }
1238 }
1239}
1240
1241impl ToTokens for Visibility {
1242 fn to_tokens(&self, tokens: &mut TokenStream) {
1243 tokens.extend(match self {
1244 Visibility::Private => quote!(),
1245 Visibility::Public => quote! {pub},
1246 Visibility::PublicSuper => quote! {pub(super)},
1247 Visibility::PublicSelf => quote! {pub(self)},
1248 Visibility::PublicCrate => quote! {pub(crate)},
1249 Visibility::PublicIn(data) => {
1250 let other = str::parse::<TokenStream>(data).unwrap();
1251 quote! {pub(in #other)}
1252 }
1253 })
1254 }
1255}
1256
1257impl Visibility {
1258 fn to_variant_tokens(&self) -> TokenStream {
1259 match self {
1260 Visibility::Private => quote!(::lrpar::Visibility::Private),
1261 Visibility::Public => quote!(::lrpar::Visibility::Public),
1262 Visibility::PublicSuper => quote!(::lrpar::Visibility::PublicSuper),
1263 Visibility::PublicSelf => quote!(::lrpar::Visibility::PublicSelf),
1264 Visibility::PublicCrate => quote!(::lrpar::Visibility::PublicCrate),
1265 Visibility::PublicIn(data) => {
1266 let data = QuoteToString(data);
1267 quote!(::lrpar::Visibility::PublicIn(#data))
1268 }
1269 }
1270 }
1271}
1272
1273impl ToTokens for SerialisationFormat {
1274 fn to_tokens(&self, tokens: &mut TokenStream) {
1275 tokens.extend(match self {
1276 SerialisationFormat::FixedSizeInteger => {
1277 quote! {::lrpar::ctbuilder::SerialisationFormat::FixedSizeInteger}
1278 }
1279 SerialisationFormat::VariableSizedInteger => {
1280 quote! {::lrpar::ctbuilder::SerialisationFormat::VariableSizedInteger}
1281 }
1282 })
1283 }
1284}
1285
1286pub(crate) fn make_generics(parse_generics: Option<&str>) -> Result<Generics, CodegenError> {
1287 if let Some(parse_generics) = parse_generics {
1288 let tokens = str::parse::<TokenStream>(parse_generics)?;
1289 match syn::parse2(quote!(<'lexer, 'input: 'lexer, #tokens>)) {
1290 Ok(res) => Ok(res),
1291 Err(err) => Err(CodegenError::InvalidParseGenerics(err)),
1292 }
1293 } else {
1294 Ok(parse_quote!(<'lexer, 'input: 'lexer>))
1295 }
1296}