| ... | ... | @@ -326,7 +326,7 @@ pub const Token = struct { |
| 326 | 326 | }; |
| 327 | 327 | |
| 328 | 328 | pub const Tokenizer = struct { |
| 329 | | buffer: []const u8, |
| 329 | buffer: [:0]const u8, |
| 330 | 330 | index: usize, |
| 331 | 331 | pending_invalid_token: ?Token, |
| 332 | 332 | |
| ... | ... | @@ -335,7 +335,7 @@ pub const Tokenizer = struct { |
| 335 | 335 | std.debug.warn("{s} \"{s}\"\n", .{ @tagName(token.tag), self.buffer[token.start..token.end] }); |
| 336 | 336 | } |
| 337 | 337 | |
| 338 | | pub fn init(buffer: []const u8) Tokenizer { |
| 338 | pub fn init(buffer: [:0]const u8) Tokenizer { |
| 339 | 339 | // Skip the UTF-8 BOM if present |
| 340 | 340 | const src_start = if (mem.startsWith(u8, buffer, "\xEF\xBB\xBF")) 3 else @as(usize, 0); |
| 341 | 341 | return Tokenizer{ |
| ... | ... | @@ -373,7 +373,6 @@ pub const Tokenizer = struct { |
| 373 | 373 | line_comment, |
| 374 | 374 | doc_comment_start, |
| 375 | 375 | doc_comment, |
| 376 | | container_doc_comment, |
| 377 | 376 | zero, |
| 378 | 377 | int_literal_dec, |
| 379 | 378 | int_literal_dec_no_underscore, |
| ... | ... | @@ -407,10 +406,6 @@ pub const Tokenizer = struct { |
| 407 | 406 | saw_at_sign, |
| 408 | 407 | }; |
| 409 | 408 | |
| 410 | | fn isIdentifierChar(char: u8) bool { |
| 411 | | return std.ascii.isAlNum(char) or char == '_'; |
| 412 | | } |
| 413 | | |
| 414 | 409 | pub fn next(self: *Tokenizer) Token { |
| 415 | 410 | if (self.pending_invalid_token) |token| { |
| 416 | 411 | self.pending_invalid_token = null; |
| ... | ... | @@ -426,10 +421,11 @@ pub const Tokenizer = struct { |
| 426 | 421 | }; |
| 427 | 422 | var seen_escape_digits: usize = undefined; |
| 428 | 423 | var remaining_code_units: usize = undefined; |
| 429 | | while (self.index < self.buffer.len) : (self.index += 1) { |
| 424 | while (true) : (self.index += 1) { |
| 430 | 425 | const c = self.buffer[self.index]; |
| 431 | 426 | switch (state) { |
| 432 | 427 | .start => switch (c) { |
| 428 | 0 => break, |
| 433 | 429 | ' ', '\n', '\t', '\r' => { |
| 434 | 430 | result.loc.start = self.index + 1; |
| 435 | 431 | }, |
| ... | ... | @@ -705,18 +701,22 @@ pub const Tokenizer = struct { |
| 705 | 701 | self.index += 1; |
| 706 | 702 | break; |
| 707 | 703 | }, |
| 708 | | '\n', '\r' => break, // Look for this error later. |
| 704 | 0, '\n', '\r' => break, // Look for this error later. |
| 709 | 705 | else => self.checkLiteralCharacter(), |
| 710 | 706 | }, |
| 711 | 707 | |
| 712 | 708 | .string_literal_backslash => switch (c) { |
| 713 | | '\n', '\r' => break, // Look for this error later. |
| 709 | 0, '\n', '\r' => break, // Look for this error later. |
| 714 | 710 | else => { |
| 715 | 711 | state = .string_literal; |
| 716 | 712 | }, |
| 717 | 713 | }, |
| 718 | 714 | |
| 719 | 715 | .char_literal => switch (c) { |
| 716 | 0 => { |
| 717 | result.tag = .invalid; |
| 718 | break; |
| 719 | }, |
| 720 | 720 | '\\' => { |
| 721 | 721 | state = .char_literal_backslash; |
| 722 | 722 | }, |
| ... | ... | @@ -742,7 +742,7 @@ pub const Tokenizer = struct { |
| 742 | 742 | }, |
| 743 | 743 | |
| 744 | 744 | .char_literal_backslash => switch (c) { |
| 745 | | '\n' => { |
| 745 | 0, '\n' => { |
| 746 | 746 | result.tag = .invalid; |
| 747 | 747 | break; |
| 748 | 748 | }, |
| ... | ... | @@ -834,6 +834,7 @@ pub const Tokenizer = struct { |
| 834 | 834 | }, |
| 835 | 835 | |
| 836 | 836 | .multiline_string_literal_line => switch (c) { |
| 837 | 0 => break, |
| 837 | 838 | '\n' => { |
| 838 | 839 | self.index += 1; |
| 839 | 840 | break; |
| ... | ... | @@ -1025,12 +1026,13 @@ pub const Tokenizer = struct { |
| 1025 | 1026 | }, |
| 1026 | 1027 | }, |
| 1027 | 1028 | .line_comment_start => switch (c) { |
| 1029 | 0 => break, |
| 1028 | 1030 | '/' => { |
| 1029 | 1031 | state = .doc_comment_start; |
| 1030 | 1032 | }, |
| 1031 | 1033 | '!' => { |
| 1032 | 1034 | result.tag = .container_doc_comment; |
| 1033 | | state = .container_doc_comment; |
| 1035 | state = .doc_comment; |
| 1034 | 1036 | }, |
| 1035 | 1037 | '\n' => { |
| 1036 | 1038 | state = .start; |
| ... | ... | @@ -1046,7 +1048,7 @@ pub const Tokenizer = struct { |
| 1046 | 1048 | '/' => { |
| 1047 | 1049 | state = .line_comment; |
| 1048 | 1050 | }, |
| 1049 | | '\n' => { |
| 1051 | 0, '\n' => { |
| 1050 | 1052 | result.tag = .doc_comment; |
| 1051 | 1053 | break; |
| 1052 | 1054 | }, |
| ... | ... | @@ -1061,6 +1063,7 @@ pub const Tokenizer = struct { |
| 1061 | 1063 | }, |
| 1062 | 1064 | }, |
| 1063 | 1065 | .line_comment => switch (c) { |
| 1066 | 0 => break, |
| 1064 | 1067 | '\n' => { |
| 1065 | 1068 | state = .start; |
| 1066 | 1069 | result.loc.start = self.index + 1; |
| ... | ... | @@ -1068,8 +1071,8 @@ pub const Tokenizer = struct { |
| 1068 | 1071 | '\t', '\r' => {}, |
| 1069 | 1072 | else => self.checkLiteralCharacter(), |
| 1070 | 1073 | }, |
| 1071 | | .doc_comment, .container_doc_comment => switch (c) { |
| 1072 | | '\n' => break, |
| 1074 | .doc_comment => switch (c) { |
| 1075 | 0, '\n' => break, |
| 1073 | 1076 | '\t', '\r' => {}, |
| 1074 | 1077 | else => self.checkLiteralCharacter(), |
| 1075 | 1078 | }, |
| ... | ... | @@ -1088,12 +1091,11 @@ pub const Tokenizer = struct { |
| 1088 | 1091 | self.index -= 1; |
| 1089 | 1092 | state = .int_literal_dec; |
| 1090 | 1093 | }, |
| 1091 | | else => { |
| 1092 | | if (isIdentifierChar(c)) { |
| 1093 | | result.tag = .invalid; |
| 1094 | | } |
| 1094 | 'a', 'c', 'd', 'f'...'n', 'p'...'w', 'y', 'z', 'A'...'D', 'F'...'Z' => { |
| 1095 | result.tag = .invalid; |
| 1095 | 1096 | break; |
| 1096 | 1097 | }, |
| 1098 | else => break, |
| 1097 | 1099 | }, |
| 1098 | 1100 | .int_literal_bin_no_underscore => switch (c) { |
| 1099 | 1101 | '0'...'1' => { |
| ... | ... | @@ -1109,12 +1111,11 @@ pub const Tokenizer = struct { |
| 1109 | 1111 | state = .int_literal_bin_no_underscore; |
| 1110 | 1112 | }, |
| 1111 | 1113 | '0'...'1' => {}, |
| 1112 | | else => { |
| 1113 | | if (isIdentifierChar(c)) { |
| 1114 | | result.tag = .invalid; |
| 1115 | | } |
| 1114 | '2'...'9', 'a'...'z', 'A'...'Z' => { |
| 1115 | result.tag = .invalid; |
| 1116 | 1116 | break; |
| 1117 | 1117 | }, |
| 1118 | else => break, |
| 1118 | 1119 | }, |
| 1119 | 1120 | .int_literal_oct_no_underscore => switch (c) { |
| 1120 | 1121 | '0'...'7' => { |
| ... | ... | @@ -1130,12 +1131,11 @@ pub const Tokenizer = struct { |
| 1130 | 1131 | state = .int_literal_oct_no_underscore; |
| 1131 | 1132 | }, |
| 1132 | 1133 | '0'...'7' => {}, |
| 1133 | | else => { |
| 1134 | | if (isIdentifierChar(c)) { |
| 1135 | | result.tag = .invalid; |
| 1136 | | } |
| 1134 | '8', '9', 'a'...'z', 'A'...'Z' => { |
| 1135 | result.tag = .invalid; |
| 1137 | 1136 | break; |
| 1138 | 1137 | }, |
| 1138 | else => break, |
| 1139 | 1139 | }, |
| 1140 | 1140 | .int_literal_dec_no_underscore => switch (c) { |
| 1141 | 1141 | '0'...'9' => { |
| ... | ... | @@ -1159,12 +1159,11 @@ pub const Tokenizer = struct { |
| 1159 | 1159 | result.tag = .float_literal; |
| 1160 | 1160 | }, |
| 1161 | 1161 | '0'...'9' => {}, |
| 1162 | | else => { |
| 1163 | | if (isIdentifierChar(c)) { |
| 1164 | | result.tag = .invalid; |
| 1165 | | } |
| 1162 | 'a'...'d', 'f'...'z', 'A'...'D', 'F'...'Z' => { |
| 1163 | result.tag = .invalid; |
| 1166 | 1164 | break; |
| 1167 | 1165 | }, |
| 1166 | else => break, |
| 1168 | 1167 | }, |
| 1169 | 1168 | .int_literal_hex_no_underscore => switch (c) { |
| 1170 | 1169 | '0'...'9', 'a'...'f', 'A'...'F' => { |
| ... | ... | @@ -1188,12 +1187,11 @@ pub const Tokenizer = struct { |
| 1188 | 1187 | result.tag = .float_literal; |
| 1189 | 1188 | }, |
| 1190 | 1189 | '0'...'9', 'a'...'f', 'A'...'F' => {}, |
| 1191 | | else => { |
| 1192 | | if (isIdentifierChar(c)) { |
| 1193 | | result.tag = .invalid; |
| 1194 | | } |
| 1190 | 'g'...'o', 'q'...'z', 'G'...'O', 'Q'...'Z' => { |
| 1191 | result.tag = .invalid; |
| 1195 | 1192 | break; |
| 1196 | 1193 | }, |
| 1194 | else => break, |
| 1197 | 1195 | }, |
| 1198 | 1196 | .num_dot_dec => switch (c) { |
| 1199 | 1197 | '.' => { |
| ... | ... | @@ -1206,12 +1204,11 @@ pub const Tokenizer = struct { |
| 1206 | 1204 | result.tag = .float_literal; |
| 1207 | 1205 | state = .float_fraction_dec; |
| 1208 | 1206 | }, |
| 1209 | | else => { |
| 1210 | | if (isIdentifierChar(c)) { |
| 1211 | | result.tag = .invalid; |
| 1212 | | } |
| 1207 | '_', 'a'...'z', 'A'...'Z' => { |
| 1208 | result.tag = .invalid; |
| 1213 | 1209 | break; |
| 1214 | 1210 | }, |
| 1211 | else => break, |
| 1215 | 1212 | }, |
| 1216 | 1213 | .num_dot_hex => switch (c) { |
| 1217 | 1214 | '.' => { |
| ... | ... | @@ -1224,12 +1221,11 @@ pub const Tokenizer = struct { |
| 1224 | 1221 | result.tag = .float_literal; |
| 1225 | 1222 | state = .float_fraction_hex; |
| 1226 | 1223 | }, |
| 1227 | | else => { |
| 1228 | | if (isIdentifierChar(c)) { |
| 1229 | | result.tag = .invalid; |
| 1230 | | } |
| 1224 | '_', 'g'...'z', 'G'...'Z' => { |
| 1225 | result.tag = .invalid; |
| 1231 | 1226 | break; |
| 1232 | 1227 | }, |
| 1228 | else => break, |
| 1233 | 1229 | }, |
| 1234 | 1230 | .float_fraction_dec_no_underscore => switch (c) { |
| 1235 | 1231 | '0'...'9' => { |
| ... | ... | @@ -1248,12 +1244,11 @@ pub const Tokenizer = struct { |
| 1248 | 1244 | state = .float_exponent_unsigned; |
| 1249 | 1245 | }, |
| 1250 | 1246 | '0'...'9' => {}, |
| 1251 | | else => { |
| 1252 | | if (isIdentifierChar(c)) { |
| 1253 | | result.tag = .invalid; |
| 1254 | | } |
| 1247 | 'a'...'d', 'f'...'z', 'A'...'D', 'F'...'Z' => { |
| 1248 | result.tag = .invalid; |
| 1255 | 1249 | break; |
| 1256 | 1250 | }, |
| 1251 | else => break, |
| 1257 | 1252 | }, |
| 1258 | 1253 | .float_fraction_hex_no_underscore => switch (c) { |
| 1259 | 1254 | '0'...'9', 'a'...'f', 'A'...'F' => { |
| ... | ... | @@ -1272,12 +1267,11 @@ pub const Tokenizer = struct { |
| 1272 | 1267 | state = .float_exponent_unsigned; |
| 1273 | 1268 | }, |
| 1274 | 1269 | '0'...'9', 'a'...'f', 'A'...'F' => {}, |
| 1275 | | else => { |
| 1276 | | if (isIdentifierChar(c)) { |
| 1277 | | result.tag = .invalid; |
| 1278 | | } |
| 1270 | 'g'...'o', 'q'...'z', 'G'...'O', 'Q'...'Z' => { |
| 1271 | result.tag = .invalid; |
| 1279 | 1272 | break; |
| 1280 | 1273 | }, |
| 1274 | else => break, |
| 1281 | 1275 | }, |
| 1282 | 1276 | .float_exponent_unsigned => switch (c) { |
| 1283 | 1277 | '+', '-' => { |
| ... | ... | @@ -1303,130 +1297,11 @@ pub const Tokenizer = struct { |
| 1303 | 1297 | state = .float_exponent_num_no_underscore; |
| 1304 | 1298 | }, |
| 1305 | 1299 | '0'...'9' => {}, |
| 1306 | | else => { |
| 1307 | | if (isIdentifierChar(c)) { |
| 1308 | | result.tag = .invalid; |
| 1309 | | } |
| 1300 | 'a'...'z', 'A'...'Z' => { |
| 1301 | result.tag = .invalid; |
| 1310 | 1302 | break; |
| 1311 | 1303 | }, |
| 1312 | | }, |
| 1313 | | } |
| 1314 | | } else if (self.index == self.buffer.len) { |
| 1315 | | switch (state) { |
| 1316 | | .start, |
| 1317 | | .int_literal_dec, |
| 1318 | | .int_literal_bin, |
| 1319 | | .int_literal_oct, |
| 1320 | | .int_literal_hex, |
| 1321 | | .num_dot_dec, |
| 1322 | | .num_dot_hex, |
| 1323 | | .float_fraction_dec, |
| 1324 | | .float_fraction_hex, |
| 1325 | | .float_exponent_num, |
| 1326 | | .string_literal, // find this error later |
| 1327 | | .multiline_string_literal_line, |
| 1328 | | .builtin, |
| 1329 | | .line_comment, |
| 1330 | | .line_comment_start, |
| 1331 | | => {}, |
| 1332 | | |
| 1333 | | .identifier => { |
| 1334 | | if (Token.getKeyword(self.buffer[result.loc.start..self.index])) |tag| { |
| 1335 | | result.tag = tag; |
| 1336 | | } |
| 1337 | | }, |
| 1338 | | .doc_comment, .doc_comment_start => { |
| 1339 | | result.tag = .doc_comment; |
| 1340 | | }, |
| 1341 | | .container_doc_comment => { |
| 1342 | | result.tag = .container_doc_comment; |
| 1343 | | }, |
| 1344 | | |
| 1345 | | .int_literal_dec_no_underscore, |
| 1346 | | .int_literal_bin_no_underscore, |
| 1347 | | .int_literal_oct_no_underscore, |
| 1348 | | .int_literal_hex_no_underscore, |
| 1349 | | .float_fraction_dec_no_underscore, |
| 1350 | | .float_fraction_hex_no_underscore, |
| 1351 | | .float_exponent_num_no_underscore, |
| 1352 | | .float_exponent_unsigned, |
| 1353 | | .saw_at_sign, |
| 1354 | | .backslash, |
| 1355 | | .char_literal, |
| 1356 | | .char_literal_backslash, |
| 1357 | | .char_literal_hex_escape, |
| 1358 | | .char_literal_unicode_escape_saw_u, |
| 1359 | | .char_literal_unicode_escape, |
| 1360 | | .char_literal_unicode_invalid, |
| 1361 | | .char_literal_end, |
| 1362 | | .char_literal_unicode, |
| 1363 | | .string_literal_backslash, |
| 1364 | | => { |
| 1365 | | result.tag = .invalid; |
| 1366 | | }, |
| 1367 | | |
| 1368 | | .equal => { |
| 1369 | | result.tag = .equal; |
| 1370 | | }, |
| 1371 | | .bang => { |
| 1372 | | result.tag = .bang; |
| 1373 | | }, |
| 1374 | | .minus => { |
| 1375 | | result.tag = .minus; |
| 1376 | | }, |
| 1377 | | .slash => { |
| 1378 | | result.tag = .slash; |
| 1379 | | }, |
| 1380 | | .zero => { |
| 1381 | | result.tag = .integer_literal; |
| 1382 | | }, |
| 1383 | | .ampersand => { |
| 1384 | | result.tag = .ampersand; |
| 1385 | | }, |
| 1386 | | .period => { |
| 1387 | | result.tag = .period; |
| 1388 | | }, |
| 1389 | | .period_2 => { |
| 1390 | | result.tag = .ellipsis2; |
| 1391 | | }, |
| 1392 | | .period_asterisk => { |
| 1393 | | result.tag = .period_asterisk; |
| 1394 | | }, |
| 1395 | | .pipe => { |
| 1396 | | result.tag = .pipe; |
| 1397 | | }, |
| 1398 | | .angle_bracket_angle_bracket_right => { |
| 1399 | | result.tag = .angle_bracket_angle_bracket_right; |
| 1400 | | }, |
| 1401 | | .angle_bracket_right => { |
| 1402 | | result.tag = .angle_bracket_right; |
| 1403 | | }, |
| 1404 | | .angle_bracket_angle_bracket_left => { |
| 1405 | | result.tag = .angle_bracket_angle_bracket_left; |
| 1406 | | }, |
| 1407 | | .angle_bracket_left => { |
| 1408 | | result.tag = .angle_bracket_left; |
| 1409 | | }, |
| 1410 | | .plus_percent => { |
| 1411 | | result.tag = .plus_percent; |
| 1412 | | }, |
| 1413 | | .plus => { |
| 1414 | | result.tag = .plus; |
| 1415 | | }, |
| 1416 | | .percent => { |
| 1417 | | result.tag = .percent; |
| 1418 | | }, |
| 1419 | | .caret => { |
| 1420 | | result.tag = .caret; |
| 1421 | | }, |
| 1422 | | .asterisk_percent => { |
| 1423 | | result.tag = .asterisk_percent; |
| 1424 | | }, |
| 1425 | | .asterisk => { |
| 1426 | | result.tag = .asterisk; |
| 1427 | | }, |
| 1428 | | .minus_percent => { |
| 1429 | | result.tag = .minus_percent; |
| 1304 | else => break, |
| 1430 | 1305 | }, |
| 1431 | 1306 | } |
| 1432 | 1307 | } |