Add granular errors regarding numeric literal parsing

This commit is contained in:
ayazhafiz 2022-02-01 00:18:42 -05:00
parent f55e767035
commit 17c5fe0bff
4 changed files with 197 additions and 16 deletions

View file

@ -152,7 +152,9 @@ fn chomp_number_base<'a>(
},
new,
)),
Some(NumWidth::Float(_)) => Err((Progress::MadeProgress, ENumber::End, state)),
Some(NumWidth::Float(_)) => {
Err((Progress::MadeProgress, ENumber::IntHasFloatSuffix, state))
}
}
}
@ -201,7 +203,9 @@ fn chomp_number_dec<'a>(
NumLiteral::Int(string, NumericBound::Exact(iw)),
new,
)),
(true, Some(NumWidth::Int(_))) => Err((Progress::MadeProgress, ENumber::End, state)),
(true, Some(NumWidth::Int(_))) => {
Err((Progress::MadeProgress, ENumber::FloatHasIntSuffix, state))
}
}
}
@ -282,6 +286,20 @@ fn chomp_number<'a>(
return Err((Progress::NoProgress, ENumber::End, state));
}
if bytes
.get(0)
.copied()
.unwrap_or_default()
.is_ascii_alphabetic()
{
// The user likely mistyped a literal suffix type here.
return Err((
Progress::MadeProgress,
ENumber::LiteralSuffix,
state.advance(start_bytes_len - bytes.len()),
));
}
return Err((Progress::MadeProgress, ENumber::End, state));
}
}

View file

@ -338,6 +338,9 @@ pub enum EExpr<'a> {
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ENumber {
End,
LiteralSuffix,
IntHasFloatSuffix,
FloatHasIntSuffix,
}
#[derive(Debug, Clone, PartialEq, Eq)]

View file

@ -522,6 +522,15 @@ fn to_expr_report<'a>(
&EExpr::Number(ENumber::End, pos) => {
to_malformed_number_literal_report(alloc, lines, filename, pos)
}
&EExpr::Number(ENumber::LiteralSuffix, pos) => {
to_number_literal_with_bad_suffix_report(alloc, lines, filename, pos)
}
&EExpr::Number(ENumber::IntHasFloatSuffix, pos) => {
to_number_literal_mismatch_suffix(alloc, lines, filename, pos, "an integer", "a float")
}
&EExpr::Number(ENumber::FloatHasIntSuffix, pos) => {
to_number_literal_mismatch_suffix(alloc, lines, filename, pos, "a float", "an integer")
}
_ => todo!("unhandled parse error: {:?}", parse_problem),
}
@ -1561,6 +1570,15 @@ fn to_pattern_report<'a>(
&EPattern::NumLiteral(ENumber::End, pos) => {
to_malformed_number_literal_report(alloc, lines, filename, pos)
}
&EPattern::NumLiteral(ENumber::LiteralSuffix, pos) => {
to_number_literal_with_bad_suffix_report(alloc, lines, filename, pos)
}
&EPattern::NumLiteral(ENumber::IntHasFloatSuffix, pos) => {
to_number_literal_mismatch_suffix(alloc, lines, filename, pos, "an integer", "a float")
}
&EPattern::NumLiteral(ENumber::FloatHasIntSuffix, pos) => {
to_number_literal_mismatch_suffix(alloc, lines, filename, pos, "a float", "an integer")
}
_ => todo!("unhandled parse error: {:?}", parse_problem),
}
}
@ -1976,6 +1994,57 @@ fn to_malformed_number_literal_report<'a>(
}
}
fn to_number_literal_with_bad_suffix_report<'a>(
alloc: &'a RocDocAllocator<'a>,
lines: &LineInfo,
filename: PathBuf,
start: Position,
) -> Report<'a> {
let surroundings = Region::new(start, start);
let region = LineColumnRegion::from_pos(lines.convert_pos(start));
let doc = alloc.stack(vec![
alloc.reflow(r"It looks like you are trying to use type suffix on this number literal, but it's not one that I recognize:"),
alloc.region_with_subregion(lines.convert_region(surroundings), region),
]);
Report {
filename,
doc,
title: "INVALID NUMBER LITERAL SUFFIX".to_string(),
severity: Severity::RuntimeError,
}
}
fn to_number_literal_mismatch_suffix<'a>(
alloc: &'a RocDocAllocator<'a>,
lines: &LineInfo,
filename: PathBuf,
start: Position,
literal_kind: &'static str,
suffix_kind: &'static str,
) -> Report<'a> {
let surroundings = Region::new(start, start);
let region = LineColumnRegion::from_pos(lines.convert_pos(start));
let doc = alloc.stack(vec![
alloc.concat(vec![
alloc.text(r"This number literal is "),
alloc.text(literal_kind),
alloc.text(", but its suffix says it's "),
alloc.text(suffix_kind),
]),
alloc.region_with_subregion(lines.convert_region(surroundings), region),
]);
Report {
filename,
doc,
title: "NUMBER LITERAL CONFLICTS WITH SUFFIX".to_string(),
severity: Severity::RuntimeError,
}
}
fn to_type_report<'a>(
alloc: &'a RocDocAllocator<'a>,
lines: &LineInfo,

