@@ -973,7 +973,15 @@ where
973973 None
974974 } ;
975975
976- let mod_name = format_ident ! ( "{}" , mod_name) ;
976+ let mod_name =
977+ match syn:: parse_str :: < proc_macro2:: Ident > ( mod_name) {
978+ Ok ( s) => s,
979+ Err ( e) => return Err ( format ! (
980+ "CTParserBuilder::mod_name(\" {}\" ) is not a valid rust identifier due to '{}'" ,
981+ mod_name, e
982+ )
983+ . into ( ) ) ,
984+ } ;
977985 let out_tokens = quote ! {
978986 #visibility mod #mod_name {
979987 // At the top so that `user_actions` may contain #![inner_attribute]
@@ -1801,6 +1809,37 @@ C : 'a';"
18011809 }
18021810 }
18031811
1812+ #[ test]
1813+ /// Tests a yacc .y filename containing a dash character leading to an invalid rust identifier
1814+ /// when that dash is subsequently used as the default `CTParserBuilder::mod_name`.
1815+ fn test_invalid_identifier_in_derived_mod_name ( ) {
1816+ let temp = TempDir :: new ( ) . unwrap ( ) ;
1817+ let mut file_path = PathBuf :: from ( temp. as_ref ( ) ) ;
1818+ file_path. push ( "contains-a-dash.y" ) ;
1819+ let mut f = File :: create ( & file_path) . unwrap ( ) ;
1820+ let _ = f. write_all (
1821+ "%start A
1822+ %%
1823+ A : 'a';"
1824+ . as_bytes ( ) ,
1825+ ) ;
1826+ match CTParserBuilder :: < TestLexerTypes > :: new ( )
1827+ . yacckind ( YaccKind :: Original ( YaccOriginalActionKind :: GenericParseTree ) )
1828+ . grammar_path ( file_path. to_str ( ) . unwrap ( ) )
1829+ . output_path ( file_path. with_extension ( "ignored" ) )
1830+ . build ( )
1831+ {
1832+ Ok ( _) => panic ! ( "Expected error" ) ,
1833+ Err ( e) => {
1834+ let err_string = e. to_string ( ) ;
1835+ assert_eq ! (
1836+ err_string,
1837+ "CTParserBuilder::mod_name(\" contains-a-dash_y\" ) is not a valid rust identifier due to 'unexpected token'"
1838+ ) ;
1839+ }
1840+ }
1841+ }
1842+
18041843 #[ cfg( test) ]
18051844 #[ test]
18061845 fn test_recoverer_header ( ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
0 commit comments