| 262 | while i < chars.len() { |
| 263 | if chars[i] == '\\' { |
| 264 | i = (i + 2).min(chars.len()); |
| 265 | } else { |
| 266 | let done = chars[i] == '\''; |
| 267 | i += 1; |
| 268 | if done { |
| 269 | break; |
| 270 | } |
| 271 | } |
| 272 | } |
| 273 | push_span(&mut out, "tok-str", &chars[start..i]); |
| 274 | } else if ch.is_ascii_digit() { |
| 275 | let start = i; |
| 276 | i += 1; |
| 277 | while i < chars.len() |
| 278 | && (chars[i].is_ascii_alphanumeric() |
| 279 | || chars[i] == '_' |
| 280 | || chars[i] == '.' |
| 281 | || chars[i] == ':') |
| 282 | { |
| 283 | i += 1; |
| 284 | } |
| 285 | push_span(&mut out, "tok-num", &chars[start..i]); |
| 286 | } else if is_ident_start(ch) { |
| 287 | let start = i; |
| 288 | i += 1; |
| 289 | while i < chars.len() && is_ident_continue(chars[i]) { |
| 290 | i += 1; |
| 291 | } |
| 292 | let ident = chars[start..i].iter().collect::<String>(); |
| 293 | if chars.get(i) == Some(&'!') { |
| 294 | i += 1; |
| 295 | push_span(&mut out, "tok-macro", &chars[start..i]); |
| 296 | } else if is_rust_keyword(&ident) { |
| 297 | push_span(&mut out, "tok-kw", &chars[start..i]); |
| 298 | } else if is_builtin_type(&ident) |
| 299 | || ident.chars().next().is_some_and(char::is_uppercase) |
| 300 | { |
| 301 | push_span(&mut out, "tok-type", &chars[start..i]); |
| 302 | } else { |
| 303 | push_escaped_chars(&mut out, &chars[start..i]); |
| 304 | } |
| 305 | } else { |
| 306 | push_escaped_char(&mut out, ch); |
| 307 | i += 1; |
| 308 | } |