View file

@ -1730,9 +1730,10 @@ mod test_reporting {
),
indoc!(
r#"
INVALID NUMBER LITERAL
INVALID NUMBER LITERAL SUFFIX
This number literal is malformed:
It looks like you are trying to use type suffix on this number
literal, but it's not one that I recognize:
2 100A -> 3
^
@ -1753,9 +1754,10 @@ mod test_reporting {
),
indoc!(
r#"
INVALID NUMBER LITERAL
INVALID NUMBER LITERAL SUFFIX
This number literal is malformed:
It looks like you are trying to use type suffix on this number
literal, but it's not one that I recognize:
2 2.X -> 3
^
@ -1776,9 +1778,10 @@ mod test_reporting {
),
indoc!(
r#"
INVALID NUMBER LITERAL
INVALID NUMBER LITERAL SUFFIX
This number literal is malformed:
It looks like you are trying to use type suffix on this number
literal, but it's not one that I recognize:
2 0xZ -> 3
^
@ -3533,9 +3536,10 @@ mod test_reporting {
),
indoc!(
r#"
INVALID NUMBER LITERAL
INVALID NUMBER LITERAL SUFFIX
This number literal is malformed:
It looks like you are trying to use type suffix on this number
literal, but it's not one that I recognize:
1 dec = 100A
^
@ -3614,9 +3618,10 @@ mod test_reporting {
),
indoc!(
r#"
INVALID NUMBER LITERAL
INVALID NUMBER LITERAL SUFFIX
This number literal is malformed:
It looks like you are trying to use type suffix on this number
literal, but it's not one that I recognize:
1 x = 3.0A
^
@ -7316,4 +7321,90 @@ I need all branches in an `if` to have the same type!
1, "f32", mismatched_suffix_f32
1, "f64", mismatched_suffix_f64
}
#[test]
fn bad_numeric_literal_suffix() {
report_problem_as(
indoc!(
r#"
1u256
"#
),
indoc!(
r#"
INVALID NUMBER LITERAL SUFFIX
It looks like you are trying to use type suffix on this number
literal, but it's not one that I recognize:
1 1u256
^
"#
),
)
}
#[test]
fn numer_literal_multi_suffix() {
report_problem_as(
indoc!(
r#"
1u8u8
"#
),
indoc!(
r#"
INVALID NUMBER LITERAL SUFFIX
It looks like you are trying to use type suffix on this number
literal, but it's not one that I recognize:
1 1u8u8
^
"#
),
)
}
#[test]
fn int_literal_has_float_suffix() {
report_problem_as(
indoc!(
r#"
0b1f32
"#
),
indoc!(
r#"
NUMBER LITERAL CONFLICTS WITH SUFFIX
This number literal is an integer, but its suffix says it's a float
1 0b1f32
^
"#
),
)
}
#[test]
fn float_literal_has_int_suffix() {
report_problem_as(
indoc!(
r#"
1.0u8
"#
),
indoc!(
r#"
NUMBER LITERAL CONFLICTS WITH SUFFIX
This number literal is a float, but its suffix says it's an integer
1 1.0u8
^
"#
),
)
}
}