diff --git a/.gitignore b/.gitignore index cbfe708..f1ec226 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ doc/whitespace/src/parser.rs lalrpop-test/src/error.rs lalrpop-test/src/error_issue_113.rs lalrpop-test/src/error_issue_278.rs +lalrpop-test/src/error_issue_261.rs lalrpop-test/src/error_recovery.rs lalrpop-test/src/error_recovery_pull_182.rs lalrpop-test/src/error_recovery_issue_240.rs diff --git a/lalrpop-test/src/error_issue_261.lalrpop b/lalrpop-test/src/error_issue_261.lalrpop new file mode 100644 index 0000000..54e4aae --- /dev/null +++ b/lalrpop-test/src/error_issue_261.lalrpop @@ -0,0 +1,25 @@ +use std::str::FromStr; +use lalrpop_util::ParseError; + +grammar; + +extern { + type Error = &'static str; +} + +pub Value: f64 = { + => n, + => n as f64, +}; + + +Int: u64 = r"\d+" + =>? u64::from_str(<>).map_err(|_| ParseError::User{ error: "invalid int" }); +Float: f64 = r"\d+(\.\d+)?(e-?\d+)?" + =>? f64::from_str(<>).map_err(|_| ParseError::User{ error: "invalid float" }); + +match { + r"\d+(\.\d+)?(e-?\d+)?" +} else { + _ +} diff --git a/lalrpop/src/normalize/prevalidate/mod.rs b/lalrpop/src/normalize/prevalidate/mod.rs index 5ddce7e..5bbab6f 100644 --- a/lalrpop/src/normalize/prevalidate/mod.rs +++ b/lalrpop/src/normalize/prevalidate/mod.rs @@ -66,11 +66,13 @@ impl<'grammar> Validator<'grammar> { "multiple match definitions are not permitted"); } - // We may want to allow a limited extern to coexist with match in the future + // Only error if a custom lexer is specified, having a custom types is ok if let Some(d) = self.extern_token { - return_err!( - d.span, - "extern and match definitions are mutually exclusive"); + if d.enum_token.is_some() { + return_err!( + d.span, + "extern (with custom tokens) and match definitions are mutually exclusive"); + } } // Ensure that the catch all is final item of final block @@ -94,11 +96,13 @@ impl<'grammar> Validator<'grammar> { "multiple extern definitions are not permitted"); } - // We may want to allow a limited extern to coexist with match in the future + // Only error if a custom lexer is specified, having a custom types is ok if let Some(d) = self.match_token { - return_err!( - d.span, - "match and extern definitions are mutually exclusive"); + if data.enum_token.is_some() { + return_err!( + d.span, + "match and extern (with custom tokens) definitions are mutually exclusive"); + } } let allowed_names = vec![intern(LOCATION), intern(ERROR)]; diff --git a/lalrpop/src/normalize/prevalidate/test.rs b/lalrpop/src/normalize/prevalidate/test.rs index 95e78d2..cce2d00 100644 --- a/lalrpop/src/normalize/prevalidate/test.rs +++ b/lalrpop/src/normalize/prevalidate/test.rs @@ -82,7 +82,7 @@ fn multiple_match_token() { #[test] fn match_after_extern_token() { check_err( - r#"match and extern definitions are mutually exclusive"#, + r#"match and extern \(with custom tokens\) definitions are mutually exclusive"#, r#"grammar; extern { enum Tok { } } match { _ }"#, r#" ~~~~~ "#); } @@ -90,7 +90,7 @@ fn match_after_extern_token() { #[test] fn extern_after_match_token() { check_err( - r#"extern and match definitions are mutually exclusive"#, + r#"extern \(with custom tokens\) and match definitions are mutually exclusive"#, r#"grammar; match { _ } extern { enum Tok { } }"#, r#" ~~~~~~ "#); }