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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
// SPDX-License-Identifier: MIT
// Copyright (c) 2026 Moderately AI Inc.
//! Byte-keyed lexer class data for the parser hot loop.
/// ASCII whitespace byte (may *start* a whitespace run).
pub const CLASS_WHITESPACE: u8 = 1 << 0;
/// First byte of an unquoted identifier.
pub const CLASS_IDENTIFIER_START: u8 = 1 << 1;
/// Non-first byte of an unquoted identifier.
pub const CLASS_IDENTIFIER_CONTINUE: u8 = 1 << 2;
/// ASCII decimal digit.
pub const CLASS_DIGIT: u8 = 1 << 3;
/// Operator spelling byte.
pub const CLASS_OPERATOR: u8 = 1 << 4;
/// Whitespace-run *continuation* byte: it extends an already-open whitespace run
/// but cannot start one. SQLite's vertical tab is the sole member — SQLite's
/// tokenizer marks `0x0b` illegal as a token start (`aiClass[0x0b]` is not
/// `CC_SPACE`, so a lone or token-leading `\v` is an "unrecognized token") yet
/// `sqlite3Isspace(0x0b)` is true, so a `\v` is swallowed when it *follows* another
/// space in a run (measured: `"\x20\x0b"` accepts, `"\x0b"` and `"SELECT\x0b\x20 1"`
/// reject). The scanner reads this in the run-extension predicate only, never at
/// run entry (see the tokenizer's `skip_trivia`).
pub const CLASS_WHITESPACE_CONTINUE: u8 = 1 << 5;
/// Structural punctuation byte.
pub const CLASS_PUNCTUATION: u8 = 1 << 6;
/// Statement-boundary "trim" whitespace: it folds as whitespace like
/// [`CLASS_WHITESPACE`], but is legal *only* as leading or trailing trivia of a
/// statement (adjacent to the input start, a `;` separator, or the input end) — a
/// member wedged between two content items of one statement is a hard error; comments
/// count as content items for this boundary rule.
/// DuckDB's vertical tab is the sole member: DuckDB trims `0x0b` at each
/// `;`-segment's edges but its statement parser rejects an interior `\v` (measured:
/// `"\x0bSELECT 1"`, `"SELECT 1\x0b"`, `"SELECT 1;\x0b"` accept; `"SELECT\x0b1"`,
/// `"SELECT 1\x0bSELECT 2"`, `"SELECT\x20\x0b1"` reject). The tokenizer's
/// `skip_trivia` folds the byte, then rejects a boundary byte that a content token
/// both precedes and follows.
pub const CLASS_WHITESPACE_BOUNDARY: u8 = 1 << 7;
/// Raw byte-class table storage.
pub type ByteClassTable = ;
/// Const byte-class table shared by M1 dialects.
pub const BYTE_CLASSES: ByteClassTable = build_byte_classes;
/// Dialect-owned byte-class data for the tokenizer hot loop.
/// Standard byte classes used by the builtin dialect presets.
pub const STANDARD_BYTE_CLASSES: ByteClasses = STANDARD;
/// PostgreSQL byte classes: [`STANDARD_BYTE_CLASSES`] with the vertical tab
/// (`0x0b`, `\v`) added to [`CLASS_WHITESPACE`].
///
/// PostgreSQL's flex scanner folds its full `space` set `[ \t\n\r\f\v]` as ignorable
/// whitespace. The vertical tab is the one member the shared [`STANDARD_BYTE_CLASSES`]
/// table omits: that table derives whitespace from Rust's [`u8::is_ascii_whitespace`],
/// which covers `\t \n \x0c \r <space>` but not `0x0b`. Probing the engines directly
/// shows the vertical tab is *dialect-specific* rather than a shared control byte:
/// PostgreSQL folds it as ordinary whitespace everywhere (a lone `0x0b` parses as an
/// empty statement, `SELECT\x0b1` as `SELECT 1`), whereas SQLite folds it only as a
/// run continuation and DuckDB only as statement-trim (their own tables — see
/// [`SQLITE_BYTE_CLASSES`] / [`DUCKDB_BYTE_CLASSES`]), and ANSI keeps it strict. So
/// full whitespace-class membership rides only PostgreSQL's (and MySQL's) table.
pub const POSTGRES_BYTE_CLASSES: ByteClasses =
STANDARD_BYTE_CLASSES.with_class;
/// MySQL byte classes: [`STANDARD_BYTE_CLASSES`] with the vertical tab
/// (`0x0b`, `\v`) added to [`CLASS_WHITESPACE`], exactly as [`POSTGRES_BYTE_CLASSES`].
///
/// MySQL's tokenizer folds the same flex-style `space` set `[ \t\n\r\f\v]` as ignorable
/// whitespace, and the vertical tab is the one member the shared [`STANDARD_BYTE_CLASSES`]
/// table omits (that table derives whitespace from Rust's [`u8::is_ascii_whitespace`],
/// which covers `\t \n \x0c \r <space>` but not `0x0b`). Probing the live `mysql:8` oracle
/// directly confirms it: a lone `0x0b` prepares as an empty statement and `SELECT\x0b1`
/// prepares as `SELECT 1`, so MySQL folds it as ordinary whitespace like PostgreSQL —
/// the second dialect to layer it fully onto the baseline. SQLite and DuckDB fold it only
/// position-dependently (their own tables — see [`SQLITE_BYTE_CLASSES`] /
/// [`DUCKDB_BYTE_CLASSES`]), and ANSI stays strict.
pub const MYSQL_BYTE_CLASSES: ByteClasses =
STANDARD_BYTE_CLASSES.with_class;
/// SQLite byte classes: [`STANDARD_BYTE_CLASSES`] with the vertical tab (`0x0b`,
/// `\v`) marked [`CLASS_WHITESPACE_CONTINUE`] — a whitespace-run *continuation* that
/// cannot *start* a run.
///
/// SQLite does not fold the vertical tab as ordinary whitespace the way PostgreSQL
/// and MySQL do; its rule is position-dependent, measured against the bundled
/// `rusqlite` (3.x) oracle. SQLite's tokenizer classes `0x0b` as illegal to *begin*
/// a token (`aiClass[0x0b]` is not `CC_SPACE`, so a lone or token-leading `\v` is an
/// "unrecognized token"), yet `sqlite3Isspace(0x0b)` is true, so the space-run loop
/// swallows a `\v` that *follows* another whitespace byte. Net: `"\x20\x0b"` and
/// `"SELECT\x20\x0b1"` accept (the `\v` rides an open run), while lone `"\x0b"`,
/// `"\x0bSELECT 1"`, and `"SELECT\x0b1"` reject (the `\v` would have to start a run).
/// The tokenizer models this by reading `CLASS_WHITESPACE_CONTINUE` only in the
/// run-extension predicate, never at run entry, so no other dialect is affected.
pub const SQLITE_BYTE_CLASSES: ByteClasses =
STANDARD_BYTE_CLASSES.with_class;
/// DuckDB byte classes: [`STANDARD_BYTE_CLASSES`] with the vertical tab (`0x0b`,
/// `\v`) marked both [`CLASS_WHITESPACE`] and [`CLASS_WHITESPACE_BOUNDARY`] — it
/// folds as whitespace but is legal only as statement-boundary trim.
///
/// DuckDB's rule, measured against the linked `libduckdb` (1.5.x) oracle, is also
/// position-dependent but *different* from SQLite's: DuckDB trims `0x0b` at the
/// leading and trailing edges of every `;`-delimited statement (so `"\x0b"`,
/// `"\x0bSELECT 1"`, `"SELECT 1\x0b"`, `"SELECT 1;\x0b"`, and `"SELECT 1;\x0bSELECT 2"`
/// all accept) while its statement parser rejects a `\v` interior to a statement's
/// content (`"SELECT\x0b1"`, `"SELECT 1\x0bSELECT 2"`, and even `"SELECT\x20\x0b1"`
/// reject — unlike SQLite, adjacency to a real space does not rescue an interior
/// `\v`). The tokenizer folds the byte as whitespace, then the
/// [`CLASS_WHITESPACE_BOUNDARY`] guard rejects a boundary byte that statement content
/// (including comments) both precedes and follows.
pub const DUCKDB_BYTE_CLASSES: ByteClasses =
STANDARD_BYTE_CLASSES.with_class;
/// Return all classes for `byte`.
pub const
/// Return true if `byte` has any class in `mask`.
pub const
const
const
const
const
const