22
33use std:: {
44 any:: type_name,
5- borrow:: Cow ,
65 collections:: { HashMap , HashSet } ,
76 env:: { current_dir, var} ,
87 error:: Error ,
@@ -82,6 +81,27 @@ impl ToTokens for UnsuffixedUsize {
8281 }
8382}
8483
84+ /// This wrapper adds a missing impl of `ToTokens` for tuples.
85+ /// For a tuple `(a, b)` emits `(a.to_tokens(), b.to_tokens())`
86+ struct QuoteTuple < T > ( T ) ;
87+
88+ impl < A : ToTokens , B : ToTokens > ToTokens for QuoteTuple < ( A , B ) > {
89+ fn to_tokens ( & self , tokens : & mut TokenStream ) {
90+ let ( a, b) = & self . 0 ;
91+ tokens. append_all ( quote ! ( ( #a, #b) ) ) ;
92+ }
93+ }
94+
95+ /// The wrapped `&str` value will be emitted with a call to `to_string()`
96+ struct QuoteToString < ' a > ( & ' a str ) ;
97+
98+ impl ToTokens for QuoteToString < ' _ > {
99+ fn to_tokens ( & self , tokens : & mut TokenStream ) {
100+ let x = & self . 0 ;
101+ tokens. append_all ( quote ! { #x. to_string( ) } ) ;
102+ }
103+ }
104+
85105impl < StorageT > fmt:: Display for CTConflictsError < StorageT >
86106where
87107 StorageT : ' static + Debug + Hash + PrimInt + Unsigned ,
@@ -164,16 +184,35 @@ pub enum RustEdition {
164184 Rust2021 ,
165185}
166186
187+ impl ToTokens for Visibility {
188+ fn to_tokens ( & self , tokens : & mut TokenStream ) {
189+ tokens. extend ( match self {
190+ Visibility :: Private => quote ! ( ) ,
191+ Visibility :: Public => quote ! { pub } ,
192+ Visibility :: PublicSuper => quote ! { pub ( super ) } ,
193+ Visibility :: PublicSelf => quote ! { pub ( self ) } ,
194+ Visibility :: PublicCrate => quote ! { pub ( crate ) } ,
195+ Visibility :: PublicIn ( data) => {
196+ let other = str:: parse :: < TokenStream > ( data) . unwrap ( ) ;
197+ quote ! { pub ( in #other) }
198+ }
199+ } )
200+ }
201+ }
202+
167203impl Visibility {
168- fn cow_str ( & self ) -> Cow < ' static , str > {
169- match self {
170- Visibility :: Private => Cow :: from ( "" ) ,
171- Visibility :: Public => Cow :: from ( "pub" ) ,
172- Visibility :: PublicSuper => Cow :: from ( "pub(super)" ) ,
173- Visibility :: PublicSelf => Cow :: from ( "pub(self)" ) ,
174- Visibility :: PublicCrate => Cow :: from ( "pub(crate)" ) ,
175- Visibility :: PublicIn ( data) => Cow :: from ( format ! ( "pub(in {})" , data) ) ,
176- }
204+ fn to_variant_tokens ( & self , tokens : & mut TokenStream ) {
205+ tokens. extend ( match self {
206+ Visibility :: Private => quote ! ( :: lrpar:: Visibility :: Private ) ,
207+ Visibility :: Public => quote ! ( :: lrpar:: Visibility :: Public ) ,
208+ Visibility :: PublicSuper => quote ! ( :: lrpar:: Visibility :: PublicSuper ) ,
209+ Visibility :: PublicSelf => quote ! ( :: lrpar:: Visibility :: PublicSelf ) ,
210+ Visibility :: PublicCrate => quote ! ( :: lrpar:: Visibility :: PublicCrate ) ,
211+ Visibility :: PublicIn ( data) => {
212+ let data = QuoteToString ( data) ;
213+ quote ! ( :: lrpar:: Visibility :: PublicIn ( #data) )
214+ }
215+ } )
177216 }
178217}
179218
@@ -708,7 +747,8 @@ where
708747 cache : & str ,
709748 ) -> Result < ( ) , Box < dyn Error > > {
710749 let mut outs = String :: new ( ) ;
711- writeln ! ( outs, "{} mod {} {{" , self . visibility. cow_str( ) , mod_name) . ok ( ) ;
750+ let visibility = self . visibility . clone ( ) ;
751+ writeln ! ( outs, "{} mod {} {{" , quote!( #visibility) , mod_name) . ok ( ) ;
712752 // Emit user program section, and actions at the top so they may specify inner attributes.
713753 if let Some ( YaccKind :: Original ( YaccOriginalActionKind :: UserAction ) | YaccKind :: Grmtools ) =
714754 self . yacckind
@@ -741,10 +781,10 @@ where
741781 outs. push_str ( " pub use _parser_::*;\n " ) ;
742782 outs. push_str ( " #[allow(unused_imports)]\n " ) ;
743783 outs. push_str ( " use ::lrpar::Lexeme;\n " ) ;
744- outs. push_str ( "} // End of `mod {mod_name}` \n \n " ) ;
745784
746785 // Output the cache so that we can check whether the IDs map is stable.
747786 outs. push_str ( cache) ;
787+ outs. push_str ( "} // End of `mod {mod_name}` \n \n " ) ;
748788
749789 let mut f = File :: create ( outp_rs) ?;
750790 f. write_all ( outs. as_bytes ( ) ) ?;
@@ -757,43 +797,48 @@ where
757797 fn rebuild_cache ( & self , grm : & YaccGrammar < StorageT > ) -> String {
758798 // We don't need to be particularly clever here: we just need to record the various things
759799 // that could change between builds.
760- let mut cache = String :: new ( ) ;
761- cache. push_str ( "\n /* CACHE INFORMATION\n " ) ;
762-
800+ //
763801 // Record the time that this version of lrpar was built. If the source code changes and
764802 // rustc forces a recompile, this will change this value, causing anything which depends on
765803 // this build of lrpar to be recompiled too.
766804 let build_time = env ! ( "VERGEN_BUILD_TIMESTAMP" ) ;
767805 let grammar_path = self . grammar_path . as_ref ( ) . unwrap ( ) . to_string_lossy ( ) ;
768- let mod_name = self . mod_name ;
806+ let mod_name = QuoteOption ( self . mod_name ) ;
769807 let recoverer = self . recoverer ;
770808 let yacckind = self . yacckind ;
771- let visibility = self . visibility . cow_str ( ) ;
809+ let mut visibility = TokenStream :: new ( ) ;
810+ self . visibility . to_variant_tokens ( & mut visibility) ;
772811 let error_on_conflicts = self . error_on_conflicts ;
773- writeln ! ( cache, " Build time: {}" , quote!( #build_time) ) . ok ( ) ;
774- writeln ! ( cache, " Grammar path: {}" , quote!( #grammar_path) ) . ok ( ) ;
775- writeln ! ( cache, " Mod name: {}" , quote!( #mod_name) ) . ok ( ) ;
776- writeln ! ( cache, " Recoverer: {}" , quote!( #recoverer) ) . ok ( ) ;
777- writeln ! ( cache, " YaccKind: {}" , quote!( #yacckind) ) . ok ( ) ;
778- writeln ! ( cache, " Visibility: {}" , quote!( #visibility) ) . ok ( ) ;
779- writeln ! (
780- cache,
781- " Error on conflicts: {}\n " ,
782- quote!( #error_on_conflicts)
783- )
784- . ok ( ) ;
785812
786- // Record the rule IDs map
787- for tidx in grm. iter_tidxs ( ) {
788- let n = match grm. token_name ( tidx) {
789- Some ( n) => format ! ( "'{}'" , n) ,
790- None => "<unknown>" . to_string ( ) ,
791- } ;
792- writeln ! ( cache, " {} {}" , usize :: from( tidx) , n) . ok ( ) ;
793- }
794-
795- cache. push_str ( "*/\n " ) ;
796- cache
813+ let rule_map = grm
814+ . iter_tidxs ( )
815+ . map ( |tidx| {
816+ QuoteTuple ( (
817+ usize:: from ( tidx) ,
818+ grm. token_name ( tidx) . unwrap_or ( "<unknown>" ) ,
819+ ) )
820+ } )
821+ . collect :: < Vec < _ > > ( ) ;
822+ let rule_map_len = rule_map. len ( ) ;
823+ let cache_module = quote ! {
824+ #[ allow( unused) ]
825+ mod _cache_information_ {
826+ use :: lrpar:: { RecoveryKind , Visibility , RustEdition } ;
827+ use :: cfgrammar:: yacc:: YaccKind ;
828+
829+ const BUILD_TIME : & str = #build_time;
830+ const GRAMMAR_PATH : & str = #grammar_path;
831+ const MOD_NAME : Option <& str > = #mod_name;
832+ const RECOVERER : RecoveryKind = #recoverer;
833+ const YACC_KIND : YaccKind = #yacckind;
834+ const ERROR_ON_CONFLICTS : bool = #error_on_conflicts;
835+ const RULE_IDS_MAP : [ ( usize , & str ) ; #rule_map_len] = [ #( #rule_map, ) * ] ;
836+ fn visibility( ) -> Visibility {
837+ #visibility
838+ }
839+ }
840+ } ;
841+ cache_module. to_string ( )
797842 }
798843
799844 /// Generate the main parse() function for the output file.
0 commit comments