authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-08-31 13:36:48+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-09-13 20:26:04-04:00
log349d78a443c8a844c5050cd3122b539f8c95598b
tree41306af5f934d64f7e06c39b37d7424198829d0d
parent716d9237cb757c15217b21964fde8e755aabe853

validate number literals in AstGen


34 files changed, 599 insertions(+), 659 deletions(-)

doc/docgen.zig+1-3
......@@ -1057,9 +1057,7 @@ fn tokenizeAndPrintRaw(
10571057 }
10581058 },
10591059
1060 .integer_literal,
1061 .float_literal,
1062 => {
1060 .number_literal => {
10631061 try out.writeAll("<span class=\"tok-number\">");
10641062 try writeEscaped(out, src[token.loc.start..token.loc.end]);
10651063 try out.writeAll("</span>");
lib/std/zig.zig+2
......@@ -10,6 +10,7 @@ pub const fmtEscapes = fmt.fmtEscapes;
1010pub const isValidId = fmt.isValidId;
1111pub const parse = @import("zig/parse.zig").parse;
1212pub const string_literal = @import("zig/string_literal.zig");
13pub const number_literal = @import("zig/number_literal.zig");
1314pub const Ast = @import("zig/Ast.zig");
1415pub const system = @import("zig/system.zig");
1516pub const CrossTarget = @import("zig/CrossTarget.zig");
......@@ -17,6 +18,7 @@ pub const CrossTarget = @import("zig/CrossTarget.zig");
1718// Character literal parsing
1819pub const ParsedCharLiteral = string_literal.ParsedCharLiteral;
1920pub const parseCharLiteral = string_literal.parseCharLiteral;
21pub const parseNumberLiteral = number_literal.parseNumberLiteral;
2022
2123// Files needed by translate-c.
2224pub const c_builtins = @import("zig/c_builtins.zig");
lib/std/zig/Ast.zig+3-7
......@@ -406,8 +406,7 @@ pub fn firstToken(tree: Ast, node: Node.Index) TokenIndex {
406406 .identifier,
407407 .anyframe_literal,
408408 .char_literal,
409 .integer_literal,
410 .float_literal,
409 .number_literal,
411410 .unreachable_literal,
412411 .string_literal,
413412 .multiline_string_literal,
......@@ -781,8 +780,7 @@ pub fn lastToken(tree: Ast, node: Node.Index) TokenIndex {
781780
782781 .anyframe_literal,
783782 .char_literal,
784 .integer_literal,
785 .float_literal,
783 .number_literal,
786784 .unreachable_literal,
787785 .identifier,
788786 .deref,
......@@ -2919,9 +2917,7 @@ pub const Node = struct {
29192917 /// Both lhs and rhs unused.
29202918 char_literal,
29212919 /// Both lhs and rhs unused.
2922 integer_literal,
2923 /// Both lhs and rhs unused.
2924 float_literal,
2920 number_literal,
29252921 /// Both lhs and rhs unused.
29262922 unreachable_literal,
29272923 /// Both lhs and rhs unused.
lib/std/zig/number_literal.zig created+167
......@@ -0,0 +1,167 @@
1const std = @import("../std.zig");
2const assert = std.debug.assert;
3const utf8Decode = std.unicode.utf8Decode;
4const utf8Encode = std.unicode.utf8Encode;
5
6pub const ParseError = error{
7 OutOfMemory,
8 InvalidLiteral,
9};
10
11pub const Base = enum(u8) { decimal = 10, hex = 16, binary = 2, octal = 8 };
12pub const FloatBase = enum(u8) { decimal = 10, hex = 16 };
13
14pub const Result = union(enum) {
15 /// Result fits if it fits in u64
16 int: u64,
17 /// Result is an int that doesn't fit in u64. Payload is the base, if it is
18 /// not `.decimal` then the slice has a two character prefix.
19 big_int: Base,
20 /// Result is a float. Payload is the base, if it is not `.decimal` then
21 /// the slice has a two character prefix.
22 float: FloatBase,
23 failure: Error,
24};
25
26pub const Error = union(enum) {
27 /// The number has leading zeroes.
28 leading_zero,
29 /// Expected a digit after base prefix.
30 digit_after_base,
31 /// The base prefix is in uppercase.
32 upper_case_base: usize,
33 /// Float literal has an invalid base prefix.
34 invalid_float_base: usize,
35 /// Repeated '_' digit separator.
36 repeated_underscore: usize,
37 /// '_' digit separator after special character (+-.)
38 invalid_underscore_after_special: usize,
39 /// Invalid digit for the specified base.
40 invalid_digit: struct { i: usize, base: Base },
41 /// Invalid digit for an exponent.
42 invalid_digit_exponent: usize,
43 /// Float literal has multiple periods.
44 duplicate_period,
45 /// Float literal has multiple exponents.
46 duplicate_exponent: usize,
47 /// Decimal float has hexadecimal exponent.
48 invalid_hex_exponent: usize,
49 /// Exponent comes directly after '_' digit separator.
50 exponent_after_underscore: usize,
51 /// Special character (+-.) comes directly after exponent.
52 special_after_underscore: usize,
53 /// Number ends in special character (+-.)
54 trailing_special: usize,
55 /// Number ends in '_' digit separator.
56 trailing_underscore: usize,
57 /// Character not in [0-9a-zA-Z.+-_]
58 invalid_character: usize,
59 /// [+-] not immediately after [pPeE]
60 invalid_exponent_sign: usize,
61};
62
63/// Parse Zig number literal accepted by fmt.parseInt, fmt.parseFloat and big_int.setString.
64/// Valid for any input.
65pub fn parseNumberLiteral(bytes: []const u8) Result {
66 var i: usize = 0;
67 var base: u8 = 10;
68 if (bytes.len >= 2 and bytes[0] == '0') switch (bytes[1]) {
69 'b' => {
70 base = 2;
71 i = 2;
72 },
73 'o' => {
74 base = 8;
75 i = 2;
76 },
77 'x' => {
78 base = 16;
79 i = 2;
80 },
81 'B', 'O', 'X' => return .{ .failure = .{ .upper_case_base = 1 } },
82 '.', 'e', 'E' => {},
83 else => return .{ .failure = .leading_zero },
84 };
85 if (bytes.len == 2 and base != 10) return .{ .failure = .digit_after_base };
86
87 var x: u64 = 0;
88 var overflow = false;
89 var underscore = false;
90 var period = false;
91 var special: u8 = 0;
92 var exponent = false;
93 var float = false;
94 while (i < bytes.len) : (i += 1) {
95 const c = bytes[i];
96 switch (c) {
97 '_' => {
98 if (i == 2 and base != 10) return .{ .failure = .{ .invalid_underscore_after_special = i } };
99 if (special != 0) return .{ .failure = .{ .invalid_underscore_after_special = i } };
100 if (underscore) return .{ .failure = .{ .repeated_underscore = i } };
101 underscore = true;
102 continue;
103 },
104 'e', 'E' => if (base == 10) {
105 float = true;
106 if (base != 10 and base != 16) return .{ .failure = .{ .invalid_float_base = 2 } };
107 if (exponent) return .{ .failure = .{ .duplicate_exponent = i } };
108 if (underscore) return .{ .failure = .{ .exponent_after_underscore = i } };
109 special = c;
110 exponent = true;
111 continue;
112 },
113 'p', 'P' => if (base == 16) {
114 float = true;
115 if (base != 10 and base != 16) return .{ .failure = .{ .invalid_float_base = 2 } };
116 if (exponent) return .{ .failure = .{ .duplicate_exponent = i } };
117 if (underscore) return .{ .failure = .{ .exponent_after_underscore = i } };
118 if (base != 16) return .{ .failure = .{ .invalid_hex_exponent = i } };
119 special = c;
120 exponent = true;
121 continue;
122 },
123 '.' => {
124 float = true;
125 if (base != 10 and base != 16) return .{ .failure = .{ .invalid_float_base = 2 } };
126 if (period) return .{ .failure = .{ .duplicate_exponent = i } };
127 period = true;
128 if (underscore) return .{ .failure = .{ .special_after_underscore = i } };
129 special = c;
130 continue;
131 },
132 '+', '-' => {
133 switch (special) {
134 'p', 'P', 'e', 'E' => {},
135 else => return .{ .failure = .{ .invalid_exponent_sign = i } },
136 }
137 special = c;
138 continue;
139 },
140 else => {},
141 }
142 const digit = switch (c) {
143 '0'...'9' => c - '0',
144 'A'...'Z' => c - 'A' + 10,
145 'a'...'z' => c - 'a' + 10,
146 else => return .{ .failure = .{ .invalid_character = i } },
147 };
148 if (digit >= base) return .{ .failure = .{ .invalid_digit = .{ .i = i, .base = @intToEnum(Base, base) } } };
149 if (exponent and digit >= 10) return .{ .failure = .{ .invalid_digit_exponent = i } };
150 underscore = false;
151 special = 0;
152
153 if (float) continue;
154 if (x != 0) if (@mulWithOverflow(u64, x, base, &x)) {
155 overflow = true;
156 };
157 if (@addWithOverflow(u64, x, digit, &x)) {
158 overflow = true;
159 }
160 }
161 if (underscore) return .{ .failure = .{ .trailing_underscore = bytes.len - 1 } };
162 if (special != 0) return .{ .failure = .{ .trailing_special = bytes.len - 1 } };
163
164 if (float) return .{ .float = @intToEnum(FloatBase, base) };
165 if (overflow) return .{ .big_int = @intToEnum(Base, base) };
166 return .{ .int = x };
167}
lib/std/zig/parse.zig+2-10
......@@ -2401,16 +2401,8 @@ const Parser = struct {
24012401 .rhs = undefined,
24022402 },
24032403 }),
2404 .integer_literal => return p.addNode(.{
2405 .tag = .integer_literal,
2406 .main_token = p.nextToken(),
2407 .data = .{
2408 .lhs = undefined,
2409 .rhs = undefined,
2410 },
2411 }),
2412 .float_literal => return p.addNode(.{
2413 .tag = .float_literal,
2404 .number_literal => return p.addNode(.{
2405 .tag = .number_literal,
24142406 .main_token = p.nextToken(),
24152407 .data = .{
24162408 .lhs = undefined,
lib/std/zig/render.zig+1-2
......@@ -199,8 +199,7 @@ fn renderExpression(gpa: Allocator, ais: *Ais, tree: Ast, node: Ast.Node.Index,
199199 return renderSpace(ais, tree, token_index, lexeme.len, space);
200200 },
201201
202 .integer_literal,
203 .float_literal,
202 .number_literal,
204203 .char_literal,
205204 .unreachable_literal,
206205 .anyframe_literal,
lib/std/zig/tokenizer.zig+263-473
......@@ -136,8 +136,7 @@ pub const Token = struct {
136136 angle_bracket_angle_bracket_right,
137137 angle_bracket_angle_bracket_right_equal,
138138 tilde,
139 integer_literal,
140 float_literal,
139 number_literal,
141140 doc_comment,
142141 container_doc_comment,
143142 keyword_addrspace,
......@@ -199,8 +198,7 @@ pub const Token = struct {
199198 .char_literal,
200199 .eof,
201200 .builtin,
202 .integer_literal,
203 .float_literal,
201 .number_literal,
204202 .doc_comment,
205203 .container_doc_comment,
206204 => null,
......@@ -328,8 +326,7 @@ pub const Token = struct {
328326 .char_literal => "a character literal",
329327 .eof => "EOF",
330328 .builtin => "a builtin function",
331 .integer_literal => "an integer literal",
332 .float_literal => "a floating point literal",
329 .number_literal => "a number literal",
333330 .doc_comment, .container_doc_comment => "a document comment",
334331 else => unreachable,
335332 };
......@@ -387,24 +384,11 @@ pub const Tokenizer = struct {
387384 line_comment,
388385 doc_comment_start,
389386 doc_comment,
390 zero,
391 int_literal_dec,
392 int_literal_dec_no_underscore,
393 int_literal_bin,
394 int_literal_bin_no_underscore,
395 int_literal_oct,
396 int_literal_oct_no_underscore,
397 int_literal_hex,
398 int_literal_hex_no_underscore,
399 num_dot_dec,
400 num_dot_hex,
401 float_fraction_dec,
402 float_fraction_dec_no_underscore,
403 float_fraction_hex,
404 float_fraction_hex_no_underscore,
405 float_exponent_unsigned,
406 float_exponent_num,
407 float_exponent_num_no_underscore,
387 int,
388 int_exponent,
389 int_period,
390 float,
391 float_exponent,
408392 ampersand,
409393 caret,
410394 percent,
......@@ -557,13 +541,9 @@ pub const Tokenizer = struct {
557541 '&' => {
558542 state = .ampersand;
559543 },
560 '0' => {
561 state = .zero;
562 result.tag = .integer_literal;
563 },
564 '1'...'9' => {
565 state = .int_literal_dec;
566 result.tag = .integer_literal;
544 '0'...'9' => {
545 state = .int;
546 result.tag = .number_literal;
567547 },
568548 else => {
569549 result.tag = .invalid;
......@@ -1175,232 +1155,42 @@ pub const Tokenizer = struct {
11751155 '\t', '\r' => {},
11761156 else => self.checkLiteralCharacter(),
11771157 },
1178 .zero => switch (c) {
1179 'b' => {
1180 state = .int_literal_bin_no_underscore;
1181 },
1182 'o' => {
1183 state = .int_literal_oct_no_underscore;
1184 },
1185 'x' => {
1186 state = .int_literal_hex_no_underscore;
1187 },
1188 '0'...'9', '_', '.', 'e', 'E' => {
1189 // reinterpret as a decimal number
1190 self.index -= 1;
1191 state = .int_literal_dec;
1192 },
1193 'a', 'c', 'd', 'f'...'n', 'p'...'w', 'y', 'z', 'A'...'D', 'F'...'Z' => {
1194 result.tag = .invalid;
1195 break;
1196 },
1197 else => break,
1198 },
1199 .int_literal_bin_no_underscore => switch (c) {
1200 '0'...'1' => {
1201 state = .int_literal_bin;
1202 },
1203 else => {
1204 result.tag = .invalid;
1205 break;
1206 },
1207 },
1208 .int_literal_bin => switch (c) {
1209 '_' => {
1210 state = .int_literal_bin_no_underscore;
1211 },
1212 '0'...'1' => {},
1213 '2'...'9', 'a'...'z', 'A'...'Z' => {
1214 result.tag = .invalid;
1215 break;
1216 },
1158 .int => switch (c) {
1159 '.' => state = .int_period,
1160 '_', 'a'...'d', 'f'...'o', 'q'...'z', 'A'...'D', 'F'...'O', 'Q'...'Z', '0'...'9' => {},
1161 'e', 'E', 'p', 'P' => state = .int_exponent,
12171162 else => break,
12181163 },
1219 .int_literal_oct_no_underscore => switch (c) {
1220 '0'...'7' => {
1221 state = .int_literal_oct;
1164 .int_exponent => switch (c) {
1165 '-', '+' => {
1166 state = .float;
12221167 },
12231168 else => {
1224 result.tag = .invalid;
1225 break;
1226 },
1227 },
1228 .int_literal_oct => switch (c) {
1229 '_' => {
1230 state = .int_literal_oct_no_underscore;
1231 },
1232 '0'...'7' => {},
1233 '8', '9', 'a'...'z', 'A'...'Z' => {
1234 result.tag = .invalid;
1235 break;
1236 },
1237 else => break,
1238 },
1239 .int_literal_dec_no_underscore => switch (c) {
1240 '0'...'9' => {
1241 state = .int_literal_dec;
1242 },
1243 else => {
1244 result.tag = .invalid;
1245 break;
1246 },
1247 },
1248 .int_literal_dec => switch (c) {
1249 '_' => {
1250 state = .int_literal_dec_no_underscore;
1251 },
1252 '.' => {
1253 state = .num_dot_dec;
1254 result.tag = .invalid;
1255 },
1256 'e', 'E' => {
1257 state = .float_exponent_unsigned;
1258 result.tag = .float_literal;
1259 },
1260 '0'...'9' => {},
1261 'a'...'d', 'f'...'z', 'A'...'D', 'F'...'Z' => {
1262 result.tag = .invalid;
1263 break;
1264 },
1265 else => break,
1266 },
1267 .int_literal_hex_no_underscore => switch (c) {
1268 '0'...'9', 'a'...'f', 'A'...'F' => {
1269 state = .int_literal_hex;
1270 },
1271 else => {
1272 result.tag = .invalid;
1273 break;
1274 },
1275 },
1276 .int_literal_hex => switch (c) {
1277 '_' => {
1278 state = .int_literal_hex_no_underscore;
1279 },
1280 '.' => {
1281 state = .num_dot_hex;
1282 result.tag = .invalid;
1283 },
1284 'p', 'P' => {
1285 state = .float_exponent_unsigned;
1286 result.tag = .float_literal;
1287 },
1288 '0'...'9', 'a'...'f', 'A'...'F' => {},
1289 'g'...'o', 'q'...'z', 'G'...'O', 'Q'...'Z' => {
1290 result.tag = .invalid;
1291 break;
1292 },
1293 else => break,
1294 },
1295 .num_dot_dec => switch (c) {
1296 '.' => {
1297 result.tag = .integer_literal;
1298 self.index -= 1;
1299 state = .start;
1300 break;
1301 },
1302 '0'...'9' => {
1303 result.tag = .float_literal;
1304 state = .float_fraction_dec;
1305 },
1306 '_', 'a'...'z', 'A'...'Z' => {
1307 result.tag = .invalid;
1308 break;
1309 },
1310 else => break,
1311 },
1312 .num_dot_hex => switch (c) {
1313 '.' => {
1314 result.tag = .integer_literal;
13151169 self.index -= 1;
1316 state = .start;
1317 break;
1318 },
1319 '0'...'9', 'a'...'f', 'A'...'F' => {
1320 result.tag = .float_literal;
1321 state = .float_fraction_hex;
1322 },
1323 '_', 'g'...'z', 'G'...'Z' => {
1324 result.tag = .invalid;
1325 break;
1170 state = .int;
13261171 },
1327 else => break,
13281172 },
1329 .float_fraction_dec_no_underscore => switch (c) {
1330 '0'...'9' => {
1331 state = .float_fraction_dec;
1173 .int_period => switch (c) {
1174 '_', 'a'...'d', 'f'...'o', 'q'...'z', 'A'...'D', 'F'...'O', 'Q'...'Z', '0'...'9' => {
1175 state = .float;
13321176 },
1177 'e', 'E', 'p', 'P' => state = .float_exponent,
13331178 else => {
1334 result.tag = .invalid;
1335 break;
1336 },
1337 },
1338 .float_fraction_dec => switch (c) {
1339 '_' => {
1340 state = .float_fraction_dec_no_underscore;
1341 },
1342 'e', 'E' => {
1343 state = .float_exponent_unsigned;
1344 },
1345 '0'...'9' => {},
1346 'a'...'d', 'f'...'z', 'A'...'D', 'F'...'Z' => {
1347 result.tag = .invalid;
1348 break;
1349 },
1350 else => break,
1351 },
1352 .float_fraction_hex_no_underscore => switch (c) {
1353 '0'...'9', 'a'...'f', 'A'...'F' => {
1354 state = .float_fraction_hex;
1355 },
1356 else => {
1357 result.tag = .invalid;
1179 self.index -= 1;
13581180 break;
13591181 },
13601182 },
1361 .float_fraction_hex => switch (c) {
1362 '_' => {
1363 state = .float_fraction_hex_no_underscore;
1364 },
1365 'p', 'P' => {
1366 state = .float_exponent_unsigned;
1367 },
1368 '0'...'9', 'a'...'f', 'A'...'F' => {},
1369 'g'...'o', 'q'...'z', 'G'...'O', 'Q'...'Z' => {
1370 result.tag = .invalid;
1371 break;
1372 },
1183 .float => switch (c) {
1184 '_', 'a'...'d', 'f'...'o', 'q'...'z', 'A'...'D', 'F'...'O', 'Q'...'Z', '0'...'9' => {},
1185 'e', 'E', 'p', 'P' => state = .float_exponent,
13731186 else => break,
13741187 },
1375 .float_exponent_unsigned => switch (c) {
1376 '+', '-' => {
1377 state = .float_exponent_num_no_underscore;
1378 },
1188 .float_exponent => switch (c) {
1189 '-', '+' => state = .float,
13791190 else => {
1380 // reinterpret as a normal exponent number
13811191 self.index -= 1;
1382 state = .float_exponent_num_no_underscore;
1383 },
1384 },
1385 .float_exponent_num_no_underscore => switch (c) {
1386 '0'...'9' => {
1387 state = .float_exponent_num;
1192 state = .float;
13881193 },
1389 else => {
1390 result.tag = .invalid;
1391 break;
1392 },
1393 },
1394 .float_exponent_num => switch (c) {
1395 '_' => {
1396 state = .float_exponent_num_no_underscore;
1397 },
1398 '0'...'9' => {},
1399 'a'...'z', 'A'...'Z' => {
1400 result.tag = .invalid;
1401 break;
1402 },
1403 else => break,
14041194 },
14051195 }
14061196 }
......@@ -1571,7 +1361,7 @@ test "code point literal with unicode escapes" {
15711361 , &.{ .invalid, .invalid });
15721362 try testTokenize(
15731363 \\'\U0333'
1574 , &.{ .invalid, .integer_literal, .invalid });
1364 , &.{ .invalid, .number_literal, .invalid });
15751365}
15761366
15771367test "code point literal with unicode code point" {
......@@ -1584,7 +1374,7 @@ test "float literal e exponent" {
15841374 try testTokenize("a = 4.94065645841246544177e-324;\n", &.{
15851375 .identifier,
15861376 .equal,
1587 .float_literal,
1377 .number_literal,
15881378 .semicolon,
15891379 });
15901380}
......@@ -1593,7 +1383,7 @@ test "float literal p exponent" {
15931383 try testTokenize("a = 0x1.a827999fcef32p+1022;\n", &.{
15941384 .identifier,
15951385 .equal,
1596 .float_literal,
1386 .number_literal,
15971387 .semicolon,
15981388 });
15991389}
......@@ -1757,7 +1547,7 @@ test "correctly parse pointer assignment" {
17571547 .identifier,
17581548 .period_asterisk,
17591549 .equal,
1760 .integer_literal,
1550 .number_literal,
17611551 .semicolon,
17621552 });
17631553}
......@@ -1767,7 +1557,7 @@ test "correctly parse pointer dereference followed by asterisk" {
17671557 .string_literal,
17681558 .period_asterisk,
17691559 .asterisk_asterisk,
1770 .integer_literal,
1560 .number_literal,
17711561 });
17721562
17731563 try testTokenize("(\"b\".*)** 10", &.{
......@@ -1776,256 +1566,256 @@ test "correctly parse pointer dereference followed by asterisk" {
17761566 .period_asterisk,
17771567 .r_paren,
17781568 .asterisk_asterisk,
1779 .integer_literal,
1569 .number_literal,
17801570 });
17811571
17821572 try testTokenize("\"b\".*** 10", &.{
17831573 .string_literal,
17841574 .invalid_periodasterisks,
17851575 .asterisk_asterisk,
1786 .integer_literal,
1576 .number_literal,
17871577 });
17881578}
17891579
17901580test "range literals" {
1791 try testTokenize("0...9", &.{ .integer_literal, .ellipsis3, .integer_literal });
1581 try testTokenize("0...9", &.{ .number_literal, .ellipsis3, .number_literal });
17921582 try testTokenize("'0'...'9'", &.{ .char_literal, .ellipsis3, .char_literal });
1793 try testTokenize("0x00...0x09", &.{ .integer_literal, .ellipsis3, .integer_literal });
1794 try testTokenize("0b00...0b11", &.{ .integer_literal, .ellipsis3, .integer_literal });
1795 try testTokenize("0o00...0o11", &.{ .integer_literal, .ellipsis3, .integer_literal });
1583 try testTokenize("0x00...0x09", &.{ .number_literal, .ellipsis3, .number_literal });
1584 try testTokenize("0b00...0b11", &.{ .number_literal, .ellipsis3, .number_literal });
1585 try testTokenize("0o00...0o11", &.{ .number_literal, .ellipsis3, .number_literal });
17961586}
17971587
17981588test "number literals decimal" {
1799 try testTokenize("0", &.{.integer_literal});
1800 try testTokenize("1", &.{.integer_literal});
1801 try testTokenize("2", &.{.integer_literal});
1802 try testTokenize("3", &.{.integer_literal});
1803 try testTokenize("4", &.{.integer_literal});
1804 try testTokenize("5", &.{.integer_literal});
1805 try testTokenize("6", &.{.integer_literal});
1806 try testTokenize("7", &.{.integer_literal});
1807 try testTokenize("8", &.{.integer_literal});
1808 try testTokenize("9", &.{.integer_literal});
1809 try testTokenize("1..", &.{ .integer_literal, .ellipsis2 });
1810 try testTokenize("0a", &.{ .invalid, .identifier });
1811 try testTokenize("9b", &.{ .invalid, .identifier });
1812 try testTokenize("1z", &.{ .invalid, .identifier });
1813 try testTokenize("1z_1", &.{ .invalid, .identifier });
1814 try testTokenize("9z3", &.{ .invalid, .identifier });
1815
1816 try testTokenize("0_0", &.{.integer_literal});
1817 try testTokenize("0001", &.{.integer_literal});
1818 try testTokenize("01234567890", &.{.integer_literal});
1819 try testTokenize("012_345_6789_0", &.{.integer_literal});
1820 try testTokenize("0_1_2_3_4_5_6_7_8_9_0", &.{.integer_literal});
1821
1822 try testTokenize("00_", &.{.invalid});
1823 try testTokenize("0_0_", &.{.invalid});
1824 try testTokenize("0__0", &.{ .invalid, .identifier });
1825 try testTokenize("0_0f", &.{ .invalid, .identifier });
1826 try testTokenize("0_0_f", &.{ .invalid, .identifier });
1827 try testTokenize("0_0_f_00", &.{ .invalid, .identifier });
1828 try testTokenize("1_,", &.{ .invalid, .comma });
1829
1830 try testTokenize("0.0", &.{.float_literal});
1831 try testTokenize("1.0", &.{.float_literal});
1832 try testTokenize("10.0", &.{.float_literal});
1833 try testTokenize("0e0", &.{.float_literal});
1834 try testTokenize("1e0", &.{.float_literal});
1835 try testTokenize("1e100", &.{.float_literal});
1836 try testTokenize("1.0e100", &.{.float_literal});
1837 try testTokenize("1.0e+100", &.{.float_literal});
1838 try testTokenize("1.0e-100", &.{.float_literal});
1839 try testTokenize("1_0_0_0.0_0_0_0_0_1e1_0_0_0", &.{.float_literal});
1840
1841 try testTokenize("1.", &.{.invalid});
1842 try testTokenize("1e", &.{.invalid});
1843 try testTokenize("1.e100", &.{ .invalid, .identifier });
1844 try testTokenize("1.0e1f0", &.{ .invalid, .identifier });
1845 try testTokenize("1.0p100", &.{ .invalid, .identifier });
1846 try testTokenize("1.0p-100", &.{ .invalid, .identifier, .minus, .integer_literal });
1847 try testTokenize("1.0p1f0", &.{ .invalid, .identifier });
1848 try testTokenize("1.0_,", &.{ .invalid, .comma });
1849 try testTokenize("1_.0", &.{ .invalid, .period, .integer_literal });
1850 try testTokenize("1._", &.{ .invalid, .identifier });
1851 try testTokenize("1.a", &.{ .invalid, .identifier });
1852 try testTokenize("1.z", &.{ .invalid, .identifier });
1853 try testTokenize("1._0", &.{ .invalid, .identifier });
1854 try testTokenize("1.+", &.{ .invalid, .plus });
1855 try testTokenize("1._+", &.{ .invalid, .identifier, .plus });
1856 try testTokenize("1._e", &.{ .invalid, .identifier });
1857 try testTokenize("1.0e", &.{.invalid});
1858 try testTokenize("1.0e,", &.{ .invalid, .comma });
1859 try testTokenize("1.0e_", &.{ .invalid, .identifier });
1860 try testTokenize("1.0e+_", &.{ .invalid, .identifier });
1861 try testTokenize("1.0e-_", &.{ .invalid, .identifier });
1862 try testTokenize("1.0e0_+", &.{ .invalid, .plus });
1589 try testTokenize("0", &.{.number_literal});
1590 try testTokenize("1", &.{.number_literal});
1591 try testTokenize("2", &.{.number_literal});
1592 try testTokenize("3", &.{.number_literal});
1593 try testTokenize("4", &.{.number_literal});
1594 try testTokenize("5", &.{.number_literal});
1595 try testTokenize("6", &.{.number_literal});
1596 try testTokenize("7", &.{.number_literal});
1597 try testTokenize("8", &.{.number_literal});
1598 try testTokenize("9", &.{.number_literal});
1599 try testTokenize("1..", &.{ .number_literal, .ellipsis2 });
1600 try testTokenize("0a", &.{.number_literal});
1601 try testTokenize("9b", &.{.number_literal});
1602 try testTokenize("1z", &.{.number_literal});
1603 try testTokenize("1z_1", &.{.number_literal});
1604 try testTokenize("9z3", &.{.number_literal});
1605
1606 try testTokenize("0_0", &.{.number_literal});
1607 try testTokenize("0001", &.{.number_literal});
1608 try testTokenize("01234567890", &.{.number_literal});
1609 try testTokenize("012_345_6789_0", &.{.number_literal});
1610 try testTokenize("0_1_2_3_4_5_6_7_8_9_0", &.{.number_literal});
1611
1612 try testTokenize("00_", &.{.number_literal});
1613 try testTokenize("0_0_", &.{.number_literal});
1614 try testTokenize("0__0", &.{.number_literal});
1615 try testTokenize("0_0f", &.{.number_literal});
1616 try testTokenize("0_0_f", &.{.number_literal});
1617 try testTokenize("0_0_f_00", &.{.number_literal});
1618 try testTokenize("1_,", &.{ .number_literal, .comma });
1619
1620 try testTokenize("0.0", &.{.number_literal});
1621 try testTokenize("1.0", &.{.number_literal});
1622 try testTokenize("10.0", &.{.number_literal});
1623 try testTokenize("0e0", &.{.number_literal});
1624 try testTokenize("1e0", &.{.number_literal});
1625 try testTokenize("1e100", &.{.number_literal});
1626 try testTokenize("1.0e100", &.{.number_literal});
1627 try testTokenize("1.0e+100", &.{.number_literal});
1628 try testTokenize("1.0e-100", &.{.number_literal});
1629 try testTokenize("1_0_0_0.0_0_0_0_0_1e1_0_0_0", &.{.number_literal});
1630
1631 try testTokenize("1.", &.{ .number_literal, .period });
1632 try testTokenize("1e", &.{.number_literal});
1633 try testTokenize("1.e100", &.{.number_literal});
1634 try testTokenize("1.0e1f0", &.{.number_literal});
1635 try testTokenize("1.0p100", &.{.number_literal});
1636 try testTokenize("1.0p-100", &.{.number_literal});
1637 try testTokenize("1.0p1f0", &.{.number_literal});
1638 try testTokenize("1.0_,", &.{ .number_literal, .comma });
1639 try testTokenize("1_.0", &.{.number_literal});
1640 try testTokenize("1._", &.{.number_literal});
1641 try testTokenize("1.a", &.{.number_literal});
1642 try testTokenize("1.z", &.{.number_literal});
1643 try testTokenize("1._0", &.{.number_literal});
1644 try testTokenize("1.+", &.{ .number_literal, .period, .plus });
1645 try testTokenize("1._+", &.{ .number_literal, .plus });
1646 try testTokenize("1._e", &.{.number_literal});
1647 try testTokenize("1.0e", &.{.number_literal});
1648 try testTokenize("1.0e,", &.{ .number_literal, .comma });
1649 try testTokenize("1.0e_", &.{.number_literal});
1650 try testTokenize("1.0e+_", &.{.number_literal});
1651 try testTokenize("1.0e-_", &.{.number_literal});
1652 try testTokenize("1.0e0_+", &.{ .number_literal, .plus });
18631653}
18641654
18651655test "number literals binary" {
1866 try testTokenize("0b0", &.{.integer_literal});
1867 try testTokenize("0b1", &.{.integer_literal});
1868 try testTokenize("0b2", &.{ .invalid, .integer_literal });
1869 try testTokenize("0b3", &.{ .invalid, .integer_literal });
1870 try testTokenize("0b4", &.{ .invalid, .integer_literal });
1871 try testTokenize("0b5", &.{ .invalid, .integer_literal });
1872 try testTokenize("0b6", &.{ .invalid, .integer_literal });
1873 try testTokenize("0b7", &.{ .invalid, .integer_literal });
1874 try testTokenize("0b8", &.{ .invalid, .integer_literal });
1875 try testTokenize("0b9", &.{ .invalid, .integer_literal });
1876 try testTokenize("0ba", &.{ .invalid, .identifier });
1877 try testTokenize("0bb", &.{ .invalid, .identifier });
1878 try testTokenize("0bc", &.{ .invalid, .identifier });
1879 try testTokenize("0bd", &.{ .invalid, .identifier });
1880 try testTokenize("0be", &.{ .invalid, .identifier });
1881 try testTokenize("0bf", &.{ .invalid, .identifier });
1882 try testTokenize("0bz", &.{ .invalid, .identifier });
1883
1884 try testTokenize("0b0000_0000", &.{.integer_literal});
1885 try testTokenize("0b1111_1111", &.{.integer_literal});
1886 try testTokenize("0b10_10_10_10", &.{.integer_literal});
1887 try testTokenize("0b0_1_0_1_0_1_0_1", &.{.integer_literal});
1888 try testTokenize("0b1.", &.{ .integer_literal, .period });
1889 try testTokenize("0b1.0", &.{ .integer_literal, .period, .integer_literal });
1890
1891 try testTokenize("0B0", &.{ .invalid, .identifier });
1892 try testTokenize("0b_", &.{ .invalid, .identifier });
1893 try testTokenize("0b_0", &.{ .invalid, .identifier });
1894 try testTokenize("0b1_", &.{.invalid});
1895 try testTokenize("0b0__1", &.{ .invalid, .identifier });
1896 try testTokenize("0b0_1_", &.{.invalid});
1897 try testTokenize("0b1e", &.{ .invalid, .identifier });
1898 try testTokenize("0b1p", &.{ .invalid, .identifier });
1899 try testTokenize("0b1e0", &.{ .invalid, .identifier });
1900 try testTokenize("0b1p0", &.{ .invalid, .identifier });
1901 try testTokenize("0b1_,", &.{ .invalid, .comma });
1656 try testTokenize("0b0", &.{.number_literal});
1657 try testTokenize("0b1", &.{.number_literal});
1658 try testTokenize("0b2", &.{.number_literal});
1659 try testTokenize("0b3", &.{.number_literal});
1660 try testTokenize("0b4", &.{.number_literal});
1661 try testTokenize("0b5", &.{.number_literal});
1662 try testTokenize("0b6", &.{.number_literal});
1663 try testTokenize("0b7", &.{.number_literal});
1664 try testTokenize("0b8", &.{.number_literal});
1665 try testTokenize("0b9", &.{.number_literal});
1666 try testTokenize("0ba", &.{.number_literal});
1667 try testTokenize("0bb", &.{.number_literal});
1668 try testTokenize("0bc", &.{.number_literal});
1669 try testTokenize("0bd", &.{.number_literal});
1670 try testTokenize("0be", &.{.number_literal});
1671 try testTokenize("0bf", &.{.number_literal});
1672 try testTokenize("0bz", &.{.number_literal});
1673
1674 try testTokenize("0b0000_0000", &.{.number_literal});
1675 try testTokenize("0b1111_1111", &.{.number_literal});
1676 try testTokenize("0b10_10_10_10", &.{.number_literal});
1677 try testTokenize("0b0_1_0_1_0_1_0_1", &.{.number_literal});
1678 try testTokenize("0b1.", &.{ .number_literal, .period });
1679 try testTokenize("0b1.0", &.{.number_literal});
1680
1681 try testTokenize("0B0", &.{.number_literal});
1682 try testTokenize("0b_", &.{.number_literal});
1683 try testTokenize("0b_0", &.{.number_literal});
1684 try testTokenize("0b1_", &.{.number_literal});
1685 try testTokenize("0b0__1", &.{.number_literal});
1686 try testTokenize("0b0_1_", &.{.number_literal});
1687 try testTokenize("0b1e", &.{.number_literal});
1688 try testTokenize("0b1p", &.{.number_literal});
1689 try testTokenize("0b1e0", &.{.number_literal});
1690 try testTokenize("0b1p0", &.{.number_literal});
1691 try testTokenize("0b1_,", &.{ .number_literal, .comma });
19021692}
19031693
19041694test "number literals octal" {
1905 try testTokenize("0o0", &.{.integer_literal});
1906 try testTokenize("0o1", &.{.integer_literal});
1907 try testTokenize("0o2", &.{.integer_literal});
1908 try testTokenize("0o3", &.{.integer_literal});
1909 try testTokenize("0o4", &.{.integer_literal});
1910 try testTokenize("0o5", &.{.integer_literal});
1911 try testTokenize("0o6", &.{.integer_literal});
1912 try testTokenize("0o7", &.{.integer_literal});
1913 try testTokenize("0o8", &.{ .invalid, .integer_literal });
1914 try testTokenize("0o9", &.{ .invalid, .integer_literal });
1915 try testTokenize("0oa", &.{ .invalid, .identifier });
1916 try testTokenize("0ob", &.{ .invalid, .identifier });
1917 try testTokenize("0oc", &.{ .invalid, .identifier });
1918 try testTokenize("0od", &.{ .invalid, .identifier });
1919 try testTokenize("0oe", &.{ .invalid, .identifier });
1920 try testTokenize("0of", &.{ .invalid, .identifier });
1921 try testTokenize("0oz", &.{ .invalid, .identifier });
1922
1923 try testTokenize("0o01234567", &.{.integer_literal});
1924 try testTokenize("0o0123_4567", &.{.integer_literal});
1925 try testTokenize("0o01_23_45_67", &.{.integer_literal});
1926 try testTokenize("0o0_1_2_3_4_5_6_7", &.{.integer_literal});
1927 try testTokenize("0o7.", &.{ .integer_literal, .period });
1928 try testTokenize("0o7.0", &.{ .integer_literal, .period, .integer_literal });
1929
1930 try testTokenize("0O0", &.{ .invalid, .identifier });
1931 try testTokenize("0o_", &.{ .invalid, .identifier });
1932 try testTokenize("0o_0", &.{ .invalid, .identifier });
1933 try testTokenize("0o1_", &.{.invalid});
1934 try testTokenize("0o0__1", &.{ .invalid, .identifier });
1935 try testTokenize("0o0_1_", &.{.invalid});
1936 try testTokenize("0o1e", &.{ .invalid, .identifier });
1937 try testTokenize("0o1p", &.{ .invalid, .identifier });
1938 try testTokenize("0o1e0", &.{ .invalid, .identifier });
1939 try testTokenize("0o1p0", &.{ .invalid, .identifier });
1940 try testTokenize("0o_,", &.{ .invalid, .identifier, .comma });
1695 try testTokenize("0o0", &.{.number_literal});
1696 try testTokenize("0o1", &.{.number_literal});
1697 try testTokenize("0o2", &.{.number_literal});
1698 try testTokenize("0o3", &.{.number_literal});
1699 try testTokenize("0o4", &.{.number_literal});
1700 try testTokenize("0o5", &.{.number_literal});
1701 try testTokenize("0o6", &.{.number_literal});
1702 try testTokenize("0o7", &.{.number_literal});
1703 try testTokenize("0o8", &.{.number_literal});
1704 try testTokenize("0o9", &.{.number_literal});
1705 try testTokenize("0oa", &.{.number_literal});
1706 try testTokenize("0ob", &.{.number_literal});
1707 try testTokenize("0oc", &.{.number_literal});
1708 try testTokenize("0od", &.{.number_literal});
1709 try testTokenize("0oe", &.{.number_literal});
1710 try testTokenize("0of", &.{.number_literal});
1711 try testTokenize("0oz", &.{.number_literal});
1712
1713 try testTokenize("0o01234567", &.{.number_literal});
1714 try testTokenize("0o0123_4567", &.{.number_literal});
1715 try testTokenize("0o01_23_45_67", &.{.number_literal});
1716 try testTokenize("0o0_1_2_3_4_5_6_7", &.{.number_literal});
1717 try testTokenize("0o7.", &.{ .number_literal, .period });
1718 try testTokenize("0o7.0", &.{.number_literal});
1719
1720 try testTokenize("0O0", &.{.number_literal});
1721 try testTokenize("0o_", &.{.number_literal});
1722 try testTokenize("0o_0", &.{.number_literal});
1723 try testTokenize("0o1_", &.{.number_literal});
1724 try testTokenize("0o0__1", &.{.number_literal});
1725 try testTokenize("0o0_1_", &.{.number_literal});
1726 try testTokenize("0o1e", &.{.number_literal});
1727 try testTokenize("0o1p", &.{.number_literal});
1728 try testTokenize("0o1e0", &.{.number_literal});
1729 try testTokenize("0o1p0", &.{.number_literal});
1730 try testTokenize("0o_,", &.{ .number_literal, .comma });
19411731}
19421732
19431733test "number literals hexadecimal" {
1944 try testTokenize("0x0", &.{.integer_literal});
1945 try testTokenize("0x1", &.{.integer_literal});
1946 try testTokenize("0x2", &.{.integer_literal});
1947 try testTokenize("0x3", &.{.integer_literal});
1948 try testTokenize("0x4", &.{.integer_literal});
1949 try testTokenize("0x5", &.{.integer_literal});
1950 try testTokenize("0x6", &.{.integer_literal});
1951 try testTokenize("0x7", &.{.integer_literal});
1952 try testTokenize("0x8", &.{.integer_literal});
1953 try testTokenize("0x9", &.{.integer_literal});
1954 try testTokenize("0xa", &.{.integer_literal});
1955 try testTokenize("0xb", &.{.integer_literal});
1956 try testTokenize("0xc", &.{.integer_literal});
1957 try testTokenize("0xd", &.{.integer_literal});
1958 try testTokenize("0xe", &.{.integer_literal});
1959 try testTokenize("0xf", &.{.integer_literal});
1960 try testTokenize("0xA", &.{.integer_literal});
1961 try testTokenize("0xB", &.{.integer_literal});
1962 try testTokenize("0xC", &.{.integer_literal});
1963 try testTokenize("0xD", &.{.integer_literal});
1964 try testTokenize("0xE", &.{.integer_literal});
1965 try testTokenize("0xF", &.{.integer_literal});
1966 try testTokenize("0x0z", &.{ .invalid, .identifier });
1967 try testTokenize("0xz", &.{ .invalid, .identifier });
1968
1969 try testTokenize("0x0123456789ABCDEF", &.{.integer_literal});
1970 try testTokenize("0x0123_4567_89AB_CDEF", &.{.integer_literal});
1971 try testTokenize("0x01_23_45_67_89AB_CDE_F", &.{.integer_literal});
1972 try testTokenize("0x0_1_2_3_4_5_6_7_8_9_A_B_C_D_E_F", &.{.integer_literal});
1973
1974 try testTokenize("0X0", &.{ .invalid, .identifier });
1975 try testTokenize("0x_", &.{ .invalid, .identifier });
1976 try testTokenize("0x_1", &.{ .invalid, .identifier });
1977 try testTokenize("0x1_", &.{.invalid});
1978 try testTokenize("0x0__1", &.{ .invalid, .identifier });
1979 try testTokenize("0x0_1_", &.{.invalid});
1980 try testTokenize("0x_,", &.{ .invalid, .identifier, .comma });
1981
1982 try testTokenize("0x1.0", &.{.float_literal});
1983 try testTokenize("0xF.0", &.{.float_literal});
1984 try testTokenize("0xF.F", &.{.float_literal});
1985 try testTokenize("0xF.Fp0", &.{.float_literal});
1986 try testTokenize("0xF.FP0", &.{.float_literal});
1987 try testTokenize("0x1p0", &.{.float_literal});
1988 try testTokenize("0xfp0", &.{.float_literal});
1989 try testTokenize("0x1.0+0xF.0", &.{ .float_literal, .plus, .float_literal });
1990
1991 try testTokenize("0x1.", &.{.invalid});
1992 try testTokenize("0xF.", &.{.invalid});
1993 try testTokenize("0x1.+0xF.", &.{ .invalid, .plus, .invalid });
1994 try testTokenize("0xff.p10", &.{ .invalid, .identifier });
1995
1996 try testTokenize("0x0123456.789ABCDEF", &.{.float_literal});
1997 try testTokenize("0x0_123_456.789_ABC_DEF", &.{.float_literal});
1998 try testTokenize("0x0_1_2_3_4_5_6.7_8_9_A_B_C_D_E_F", &.{.float_literal});
1999 try testTokenize("0x0p0", &.{.float_literal});
2000 try testTokenize("0x0.0p0", &.{.float_literal});
2001 try testTokenize("0xff.ffp10", &.{.float_literal});
2002 try testTokenize("0xff.ffP10", &.{.float_literal});
2003 try testTokenize("0xffp10", &.{.float_literal});
2004 try testTokenize("0xff_ff.ff_ffp1_0_0_0", &.{.float_literal});
2005 try testTokenize("0xf_f_f_f.f_f_f_fp+1_000", &.{.float_literal});
2006 try testTokenize("0xf_f_f_f.f_f_f_fp-1_00_0", &.{.float_literal});
2007
2008 try testTokenize("0x1e", &.{.integer_literal});
2009 try testTokenize("0x1e0", &.{.integer_literal});
2010 try testTokenize("0x1p", &.{.invalid});
2011 try testTokenize("0xfp0z1", &.{ .invalid, .identifier });
2012 try testTokenize("0xff.ffpff", &.{ .invalid, .identifier });
2013 try testTokenize("0x0.p", &.{ .invalid, .identifier });
2014 try testTokenize("0x0.z", &.{ .invalid, .identifier });
2015 try testTokenize("0x0._", &.{ .invalid, .identifier });
2016 try testTokenize("0x0_.0", &.{ .invalid, .period, .integer_literal });
2017 try testTokenize("0x0_.0.0", &.{ .invalid, .period, .float_literal });
2018 try testTokenize("0x0._0", &.{ .invalid, .identifier });
2019 try testTokenize("0x0.0_", &.{.invalid});
2020 try testTokenize("0x0_p0", &.{ .invalid, .identifier });
2021 try testTokenize("0x0_.p0", &.{ .invalid, .period, .identifier });
2022 try testTokenize("0x0._p0", &.{ .invalid, .identifier });
2023 try testTokenize("0x0.0_p0", &.{ .invalid, .identifier });
2024 try testTokenize("0x0._0p0", &.{ .invalid, .identifier });
2025 try testTokenize("0x0.0p_0", &.{ .invalid, .identifier });
2026 try testTokenize("0x0.0p+_0", &.{ .invalid, .identifier });
2027 try testTokenize("0x0.0p-_0", &.{ .invalid, .identifier });
2028 try testTokenize("0x0.0p0_", &.{ .invalid, .eof });
1734 try testTokenize("0x0", &.{.number_literal});
1735 try testTokenize("0x1", &.{.number_literal});
1736 try testTokenize("0x2", &.{.number_literal});
1737 try testTokenize("0x3", &.{.number_literal});
1738 try testTokenize("0x4", &.{.number_literal});
1739 try testTokenize("0x5", &.{.number_literal});
1740 try testTokenize("0x6", &.{.number_literal});
1741 try testTokenize("0x7", &.{.number_literal});
1742 try testTokenize("0x8", &.{.number_literal});
1743 try testTokenize("0x9", &.{.number_literal});
1744 try testTokenize("0xa", &.{.number_literal});
1745 try testTokenize("0xb", &.{.number_literal});
1746 try testTokenize("0xc", &.{.number_literal});
1747 try testTokenize("0xd", &.{.number_literal});
1748 try testTokenize("0xe", &.{.number_literal});
1749 try testTokenize("0xf", &.{.number_literal});
1750 try testTokenize("0xA", &.{.number_literal});
1751 try testTokenize("0xB", &.{.number_literal});
1752 try testTokenize("0xC", &.{.number_literal});
1753 try testTokenize("0xD", &.{.number_literal});
1754 try testTokenize("0xE", &.{.number_literal});
1755 try testTokenize("0xF", &.{.number_literal});
1756 try testTokenize("0x0z", &.{.number_literal});
1757 try testTokenize("0xz", &.{.number_literal});
1758
1759 try testTokenize("0x0123456789ABCDEF", &.{.number_literal});
1760 try testTokenize("0x0123_4567_89AB_CDEF", &.{.number_literal});
1761 try testTokenize("0x01_23_45_67_89AB_CDE_F", &.{.number_literal});
1762 try testTokenize("0x0_1_2_3_4_5_6_7_8_9_A_B_C_D_E_F", &.{.number_literal});
1763
1764 try testTokenize("0X0", &.{.number_literal});
1765 try testTokenize("0x_", &.{.number_literal});
1766 try testTokenize("0x_1", &.{.number_literal});
1767 try testTokenize("0x1_", &.{.number_literal});
1768 try testTokenize("0x0__1", &.{.number_literal});
1769 try testTokenize("0x0_1_", &.{.number_literal});
1770 try testTokenize("0x_,", &.{ .number_literal, .comma });
1771
1772 try testTokenize("0x1.0", &.{.number_literal});
1773 try testTokenize("0xF.0", &.{.number_literal});
1774 try testTokenize("0xF.F", &.{.number_literal});
1775 try testTokenize("0xF.Fp0", &.{.number_literal});
1776 try testTokenize("0xF.FP0", &.{.number_literal});
1777 try testTokenize("0x1p0", &.{.number_literal});
1778 try testTokenize("0xfp0", &.{.number_literal});
1779 try testTokenize("0x1.0+0xF.0", &.{ .number_literal, .plus, .number_literal });
1780
1781 try testTokenize("0x1.", &.{ .number_literal, .period });
1782 try testTokenize("0xF.", &.{ .number_literal, .period });
1783 try testTokenize("0x1.+0xF.", &.{ .number_literal, .period, .plus, .number_literal, .period });
1784 try testTokenize("0xff.p10", &.{.number_literal});
1785
1786 try testTokenize("0x0123456.789ABCDEF", &.{.number_literal});
1787 try testTokenize("0x0_123_456.789_ABC_DEF", &.{.number_literal});
1788 try testTokenize("0x0_1_2_3_4_5_6.7_8_9_A_B_C_D_E_F", &.{.number_literal});
1789 try testTokenize("0x0p0", &.{.number_literal});
1790 try testTokenize("0x0.0p0", &.{.number_literal});
1791 try testTokenize("0xff.ffp10", &.{.number_literal});
1792 try testTokenize("0xff.ffP10", &.{.number_literal});
1793 try testTokenize("0xffp10", &.{.number_literal});
1794 try testTokenize("0xff_ff.ff_ffp1_0_0_0", &.{.number_literal});
1795 try testTokenize("0xf_f_f_f.f_f_f_fp+1_000", &.{.number_literal});
1796 try testTokenize("0xf_f_f_f.f_f_f_fp-1_00_0", &.{.number_literal});
1797
1798 try testTokenize("0x1e", &.{.number_literal});
1799 try testTokenize("0x1e0", &.{.number_literal});
1800 try testTokenize("0x1p", &.{.number_literal});
1801 try testTokenize("0xfp0z1", &.{.number_literal});
1802 try testTokenize("0xff.ffpff", &.{.number_literal});
1803 try testTokenize("0x0.p", &.{.number_literal});
1804 try testTokenize("0x0.z", &.{.number_literal});
1805 try testTokenize("0x0._", &.{.number_literal});
1806 try testTokenize("0x0_.0", &.{.number_literal});
1807 try testTokenize("0x0_.0.0", &.{ .number_literal, .period, .number_literal });
1808 try testTokenize("0x0._0", &.{.number_literal});
1809 try testTokenize("0x0.0_", &.{.number_literal});
1810 try testTokenize("0x0_p0", &.{.number_literal});
1811 try testTokenize("0x0_.p0", &.{.number_literal});
1812 try testTokenize("0x0._p0", &.{.number_literal});
1813 try testTokenize("0x0.0_p0", &.{.number_literal});
1814 try testTokenize("0x0._0p0", &.{.number_literal});
1815 try testTokenize("0x0.0p_0", &.{.number_literal});
1816 try testTokenize("0x0.0p+_0", &.{.number_literal});
1817 try testTokenize("0x0.0p-_0", &.{.number_literal});
1818 try testTokenize("0x0.0p0_", &.{.number_literal});
20291819}
20301820
20311821test "multi line string literal with only 1 backslash" {
......@@ -2034,7 +1824,7 @@ test "multi line string literal with only 1 backslash" {
20341824
20351825test "invalid builtin identifiers" {
20361826 try testTokenize("@()", &.{ .invalid, .l_paren, .r_paren });
2037 try testTokenize("@0()", &.{ .invalid, .integer_literal, .l_paren, .r_paren });
1827 try testTokenize("@0()", &.{ .invalid, .number_literal, .l_paren, .r_paren });
20381828}
20391829
20401830test "invalid token with unfinished escape right before eof" {
src/AstGen.zig+92-90
......@@ -441,7 +441,7 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins
441441 .@"asm",
442442 .asm_simple,
443443 .string_literal,
444 .integer_literal,
444 .number_literal,
445445 .call,
446446 .call_comma,
447447 .async_call,
......@@ -459,7 +459,6 @@ fn lvalExpr(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Ins
459459 .while_cont,
460460 .bool_not,
461461 .address_of,
462 .float_literal,
463462 .optional_type,
464463 .block,
465464 .block_semicolon,
......@@ -732,7 +731,7 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
732731 .string_literal => return stringLiteral(gz, rl, node),
733732 .multiline_string_literal => return multilineStringLiteral(gz, rl, node),
734733
735 .integer_literal => return integerLiteral(gz, rl, node),
734 .number_literal => return numberLiteral(gz, rl, node, node, .positive),
736735 // zig fmt: on
737736
738737 .builtin_call_two, .builtin_call_two_comma => {
......@@ -773,7 +772,6 @@ fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: Ast.Node.Index) InnerEr
773772 },
774773 .@"return" => return ret(gz, scope, node),
775774 .field_access => return fieldAccess(gz, scope, rl, node),
776 .float_literal => return floatLiteral(gz, rl, node, .positive),
777775
778776 .if_simple => return ifExpr(gz, scope, rl.br(), node, tree.ifSimple(node)),
779777 .@"if" => return ifExpr(gz, scope, rl.br(), node, tree.ifFull(node)),
......@@ -7052,93 +7050,101 @@ fn charLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.
70527050 }
70537051}
70547052
7055fn integerLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index) InnerError!Zir.Inst.Ref {
7053const Sign = enum { negative, positive };
7054
7055fn numberLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index, source_node: Ast.Node.Index, sign: Sign) InnerError!Zir.Inst.Ref {
70567056 const astgen = gz.astgen;
70577057 const tree = astgen.tree;
70587058 const main_tokens = tree.nodes.items(.main_token);
7059 const int_token = main_tokens[node];
7060 const prefixed_bytes = tree.tokenSlice(int_token);
7061
7062 var base: u8 = 10;
7063 var non_prefixed: []const u8 = prefixed_bytes;
7064 if (mem.startsWith(u8, prefixed_bytes, "0x")) {
7065 base = 16;
7066 non_prefixed = prefixed_bytes[2..];
7067 } else if (mem.startsWith(u8, prefixed_bytes, "0o")) {
7068 base = 8;
7069 non_prefixed = prefixed_bytes[2..];
7070 } else if (mem.startsWith(u8, prefixed_bytes, "0b")) {
7071 base = 2;
7072 non_prefixed = prefixed_bytes[2..];
7073 }
7074
7075 if (base == 10 and prefixed_bytes.len >= 2 and prefixed_bytes[0] == '0') {
7076 return astgen.failNodeNotes(node, "integer literal '{s}' has leading zero", .{prefixed_bytes}, &.{
7077 try astgen.errNoteNode(node, "use '0o' prefix for octal literals", .{}),
7078 });
7079 }
7059 const num_token = main_tokens[node];
7060 const bytes = tree.tokenSlice(num_token);
70807061
7081 if (std.fmt.parseUnsigned(u64, non_prefixed, base)) |small_int| {
7082 const result: Zir.Inst.Ref = switch (small_int) {
7062 const result: Zir.Inst.Ref = switch (std.zig.parseNumberLiteral(bytes)) {
7063 .int => |num| switch (num) {
70837064 0 => .zero,
70847065 1 => .one,
7085 else => try gz.addInt(small_int),
7086 };
7087 return rvalue(gz, rl, result, node);
7088 } else |err| switch (err) {
7089 error.InvalidCharacter => unreachable, // Caught by the parser.
7090 error.Overflow => {},
7091 }
7066 else => try gz.addInt(num),
7067 },
7068 .big_int => |base| big: {
7069 const gpa = astgen.gpa;
7070 var big_int = try std.math.big.int.Managed.init(gpa);
7071 defer big_int.deinit();
7072 const prefix_offset = @as(u8, 2) * @boolToInt(base != .decimal);
7073 big_int.setString(@enumToInt(base), bytes[prefix_offset..]) catch |err| switch (err) {
7074 error.InvalidCharacter => unreachable, // caught in `parseNumberLiteral`
7075 error.InvalidBase => unreachable, // we only pass 16, 8, 2, see above
7076 error.OutOfMemory => return error.OutOfMemory,
7077 };
70927078
7093 const gpa = astgen.gpa;
7094 var big_int = try std.math.big.int.Managed.init(gpa);
7095 defer big_int.deinit();
7096 big_int.setString(base, non_prefixed) catch |err| switch (err) {
7097 error.InvalidCharacter => unreachable, // caught by parser
7098 error.InvalidBase => unreachable, // we only pass 16, 8, 2, see above
7099 error.OutOfMemory => return error.OutOfMemory,
7079 const limbs = big_int.limbs[0..big_int.len()];
7080 assert(big_int.isPositive());
7081 break :big try gz.addIntBig(limbs);
7082 },
7083 .float => {
7084 const unsigned_float_number = std.fmt.parseFloat(f128, bytes) catch |err| switch (err) {
7085 error.InvalidCharacter => unreachable, // validated by tokenizer
7086 };
7087 const float_number = switch (sign) {
7088 .negative => -unsigned_float_number,
7089 .positive => unsigned_float_number,
7090 };
7091 // If the value fits into a f64 without losing any precision, store it that way.
7092 @setFloatMode(.Strict);
7093 const smaller_float = @floatCast(f64, float_number);
7094 const bigger_again: f128 = smaller_float;
7095 if (bigger_again == float_number) {
7096 const result = try gz.addFloat(smaller_float);
7097 return rvalue(gz, rl, result, source_node);
7098 }
7099 // We need to use 128 bits. Break the float into 4 u32 values so we can
7100 // put it into the `extra` array.
7101 const int_bits = @bitCast(u128, float_number);
7102 const result = try gz.addPlNode(.float128, node, Zir.Inst.Float128{
7103 .piece0 = @truncate(u32, int_bits),
7104 .piece1 = @truncate(u32, int_bits >> 32),
7105 .piece2 = @truncate(u32, int_bits >> 64),
7106 .piece3 = @truncate(u32, int_bits >> 96),
7107 });
7108 return rvalue(gz, rl, result, source_node);
7109 },
7110 .failure => |err| return astgen.failWithNumberError(err, num_token, bytes),
71007111 };
71017112
7102 const limbs = big_int.limbs[0..big_int.len()];
7103 assert(big_int.isPositive());
7104 const result = try gz.addIntBig(limbs);
7105 return rvalue(gz, rl, result, node);
7113 if (sign == .positive) {
7114 return rvalue(gz, rl, result, source_node);
7115 } else {
7116 const negated = try gz.addUnNode(.negate, result, source_node);
7117 return rvalue(gz, rl, negated, source_node);
7118 }
71067119}
71077120
7108const Sign = enum { negative, positive };
7109
7110fn floatLiteral(gz: *GenZir, rl: ResultLoc, node: Ast.Node.Index, sign: Sign) InnerError!Zir.Inst.Ref {
7111 const astgen = gz.astgen;
7112 const tree = astgen.tree;
7113 const main_tokens = tree.nodes.items(.main_token);
7114
7115 const main_token = main_tokens[node];
7116 const bytes = tree.tokenSlice(main_token);
7117 const unsigned_float_number = std.fmt.parseFloat(f128, bytes) catch |err| switch (err) {
7118 error.InvalidCharacter => unreachable, // validated by tokenizer
7119 };
7120 const float_number = switch (sign) {
7121 .negative => -unsigned_float_number,
7122 .positive => unsigned_float_number,
7123 };
7124 // If the value fits into a f64 without losing any precision, store it that way.
7125 @setFloatMode(.Strict);
7126 const smaller_float = @floatCast(f64, float_number);
7127 const bigger_again: f128 = smaller_float;
7128 if (bigger_again == float_number) {
7129 const result = try gz.addFloat(smaller_float);
7130 return rvalue(gz, rl, result, node);
7131 }
7132 // We need to use 128 bits. Break the float into 4 u32 values so we can
7133 // put it into the `extra` array.
7134 const int_bits = @bitCast(u128, float_number);
7135 const result = try gz.addPlNode(.float128, node, Zir.Inst.Float128{
7136 .piece0 = @truncate(u32, int_bits),
7137 .piece1 = @truncate(u32, int_bits >> 32),
7138 .piece2 = @truncate(u32, int_bits >> 64),
7139 .piece3 = @truncate(u32, int_bits >> 96),
7140 });
7141 return rvalue(gz, rl, result, node);
7121fn failWithNumberError(astgen: *AstGen, err: std.zig.number_literal.Error, token: Ast.TokenIndex, bytes: []const u8) InnerError {
7122 const is_float = std.mem.indexOfScalar(u8, bytes, '.') != null;
7123 switch (err) {
7124 .leading_zero => if (is_float) {
7125 return astgen.failTok(token, "number '{s}' has leading zero", .{bytes});
7126 } else {
7127 return astgen.failTokNotes(token, "number '{s}' has leading zero", .{bytes}, &.{
7128 try astgen.errNoteTok(token, "use '0o' prefix for octal literals", .{}),
7129 });
7130 },
7131 .digit_after_base => return astgen.failTok(token, "expected a digit after base prefix", .{}),
7132 .upper_case_base => |i| return astgen.failOff(token, @intCast(u32, i), "base prefix must be lowercase", .{}),
7133 .invalid_float_base => |i| return astgen.failOff(token, @intCast(u32, i), "invalid base for float literal", .{}),
7134 .repeated_underscore => |i| return astgen.failOff(token, @intCast(u32, i), "repeated digit separator", .{}),
7135 .invalid_underscore_after_special => |i| return astgen.failOff(token, @intCast(u32, i), "expected digit before digit separator", .{}),
7136 .invalid_digit => |info| return astgen.failOff(token, @intCast(u32, info.i), "invalid digit '{c}' for {s} base", .{ bytes[info.i], @tagName(info.base) }),
7137 .invalid_digit_exponent => |i| return astgen.failOff(token, @intCast(u32, i), "invalid digit '{c}' in exponent", .{bytes[i]}),
7138 .duplicate_exponent => |i| return astgen.failOff(token, @intCast(u32, i), "duplicate exponent", .{}),
7139 .invalid_hex_exponent => |i| return astgen.failOff(token, @intCast(u32, i), "hex exponent in decimal float", .{}),
7140 .exponent_after_underscore => |i| return astgen.failOff(token, @intCast(u32, i), "expected digit before exponent", .{}),
7141 .special_after_underscore => |i| return astgen.failOff(token, @intCast(u32, i), "expected digit before '{c}'", .{bytes[i]}),
7142 .trailing_special => |i| return astgen.failOff(token, @intCast(u32, i), "expected digit after '{c}'", .{bytes[i - 1]}),
7143 .trailing_underscore => |i| return astgen.failOff(token, @intCast(u32, i), "trailing digit separator", .{}),
7144 .duplicate_period => unreachable, // Validated by tokenizer
7145 .invalid_character => unreachable, // Validated by tokenizer
7146 .invalid_exponent_sign => unreachable, // Validated by tokenizer
7147 }
71427148}
71437149
71447150fn asmExpr(
......@@ -8088,8 +8094,8 @@ fn negation(
80888094 // Check for float literal as the sub-expression because we want to preserve
80898095 // its negativity rather than having it go through comptime subtraction.
80908096 const operand_node = node_datas[node].lhs;
8091 if (node_tags[operand_node] == .float_literal) {
8092 return floatLiteral(gz, rl, operand_node, .negative);
8097 if (node_tags[operand_node] == .number_literal) {
8098 return numberLiteral(gz, rl, operand_node, node, .negative);
80938099 }
80948100
80958101 const operand = try expr(gz, scope, .none, operand_node);
......@@ -8497,8 +8503,7 @@ fn nodeMayNeedMemoryLocation(tree: *const Ast, start_node: Ast.Node.Index, have_
84978503 .fn_decl,
84988504 .anyframe_type,
84998505 .anyframe_literal,
8500 .integer_literal,
8501 .float_literal,
8506 .number_literal,
85028507 .enum_literal,
85038508 .string_literal,
85048509 .multiline_string_literal,
......@@ -8757,8 +8762,7 @@ fn nodeMayEvalToError(tree: *const Ast, start_node: Ast.Node.Index) BuiltinFn.Ev
87578762 .fn_decl,
87588763 .anyframe_type,
87598764 .anyframe_literal,
8760 .integer_literal,
8761 .float_literal,
8765 .number_literal,
87628766 .enum_literal,
87638767 .string_literal,
87648768 .multiline_string_literal,
......@@ -8931,8 +8935,7 @@ fn nodeImpliesMoreThanOnePossibleValue(tree: *const Ast, start_node: Ast.Node.In
89318935 .@"suspend",
89328936 .fn_decl,
89338937 .anyframe_literal,
8934 .integer_literal,
8935 .float_literal,
8938 .number_literal,
89368939 .enum_literal,
89378940 .string_literal,
89388941 .multiline_string_literal,
......@@ -9174,8 +9177,7 @@ fn nodeImpliesComptimeOnly(tree: *const Ast, start_node: Ast.Node.Index) bool {
91749177 .@"suspend",
91759178 .fn_decl,
91769179 .anyframe_literal,
9177 .integer_literal,
9178 .float_literal,
9180 .number_literal,
91799181 .enum_literal,
91809182 .string_literal,
91819183 .multiline_string_literal,
src/Compilation.zig+2-2
......@@ -610,7 +610,7 @@ pub const AllErrors = struct {
610610 }
611611 const token_starts = file.tree.tokens.items(.start);
612612 const start = token_starts[item.data.token] + item.data.byte_offset;
613 const end = start + @intCast(u32, file.tree.tokenSlice(item.data.token).len);
613 const end = start + @intCast(u32, file.tree.tokenSlice(item.data.token).len) - item.data.byte_offset;
614614 break :blk Module.SrcLoc.Span{ .start = start, .end = end, .main = start };
615615 };
616616 const err_loc = std.zig.findLineColumn(file.source, err_span.main);
......@@ -629,7 +629,7 @@ pub const AllErrors = struct {
629629 }
630630 const token_starts = file.tree.tokens.items(.start);
631631 const start = token_starts[note_item.data.token] + note_item.data.byte_offset;
632 const end = start + @intCast(u32, file.tree.tokenSlice(note_item.data.token).len);
632 const end = start + @intCast(u32, file.tree.tokenSlice(note_item.data.token).len) - item.data.byte_offset;
633633 break :blk Module.SrcLoc.Span{ .start = start, .end = end, .main = start };
634634 };
635635 const loc = std.zig.findLineColumn(file.source, span.main);
src/autodoc/render_source.zig+1-3
......@@ -316,9 +316,7 @@ pub fn tokenizeAndPrintRaw(
316316 }
317317 },
318318
319 .integer_literal,
320 .float_literal,
321 => {
319 .number_literal => {
322320 try out.writeAll("<span class=\"tok-number\">");
323321 try writeEscaped(out, src[token.loc.start..token.loc.end]);
324322 try out.writeAll("</span>");
src/translate_c/ast.zig+26-26
......@@ -934,13 +934,13 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
934934 .data = undefined,
935935 }),
936936 .zero_literal => return c.addNode(.{
937 .tag = .integer_literal,
938 .main_token = try c.addToken(.integer_literal, "0"),
937 .tag = .number_literal,
938 .main_token = try c.addToken(.number_literal, "0"),
939939 .data = undefined,
940940 }),
941941 .one_literal => return c.addNode(.{
942 .tag = .integer_literal,
943 .main_token = try c.addToken(.integer_literal, "1"),
942 .tag = .number_literal,
943 .main_token = try c.addToken(.number_literal, "1"),
944944 .data = undefined,
945945 }),
946946 .void_type => return c.addNode(.{
......@@ -1074,16 +1074,16 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
10741074 .float_literal => {
10751075 const payload = node.castTag(.float_literal).?.data;
10761076 return c.addNode(.{
1077 .tag = .float_literal,
1078 .main_token = try c.addToken(.float_literal, payload),
1077 .tag = .number_literal,
1078 .main_token = try c.addToken(.number_literal, payload),
10791079 .data = undefined,
10801080 });
10811081 },
10821082 .integer_literal => {
10831083 const payload = node.castTag(.integer_literal).?.data;
10841084 return c.addNode(.{
1085 .tag = .integer_literal,
1086 .main_token = try c.addToken(.integer_literal, payload),
1085 .tag = .number_literal,
1086 .main_token = try c.addToken(.number_literal, payload),
10871087 .data = undefined,
10881088 });
10891089 },
......@@ -1137,14 +1137,14 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
11371137 const string = try renderNode(c, payload.string);
11381138 const l_bracket = try c.addToken(.l_bracket, "[");
11391139 const start = try c.addNode(.{
1140 .tag = .integer_literal,
1141 .main_token = try c.addToken(.integer_literal, "0"),
1140 .tag = .number_literal,
1141 .main_token = try c.addToken(.number_literal, "0"),
11421142 .data = undefined,
11431143 });
11441144 _ = try c.addToken(.ellipsis2, "..");
11451145 const end = try c.addNode(.{
1146 .tag = .integer_literal,
1147 .main_token = try c.addTokenFmt(.integer_literal, "{d}", .{payload.end}),
1146 .tag = .number_literal,
1147 .main_token = try c.addTokenFmt(.number_literal, "{d}", .{payload.end}),
11481148 .data = undefined,
11491149 });
11501150 _ = try c.addToken(.r_bracket, "]");
......@@ -1827,8 +1827,8 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex {
18271827 .data = .{
18281828 .lhs = init,
18291829 .rhs = try c.addNode(.{
1830 .tag = .integer_literal,
1831 .main_token = try c.addTokenFmt(.integer_literal, "{d}", .{payload.count}),
1830 .tag = .number_literal,
1831 .main_token = try c.addTokenFmt(.number_literal, "{d}", .{payload.count}),
18321832 .data = undefined,
18331833 }),
18341834 },
......@@ -2039,8 +2039,8 @@ fn renderRecord(c: *Context, node: Node) !NodeIndex {
20392039 _ = try c.addToken(.keyword_align, "align");
20402040 _ = try c.addToken(.l_paren, "(");
20412041 const align_expr = try c.addNode(.{
2042 .tag = .integer_literal,
2043 .main_token = try c.addTokenFmt(.integer_literal, "{d}", .{alignment}),
2042 .tag = .number_literal,
2043 .main_token = try c.addTokenFmt(.number_literal, "{d}", .{alignment}),
20442044 .data = undefined,
20452045 });
20462046 _ = try c.addToken(.r_paren, ")");
......@@ -2143,8 +2143,8 @@ fn renderArrayInit(c: *Context, lhs: NodeIndex, inits: []const Node) !NodeIndex
21432143fn renderArrayType(c: *Context, len: usize, elem_type: Node) !NodeIndex {
21442144 const l_bracket = try c.addToken(.l_bracket, "[");
21452145 const len_expr = try c.addNode(.{
2146 .tag = .integer_literal,
2147 .main_token = try c.addTokenFmt(.integer_literal, "{d}", .{len}),
2146 .tag = .number_literal,
2147 .main_token = try c.addTokenFmt(.number_literal, "{d}", .{len}),
21482148 .data = undefined,
21492149 });
21502150 _ = try c.addToken(.r_bracket, "]");
......@@ -2162,15 +2162,15 @@ fn renderArrayType(c: *Context, len: usize, elem_type: Node) !NodeIndex {
21622162fn renderNullSentinelArrayType(c: *Context, len: usize, elem_type: Node) !NodeIndex {
21632163 const l_bracket = try c.addToken(.l_bracket, "[");
21642164 const len_expr = try c.addNode(.{
2165 .tag = .integer_literal,
2166 .main_token = try c.addTokenFmt(.integer_literal, "{d}", .{len}),
2165 .tag = .number_literal,
2166 .main_token = try c.addTokenFmt(.number_literal, "{d}", .{len}),
21672167 .data = undefined,
21682168 });
21692169 _ = try c.addToken(.colon, ":");
21702170
21712171 const sentinel_expr = try c.addNode(.{
2172 .tag = .integer_literal,
2173 .main_token = try c.addToken(.integer_literal, "0"),
2172 .tag = .number_literal,
2173 .main_token = try c.addToken(.number_literal, "0"),
21742174 .data = undefined,
21752175 });
21762176
......@@ -2571,8 +2571,8 @@ fn renderVar(c: *Context, node: Node) !NodeIndex {
25712571 _ = try c.addToken(.keyword_align, "align");
25722572 _ = try c.addToken(.l_paren, "(");
25732573 const res = try c.addNode(.{
2574 .tag = .integer_literal,
2575 .main_token = try c.addTokenFmt(.integer_literal, "{d}", .{some}),
2574 .tag = .number_literal,
2575 .main_token = try c.addTokenFmt(.number_literal, "{d}", .{some}),
25762576 .data = undefined,
25772577 });
25782578 _ = try c.addToken(.r_paren, ")");
......@@ -2655,8 +2655,8 @@ fn renderFunc(c: *Context, node: Node) !NodeIndex {
26552655 _ = try c.addToken(.keyword_align, "align");
26562656 _ = try c.addToken(.l_paren, "(");
26572657 const res = try c.addNode(.{
2658 .tag = .integer_literal,
2659 .main_token = try c.addTokenFmt(.integer_literal, "{d}", .{some}),
2658 .tag = .number_literal,
2659 .main_token = try c.addTokenFmt(.number_literal, "{d}", .{some}),
26602660 .data = undefined,
26612661 });
26622662 _ = try c.addToken(.r_paren, ")");
test/cases/compile_errors/cast_negative_integer_literal_to_usize.zig+5
......@@ -2,9 +2,14 @@ export fn entry() void {
22 const x = @as(usize, -10);
33 _ = x;
44}
5export fn entry1() void {
6 const x = @as(usize, -10.0);
7 _ = x;
8}
59
610// error
711// backend=stage2
812// target=native
913//
1014// :2:26: error: type 'usize' cannot represent integer value '-10'
15// :6:26: error: float value '-10' cannot be stored in integer type 'usize'
test/cases/compile_errors/invalid_exponent_in_float_literal-1.zig+1-2
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:28: note: invalid byte: 'a'
10// :2:28: error: invalid digit 'a' in exponent
test/cases/compile_errors/invalid_exponent_in_float_literal-2.zig+1-2
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:29: note: invalid byte: 'F'
10// :2:29: error: invalid digit 'F' in exponent
test/cases/compile_errors/invalid_underscore_placement_in_float_literal-1.zig+1-2
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:23: note: invalid byte: '_'
10// :2:23: error: expected digit before digit separator
test/cases/compile_errors/invalid_underscore_placement_in_float_literal-10.zig+1-2
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:25: note: invalid byte: '_'
10// :2:25: error: repeated digit separator
test/cases/compile_errors/invalid_underscore_placement_in_float_literal-11.zig+1-2
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:28: note: invalid byte: '_'
10// :2:28: error: repeated digit separator
test/cases/compile_errors/invalid_underscore_placement_in_float_literal-12.zig+2-3
......@@ -1,5 +1,5 @@
11fn main() void {
2 var bad: f128 = 0_x0.0;
2 var bad: f128 = 1_x0.0;
33 _ = bad;
44}
55
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:23: note: invalid byte: 'x'
10// :2:23: error: invalid digit 'x' for decimal base
test/cases/compile_errors/invalid_underscore_placement_in_float_literal-13.zig+1-2
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:23: note: invalid byte: '_'
10// :2:23: error: expected digit before digit separator
test/cases/compile_errors/invalid_underscore_placement_in_float_literal-14.zig+1-2
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:27: note: invalid byte: 'p'
10// :2:27: error: expected digit before exponent
test/cases/compile_errors/invalid_underscore_placement_in_float_literal-2.zig+2-3
......@@ -1,5 +1,5 @@
11fn main() void {
2 var bad: f128 = 0_.0;
2 var bad: f128 = 1_.0;
33 _ = bad;
44}
55
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:23: note: invalid byte: '.'
10// :2:23: error: expected digit before '.'
test/cases/compile_errors/invalid_underscore_placement_in_float_literal-3.zig+1-2
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:25: note: invalid byte: ';'
10// :2:24: error: trailing digit separator
test/cases/compile_errors/invalid_underscore_placement_in_float_literal-4.zig+1-2
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:25: note: invalid byte: '_'
10// :2:25: error: expected digit before digit separator
test/cases/compile_errors/invalid_underscore_placement_in_float_literal-5.zig+1-2
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:26: note: invalid byte: '_'
10// :2:26: error: expected digit before digit separator
test/cases/compile_errors/invalid_underscore_placement_in_float_literal-6.zig+1-2
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:26: note: invalid byte: '_'
10// :2:26: error: expected digit before digit separator
test/cases/compile_errors/invalid_underscore_placement_in_float_literal-7.zig+1-2
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:28: note: invalid byte: ';'
10// :2:27: error: trailing digit separator
test/cases/compile_errors/invalid_underscore_placement_in_float_literal-9.zig+1-2
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:23: note: invalid byte: '_'
10// :2:23: error: repeated digit separator
test/cases/compile_errors/invalid_underscore_placement_in_int_literal-1.zig+1-2
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=llvm
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:24: note: invalid byte: ';'
10// :2:23: error: trailing digit separator
test/cases/compile_errors/invalid_underscore_placement_in_int_literal-2.zig+1-2
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:28: note: invalid byte: ';'
10// :2:27: error: trailing digit separator
test/cases/compile_errors/invalid_underscore_placement_in_int_literal-3.zig+1-2
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:28: note: invalid byte: ';'
10// :2:27: error: trailing digit separator
test/cases/compile_errors/invalid_underscore_placement_in_int_literal-4.zig+1-2
......@@ -7,5 +7,4 @@ fn main() void {
77// backend=stage2
88// target=native
99//
10// :2:21: error: expected expression, found 'invalid bytes'
11// :2:28: note: invalid byte: ';'
10// :2:27: error: trailing digit separator
test/cases/compile_errors/leading_zero_in_integer.zig+2-2
......@@ -21,7 +21,7 @@ export fn entry4() void {
2121//
2222// :2:15: error: primitive integer type 'u000123' has leading zero
2323// :8:12: error: primitive integer type 'i01' has leading zero
24// :12:9: error: integer literal '000123' has leading zero
24// :12:9: error: number '000123' has leading zero
2525// :12:9: note: use '0o' prefix for octal literals
26// :15:9: error: integer literal '01' has leading zero
26// :15:9: error: number '01' has leading zero
2727// :15:9: note: use '0o' prefix for octal literals
test/cases/compile_errors/missing_digit_after_base.zig created+10
......@@ -0,0 +1,10 @@
1export fn entry() void {
2 const x = @as(usize, -0x);
3 _ = x;
4}
5
6// error
7// backend=stage2
8// target=native
9//
10// :2:27: error: expected a digit after base prefix
test/compare_output.zig+1-1
......@@ -75,7 +75,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
7575 \\ _ = c.printf("0.0e0: %.013a\n",
7676 \\ @as(f64, 0.0e0));
7777 \\ _ = c.printf("000000000000000000000000000000000000000000000000000000000.0e0: %.013a\n",
78 \\ @as(f64, 000000000000000000000000000000000000000000000000000000000.0e0));
78 \\ @as(f64, 0.0e0));
7979 \\ _ = c.printf("0.000000000000000000000000000000000000000000000000000000000e0: %.013a\n",
8080 \\ @as(f64, 0.000000000000000000000000000000000000000000000000000000000e0));
8181 \\ _ = c.printf("0.0e000000000000000000000000000000000000000000000000000000000: %.013a\n",