| author | |
| committer | |
| log | e1f5ad3cc875d255946cafc92e0b415a285919c9 |
| tree | 863d200a241b44b3a1bc2bd030ff91fa7bc87970 |
| parent | 49c1384bac75a908c347a74e75e9b9e0110b0700 |
| signature |
3 files changed, 20 insertions(+), 9 deletions(-)
lib/std/zig/number_literal.zig+3-7| ... | @@ -44,8 +44,6 @@ pub const Error = union(enum) { | ... | @@ -44,8 +44,6 @@ pub const Error = union(enum) { |
| 44 | duplicate_period, | 44 | duplicate_period, |
| 45 | /// Float literal has multiple exponents. | 45 | /// Float literal has multiple exponents. |
| 46 | duplicate_exponent: usize, | 46 | duplicate_exponent: usize, |
| 47 | /// Decimal float has hexadecimal exponent. | ||
| 48 | invalid_hex_exponent: usize, | ||
| 49 | /// Exponent comes directly after '_' digit separator. | 47 | /// Exponent comes directly after '_' digit separator. |
| 50 | exponent_after_underscore: usize, | 48 | exponent_after_underscore: usize, |
| 51 | /// Special character (+-.) comes directly after exponent. | 49 | /// Special character (+-.) comes directly after exponent. |
| ... | @@ -103,7 +101,6 @@ pub fn parseNumberLiteral(bytes: []const u8) Result { | ... | @@ -103,7 +101,6 @@ pub fn parseNumberLiteral(bytes: []const u8) Result { |
| 103 | }, | 101 | }, |
| 104 | 'e', 'E' => if (base == 10) { | 102 | 'e', 'E' => if (base == 10) { |
| 105 | float = true; | 103 | float = true; |
| 106 | if (base != 10 and base != 16) return .{ .failure = .{ .invalid_float_base = 2 } }; | ||
| 107 | if (exponent) return .{ .failure = .{ .duplicate_exponent = i } }; | 104 | if (exponent) return .{ .failure = .{ .duplicate_exponent = i } }; |
| 108 | if (underscore) return .{ .failure = .{ .exponent_after_underscore = i } }; | 105 | if (underscore) return .{ .failure = .{ .exponent_after_underscore = i } }; |
| 109 | special = c; | 106 | special = c; |
| ... | @@ -112,10 +109,8 @@ pub fn parseNumberLiteral(bytes: []const u8) Result { | ... | @@ -112,10 +109,8 @@ pub fn parseNumberLiteral(bytes: []const u8) Result { |
| 112 | }, | 109 | }, |
| 113 | 'p', 'P' => if (base == 16) { | 110 | 'p', 'P' => if (base == 16) { |
| 114 | float = true; | 111 | float = true; |
| 115 | if (base != 10 and base != 16) return .{ .failure = .{ .invalid_float_base = 2 } }; | ||
| 116 | if (exponent) return .{ .failure = .{ .duplicate_exponent = i } }; | 112 | if (exponent) return .{ .failure = .{ .duplicate_exponent = i } }; |
| 117 | if (underscore) return .{ .failure = .{ .exponent_after_underscore = i } }; | 113 | if (underscore) return .{ .failure = .{ .exponent_after_underscore = i } }; |
| 118 | if (base != 16) return .{ .failure = .{ .invalid_hex_exponent = i } }; | ||
| 119 | special = c; | 114 | special = c; |
| 120 | exponent = true; | 115 | exponent = true; |
| 121 | continue; | 116 | continue; |
| ... | @@ -123,7 +118,7 @@ pub fn parseNumberLiteral(bytes: []const u8) Result { | ... | @@ -123,7 +118,7 @@ pub fn parseNumberLiteral(bytes: []const u8) Result { |
| 123 | '.' => { | 118 | '.' => { |
| 124 | float = true; | 119 | float = true; |
| 125 | if (base != 10 and base != 16) return .{ .failure = .{ .invalid_float_base = 2 } }; | 120 | if (base != 10 and base != 16) return .{ .failure = .{ .invalid_float_base = 2 } }; |
| 126 | if (period) return .{ .failure = .{ .duplicate_exponent = i } }; | 121 | if (period) return .{ .failure = .duplicate_period }; |
| 127 | period = true; | 122 | period = true; |
| 128 | if (underscore) return .{ .failure = .{ .special_after_underscore = i } }; | 123 | if (underscore) return .{ .failure = .{ .special_after_underscore = i } }; |
| 129 | special = c; | 124 | special = c; |
| ... | @@ -131,7 +126,8 @@ pub fn parseNumberLiteral(bytes: []const u8) Result { | ... | @@ -131,7 +126,8 @@ pub fn parseNumberLiteral(bytes: []const u8) Result { |
| 131 | }, | 126 | }, |
| 132 | '+', '-' => { | 127 | '+', '-' => { |
| 133 | switch (special) { | 128 | switch (special) { |
| 134 | 'p', 'P', 'e', 'E' => {}, | 129 | 'p', 'P' => {}, |
| 130 | 'e', 'E' => if (base != 10) return .{ .failure = .{ .invalid_exponent_sign = i } }, | ||
| 135 | else => return .{ .failure = .{ .invalid_exponent_sign = i } }, | 131 | else => return .{ .failure = .{ .invalid_exponent_sign = i } }, |
| 136 | } | 132 | } |
| 137 | special = c; | 133 | special = c; |
src/AstGen.zig+4-2| ... | @@ -7622,14 +7622,16 @@ fn failWithNumberError(astgen: *AstGen, err: std.zig.number_literal.Error, token | ... | @@ -7622,14 +7622,16 @@ fn failWithNumberError(astgen: *AstGen, err: std.zig.number_literal.Error, token |
| 7622 | .invalid_digit => |info| return astgen.failOff(token, @intCast(u32, info.i), "invalid digit '{c}' for {s} base", .{ bytes[info.i], @tagName(info.base) }), | 7622 | .invalid_digit => |info| return astgen.failOff(token, @intCast(u32, info.i), "invalid digit '{c}' for {s} base", .{ bytes[info.i], @tagName(info.base) }), |
| 7623 | .invalid_digit_exponent => |i| return astgen.failOff(token, @intCast(u32, i), "invalid digit '{c}' in exponent", .{bytes[i]}), | 7623 | .invalid_digit_exponent => |i| return astgen.failOff(token, @intCast(u32, i), "invalid digit '{c}' in exponent", .{bytes[i]}), |
| 7624 | .duplicate_exponent => |i| return astgen.failOff(token, @intCast(u32, i), "duplicate exponent", .{}), | 7624 | .duplicate_exponent => |i| return astgen.failOff(token, @intCast(u32, i), "duplicate exponent", .{}), |
| 7625 | .invalid_hex_exponent => |i| return astgen.failOff(token, @intCast(u32, i), "hex exponent in decimal float", .{}), | ||
| 7626 | .exponent_after_underscore => |i| return astgen.failOff(token, @intCast(u32, i), "expected digit before exponent", .{}), | 7625 | .exponent_after_underscore => |i| return astgen.failOff(token, @intCast(u32, i), "expected digit before exponent", .{}), |
| 7627 | .special_after_underscore => |i| return astgen.failOff(token, @intCast(u32, i), "expected digit before '{c}'", .{bytes[i]}), | 7626 | .special_after_underscore => |i| return astgen.failOff(token, @intCast(u32, i), "expected digit before '{c}'", .{bytes[i]}), |
| 7628 | .trailing_special => |i| return astgen.failOff(token, @intCast(u32, i), "expected digit after '{c}'", .{bytes[i - 1]}), | 7627 | .trailing_special => |i| return astgen.failOff(token, @intCast(u32, i), "expected digit after '{c}'", .{bytes[i - 1]}), |
| 7629 | .trailing_underscore => |i| return astgen.failOff(token, @intCast(u32, i), "trailing digit separator", .{}), | 7628 | .trailing_underscore => |i| return astgen.failOff(token, @intCast(u32, i), "trailing digit separator", .{}), |
| 7630 | .duplicate_period => unreachable, // Validated by tokenizer | 7629 | .duplicate_period => unreachable, // Validated by tokenizer |
| 7631 | .invalid_character => unreachable, // Validated by tokenizer | 7630 | .invalid_character => unreachable, // Validated by tokenizer |
| 7632 | .invalid_exponent_sign => unreachable, // Validated by tokenizer | 7631 | .invalid_exponent_sign => |i| { |
| 7632 | assert(bytes.len >= 2 and bytes[0] == '0' and bytes[1] == 'x'); // Validated by tokenizer | ||
| 7633 | return astgen.failOff(token, @intCast(u32, i), "sign '{c}' cannot follow digit '{c}' in hex base", .{ bytes[i], bytes[i - 1] }); | ||
| 7634 | }, | ||
| 7633 | } | 7635 | } |
| 7634 | } | 7636 | } |
| 7635 | 7637 |
test/cases/compile_errors/number_literal_bad_exponent.zig created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | const a = 0x1e-4; | ||
| 2 | const b = 0x1e+4; | ||
| 3 | const c = 0x1E-4; | ||
| 4 | const d = 0x1E+4; | ||
| 5 | |||
| 6 | // error | ||
| 7 | // backend=stage2 | ||
| 8 | // target=native | ||
| 9 | // | ||
| 10 | // :1:15: error: sign '-' cannot follow digit 'e' in hex base | ||
| 11 | // :2:15: error: sign '+' cannot follow digit 'e' in hex base | ||
| 12 | // :3:15: error: sign '-' cannot follow digit 'E' in hex base | ||
| 13 | // :4:15: error: sign '+' cannot follow digit 'E' in hex base | ||