| ... | ... | @@ -897,7 +897,7 @@ pub const Scanner = struct { |
| 897 | 897 | }, |
| 898 | 898 | .number_post_dot => { |
| 899 | 899 | if (self.cursor >= self.input.len) return self.endOfBufferInNumber(false); |
| 900 | | switch (try self.expectByte()) { |
| 900 | switch (self.input[self.cursor]) { |
| 901 | 901 | '0'...'9' => { |
| 902 | 902 | self.cursor += 1; |
| 903 | 903 | self.state = .number_frac; |
| ... | ... | @@ -1032,7 +1032,8 @@ pub const Scanner = struct { |
| 1032 | 1032 | return error.BufferUnderrun; |
| 1033 | 1033 | }, |
| 1034 | 1034 | .string_backslash => { |
| 1035 | | switch (try self.expectByte()) { |
| 1035 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1036 | switch (self.input[self.cursor]) { |
| 1036 | 1037 | '"', '\\', '/' => { |
| 1037 | 1038 | // Since these characters now represent themselves literally, |
| 1038 | 1039 | // we can simply begin the next plaintext slice here. |
| ... | ... | @@ -1080,7 +1081,8 @@ pub const Scanner = struct { |
| 1080 | 1081 | } |
| 1081 | 1082 | }, |
| 1082 | 1083 | .string_backslash_u => { |
| 1083 | | const c = try self.expectByte(); |
| 1084 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1085 | const c = self.input[self.cursor]; |
| 1084 | 1086 | switch (c) { |
| 1085 | 1087 | '0'...'9' => { |
| 1086 | 1088 | self.utf16_code_units[0] = @as(u16, c - '0') << 12; |
| ... | ... | @@ -1098,7 +1100,8 @@ pub const Scanner = struct { |
| 1098 | 1100 | continue :state_loop; |
| 1099 | 1101 | }, |
| 1100 | 1102 | .string_backslash_u_1 => { |
| 1101 | | const c = try self.expectByte(); |
| 1103 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1104 | const c = self.input[self.cursor]; |
| 1102 | 1105 | switch (c) { |
| 1103 | 1106 | '0'...'9' => { |
| 1104 | 1107 | self.utf16_code_units[0] |= @as(u16, c - '0') << 8; |
| ... | ... | @@ -1116,7 +1119,8 @@ pub const Scanner = struct { |
| 1116 | 1119 | continue :state_loop; |
| 1117 | 1120 | }, |
| 1118 | 1121 | .string_backslash_u_2 => { |
| 1119 | | const c = try self.expectByte(); |
| 1122 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1123 | const c = self.input[self.cursor]; |
| 1120 | 1124 | switch (c) { |
| 1121 | 1125 | '0'...'9' => { |
| 1122 | 1126 | self.utf16_code_units[0] |= @as(u16, c - '0') << 4; |
| ... | ... | @@ -1134,7 +1138,8 @@ pub const Scanner = struct { |
| 1134 | 1138 | continue :state_loop; |
| 1135 | 1139 | }, |
| 1136 | 1140 | .string_backslash_u_3 => { |
| 1137 | | const c = try self.expectByte(); |
| 1141 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1142 | const c = self.input[self.cursor]; |
| 1138 | 1143 | switch (c) { |
| 1139 | 1144 | '0'...'9' => { |
| 1140 | 1145 | self.utf16_code_units[0] |= c - '0'; |
| ... | ... | @@ -1160,7 +1165,8 @@ pub const Scanner = struct { |
| 1160 | 1165 | } |
| 1161 | 1166 | }, |
| 1162 | 1167 | .string_surrogate_half => { |
| 1163 | | switch (try self.expectByte()) { |
| 1168 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1169 | switch (self.input[self.cursor]) { |
| 1164 | 1170 | '\\' => { |
| 1165 | 1171 | self.cursor += 1; |
| 1166 | 1172 | self.state = .string_surrogate_half_backslash; |
| ... | ... | @@ -1170,7 +1176,8 @@ pub const Scanner = struct { |
| 1170 | 1176 | } |
| 1171 | 1177 | }, |
| 1172 | 1178 | .string_surrogate_half_backslash => { |
| 1173 | | switch (try self.expectByte()) { |
| 1179 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1180 | switch (self.input[self.cursor]) { |
| 1174 | 1181 | 'u' => { |
| 1175 | 1182 | self.cursor += 1; |
| 1176 | 1183 | self.state = .string_surrogate_half_backslash_u; |
| ... | ... | @@ -1180,7 +1187,8 @@ pub const Scanner = struct { |
| 1180 | 1187 | } |
| 1181 | 1188 | }, |
| 1182 | 1189 | .string_surrogate_half_backslash_u => { |
| 1183 | | switch (try self.expectByte()) { |
| 1190 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1191 | switch (self.input[self.cursor]) { |
| 1184 | 1192 | 'D', 'd' => { |
| 1185 | 1193 | self.cursor += 1; |
| 1186 | 1194 | self.utf16_code_units[1] = 0xD << 12; |
| ... | ... | @@ -1191,7 +1199,8 @@ pub const Scanner = struct { |
| 1191 | 1199 | } |
| 1192 | 1200 | }, |
| 1193 | 1201 | .string_surrogate_half_backslash_u_1 => { |
| 1194 | | const c = try self.expectByte(); |
| 1202 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1203 | const c = self.input[self.cursor]; |
| 1195 | 1204 | switch (c) { |
| 1196 | 1205 | 'C'...'F' => { |
| 1197 | 1206 | self.cursor += 1; |
| ... | ... | @@ -1209,7 +1218,8 @@ pub const Scanner = struct { |
| 1209 | 1218 | } |
| 1210 | 1219 | }, |
| 1211 | 1220 | .string_surrogate_half_backslash_u_2 => { |
| 1212 | | const c = try self.expectByte(); |
| 1221 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1222 | const c = self.input[self.cursor]; |
| 1213 | 1223 | switch (c) { |
| 1214 | 1224 | '0'...'9' => { |
| 1215 | 1225 | self.cursor += 1; |
| ... | ... | @@ -1233,7 +1243,8 @@ pub const Scanner = struct { |
| 1233 | 1243 | } |
| 1234 | 1244 | }, |
| 1235 | 1245 | .string_surrogate_half_backslash_u_3 => { |
| 1236 | | const c = try self.expectByte(); |
| 1246 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1247 | const c = self.input[self.cursor]; |
| 1237 | 1248 | switch (c) { |
| 1238 | 1249 | '0'...'9' => { |
| 1239 | 1250 | self.utf16_code_units[1] |= c - '0'; |
| ... | ... | @@ -1254,7 +1265,8 @@ pub const Scanner = struct { |
| 1254 | 1265 | }, |
| 1255 | 1266 | |
| 1256 | 1267 | .string_utf8_last_byte => { |
| 1257 | | switch (try self.expectByte()) { |
| 1268 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1269 | switch (self.input[self.cursor]) { |
| 1258 | 1270 | 0x80...0xBF => { |
| 1259 | 1271 | self.cursor += 1; |
| 1260 | 1272 | self.state = .string; |
| ... | ... | @@ -1264,7 +1276,8 @@ pub const Scanner = struct { |
| 1264 | 1276 | } |
| 1265 | 1277 | }, |
| 1266 | 1278 | .string_utf8_second_to_last_byte => { |
| 1267 | | switch (try self.expectByte()) { |
| 1279 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1280 | switch (self.input[self.cursor]) { |
| 1268 | 1281 | 0x80...0xBF => { |
| 1269 | 1282 | self.cursor += 1; |
| 1270 | 1283 | self.state = .string_utf8_last_byte; |
| ... | ... | @@ -1274,7 +1287,8 @@ pub const Scanner = struct { |
| 1274 | 1287 | } |
| 1275 | 1288 | }, |
| 1276 | 1289 | .string_utf8_second_to_last_byte_guard_against_overlong => { |
| 1277 | | switch (try self.expectByte()) { |
| 1290 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1291 | switch (self.input[self.cursor]) { |
| 1278 | 1292 | 0xA0...0xBF => { |
| 1279 | 1293 | self.cursor += 1; |
| 1280 | 1294 | self.state = .string_utf8_last_byte; |
| ... | ... | @@ -1284,7 +1298,8 @@ pub const Scanner = struct { |
| 1284 | 1298 | } |
| 1285 | 1299 | }, |
| 1286 | 1300 | .string_utf8_second_to_last_byte_guard_against_surrogate_half => { |
| 1287 | | switch (try self.expectByte()) { |
| 1301 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1302 | switch (self.input[self.cursor]) { |
| 1288 | 1303 | 0x80...0x9F => { |
| 1289 | 1304 | self.cursor += 1; |
| 1290 | 1305 | self.state = .string_utf8_last_byte; |
| ... | ... | @@ -1294,7 +1309,8 @@ pub const Scanner = struct { |
| 1294 | 1309 | } |
| 1295 | 1310 | }, |
| 1296 | 1311 | .string_utf8_third_to_last_byte => { |
| 1297 | | switch (try self.expectByte()) { |
| 1312 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1313 | switch (self.input[self.cursor]) { |
| 1298 | 1314 | 0x80...0xBF => { |
| 1299 | 1315 | self.cursor += 1; |
| 1300 | 1316 | self.state = .string_utf8_second_to_last_byte; |
| ... | ... | @@ -1304,7 +1320,8 @@ pub const Scanner = struct { |
| 1304 | 1320 | } |
| 1305 | 1321 | }, |
| 1306 | 1322 | .string_utf8_third_to_last_byte_guard_against_overlong => { |
| 1307 | | switch (try self.expectByte()) { |
| 1323 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1324 | switch (self.input[self.cursor]) { |
| 1308 | 1325 | 0x90...0xBF => { |
| 1309 | 1326 | self.cursor += 1; |
| 1310 | 1327 | self.state = .string_utf8_second_to_last_byte; |
| ... | ... | @@ -1314,7 +1331,8 @@ pub const Scanner = struct { |
| 1314 | 1331 | } |
| 1315 | 1332 | }, |
| 1316 | 1333 | .string_utf8_third_to_last_byte_guard_against_too_large => { |
| 1317 | | switch (try self.expectByte()) { |
| 1334 | if (self.cursor >= self.input.len) return self.endOfBufferInString(); |
| 1335 | switch (self.input[self.cursor]) { |
| 1318 | 1336 | 0x80...0x8F => { |
| 1319 | 1337 | self.cursor += 1; |
| 1320 | 1338 | self.state = .string_utf8_second_to_last_byte; |
| ... | ... | @@ -1666,6 +1684,17 @@ pub const Scanner = struct { |
| 1666 | 1684 | self.value_start = self.cursor; |
| 1667 | 1685 | return slice; |
| 1668 | 1686 | } |
| 1687 | fn takeValueSliceMinusTrailingOffset(self: *@This(), trailing_negative_offset: usize) []const u8 { |
| 1688 | // Check if the escape sequence started before the current input buffer. |
| 1689 | // (The algebra here is awkward to avoid unsigned underflow, |
| 1690 | // but it's just making sure the slice on the next line isn't UB.) |
| 1691 | if (self.cursor <= self.value_start + trailing_negative_offset) return ""; |
| 1692 | const slice = self.input[self.value_start .. self.cursor - trailing_negative_offset]; |
| 1693 | // When trailing_negative_offset is non-zero, setting self.value_start doesn't matter, |
| 1694 | // because we always set it again while emitting the .partial_string_escaped_*. |
| 1695 | self.value_start = self.cursor; |
| 1696 | return slice; |
| 1697 | } |
| 1669 | 1698 | |
| 1670 | 1699 | fn endOfBufferInNumber(self: *@This(), allow_end: bool) !Token { |
| 1671 | 1700 | const slice = self.takeValueSlice(); |
| ... | ... | @@ -1678,6 +1707,39 @@ pub const Scanner = struct { |
| 1678 | 1707 | return Token{ .partial_number = slice }; |
| 1679 | 1708 | } |
| 1680 | 1709 | |
| 1710 | fn endOfBufferInString(self: *@This()) !Token { |
| 1711 | if (self.is_end_of_input) return error.UnexpectedEndOfInput; |
| 1712 | const slice = self.takeValueSliceMinusTrailingOffset(switch (self.state) { |
| 1713 | // Don't include the escape sequence in the partial string. |
| 1714 | .string_backslash => 1, |
| 1715 | .string_backslash_u => 2, |
| 1716 | .string_backslash_u_1 => 3, |
| 1717 | .string_backslash_u_2 => 4, |
| 1718 | .string_backslash_u_3 => 5, |
| 1719 | .string_surrogate_half => 6, |
| 1720 | .string_surrogate_half_backslash => 7, |
| 1721 | .string_surrogate_half_backslash_u => 8, |
| 1722 | .string_surrogate_half_backslash_u_1 => 9, |
| 1723 | .string_surrogate_half_backslash_u_2 => 10, |
| 1724 | .string_surrogate_half_backslash_u_3 => 11, |
| 1725 | |
| 1726 | // Include everything up to the cursor otherwise. |
| 1727 | .string, |
| 1728 | .string_utf8_last_byte, |
| 1729 | .string_utf8_second_to_last_byte, |
| 1730 | .string_utf8_second_to_last_byte_guard_against_overlong, |
| 1731 | .string_utf8_second_to_last_byte_guard_against_surrogate_half, |
| 1732 | .string_utf8_third_to_last_byte, |
| 1733 | .string_utf8_third_to_last_byte_guard_against_overlong, |
| 1734 | .string_utf8_third_to_last_byte_guard_against_too_large, |
| 1735 | => 0, |
| 1736 | |
| 1737 | else => unreachable, |
| 1738 | }); |
| 1739 | if (slice.len == 0) return error.BufferUnderrun; |
| 1740 | return Token{ .partial_string = slice }; |
| 1741 | } |
| 1742 | |
| 1681 | 1743 | fn partialStringCodepoint(code_point: u21) Token { |
| 1682 | 1744 | var buf: [4]u8 = undefined; |
| 1683 | 1745 | switch (std.unicode.utf8Encode(code_point, &buf) catch unreachable) { |