Skip to content

Commit 0ebc37c

Browse files
authored
Merge pull request #624 from ratmice/module_identifier_chars
Improve error when `CTParserBuilder::mod_name` is not a valid rust ident
2 parents 3314528 + bab8c60 commit 0ebc37c

2 files changed

Lines changed: 79 additions & 2 deletions

File tree

lrlex/src/lib/ctbuilder.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -753,7 +753,15 @@ where
753753
format!("{}_l", stem)
754754
}
755755
};
756-
let mod_name = format_ident!("{}", mod_name);
756+
let mod_name =
757+
match syn::parse_str::<proc_macro2::Ident>(&mod_name) {
758+
Ok(s) => s,
759+
Err(e) => return Err(format!(
760+
"CTLexerBuilder::mod_name(\"{}\") is not a valid rust identifier due to '{}'",
761+
mod_name, e
762+
)
763+
.into()),
764+
};
757765
let mut lexerdef_func_impl = {
758766
let LexFlags {
759767
allow_wholeline_comments,
@@ -1488,4 +1496,34 @@ mod test {
14881496
.unwrap();
14891497
}
14901498
}
1499+
1500+
#[test]
1501+
/// Tests a yacc .y filename containing a dash character leading to an invalid rust identifier
1502+
/// when that dash is subsequently used as the default `CTParserBuilder::mod_name`.
1503+
fn test_invalid_identifier_in_derived_mod_name() {
1504+
let mut lex_path = std::path::PathBuf::from(env!("OUT_DIR"));
1505+
lex_path.push("contains-a-dash.l");
1506+
let mut f = File::create(&lex_path).unwrap();
1507+
let _ = f.write_all(
1508+
r#"
1509+
%%
1510+
A "A"
1511+
"#
1512+
.as_bytes(),
1513+
);
1514+
match CTLexerBuilder::new()
1515+
.output_path(format!("{}.rs", lex_path.display()))
1516+
.lexer_path(lex_path.clone())
1517+
.build()
1518+
{
1519+
Ok(_) => panic!("Expected error"),
1520+
Err(e) => {
1521+
let err_string = e.to_string();
1522+
assert_eq!(
1523+
err_string,
1524+
"CTLexerBuilder::mod_name(\"contains-a-dash_l\") is not a valid rust identifier due to 'unexpected token'"
1525+
);
1526+
}
1527+
}
1528+
}
14911529
}

lrpar/src/lib/ctbuilder.rs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)