1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use ;
use Error;
/// Read a CSS string: "..." or '...'
/// Preserves raw escape sequences exactly as written (no quirks applied)
/// Content extracted via source[start+1..end-1]
///
/// **Architecture**: Lexer preserves raw content → Parser decodes → Conversion applies Svelte quirks
/// This matches TypeScript's approach and keeps the lexer simple and consistent.
pub
/// Why [`string_end`]'s scan failed, carrying the position the lexer's error wants.
pub
/// End of the string whose opening quote sits at `open` (one past its closing quote).
/// The single statement of the string token's extent, read the same way by every scanner
/// that meets a string: the lexer maps the error arms to its two messages, `decl_scan` (the
/// second reader of this grammar) declines on either, `parse_string_literal` asks whether a
/// value's opening quote closes at its very end, and the value parser's fused pass
/// (`quoted_run_end`), its operator splitter and the printer's at-rule prelude normalizers
/// (`value_normalization`'s string branch and its `skip_string`) take end-of-input for
/// either arm. A printer asking where
/// a string ends must get the lexer's answer: a prelude scanner that disagreed would rewrite
/// a region the parse had read as one token.
///
/// The two scan targets — the quote and `\` — are ASCII, so neither can occur as a
/// UTF-8 continuation byte: a multi-byte char's trailing bytes are all >= 0x80 and
/// fall through the run untouched, landing on the same terminator the former
/// per-char decode found. A `\` consumes itself plus the first byte of whatever it
/// escapes — enough, since the escaped char's remaining continuation bytes can match
/// neither target.
///
/// The run is [`tsv_lang::swar::next_byte_of`], eight bytes a word, behind a two-compare
/// test of its FIRST byte — and that pre-test is the whole lever, not an optimization of
/// it. A stylesheet's string runs are bimodal twice over: **half of them are empty**,
/// because the `\` of an icon-font escape (`content: "\e901"`) sits against the opening
/// quote and the escape step lands three bytes from the close; and while 98% of the runs
/// are under a word, 86% of the *bytes* sit in runs of 128 or more, which are data URIs.
/// A per-byte reading of that histogram sizes only the second mode. What the machine
/// actually pays is the word loop's entry, about fifteen instructions, on every one of
/// the empty runs — so retiring those on two ALU compares is what makes the word loop
/// win on a stylesheet holding no long string at all.
///
/// ⚠️ **The first-byte test is deliberately NOT a 256-entry skip table**, which is what
/// this scan's whole run used to be. A table is the right rung for a *run* — six
/// instructions a byte against a compare chain's thirteen — but for a single byte it
/// puts a dependent L1 load at the head of every call, and the same spelling with the
/// table measured a point of cycles slower on both CSS populations while removing
/// marginally *more* instructions. Rung by run length, not by habit.
pub