authorgravatar for 4678790+dweiller@users.noreply.github.comDominic <4678790+dweiller@users.noreply.github.com> 2023-05-07 18:05:53+10:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-05-07 08:05:53+00:00
loge1f5ad3cc875d255946cafc92e0b415a285919c9
tree863d200a241b44b3a1bc2bd030ff91fa7bc87970
parent49c1384bac75a908c347a74e75e9b9e0110b0700
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Fix parsing of hexadecimal literals


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 tokenizer7629 .duplicate_period => unreachable, // Validated by tokenizer
7631 .invalid_character => unreachable, // Validated by tokenizer7630 .invalid_character => unreachable, // Validated by tokenizer
7632 .invalid_exponent_sign => unreachable, // Validated by tokenizer7631 .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}
76357637
test/cases/compile_errors/number_literal_bad_exponent.zig created+13
...@@ -0,0 +1,13 @@
1const a = 0x1e-4;
2const b = 0x1e+4;
3const c = 0x1E-4;
4const 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