@prisma-next/psl-parser 0.13.0-dev.20 → 0.13.0-dev.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,89 @@
1
+ const LINE_FEED = 10;
2
+
3
+ export interface Position {
4
+ readonly line: number;
5
+ readonly character: number;
6
+ }
7
+
8
+ export interface Range {
9
+ readonly start: Position;
10
+ readonly end: Position;
11
+ }
12
+
13
+ export class SourceFile {
14
+ readonly #text: string;
15
+ readonly #lineStarts: readonly number[];
16
+
17
+ constructor(text: string) {
18
+ this.#text = text;
19
+ const lineStarts: number[] = [0];
20
+ for (let offset = 0; offset < text.length; offset++) {
21
+ if (text.charCodeAt(offset) === LINE_FEED) {
22
+ lineStarts.push(offset + 1);
23
+ }
24
+ }
25
+ this.#lineStarts = lineStarts;
26
+ }
27
+
28
+ get text(): string {
29
+ return this.#text;
30
+ }
31
+
32
+ get length(): number {
33
+ return this.#text.length;
34
+ }
35
+
36
+ get lineCount(): number {
37
+ return this.#lineStarts.length;
38
+ }
39
+
40
+ lineStartOffsets(): readonly number[] {
41
+ return this.#lineStarts;
42
+ }
43
+
44
+ positionAt(offset: number): Position {
45
+ const clamped = clamp(offset, 0, this.#text.length);
46
+ const line = this.#lineIndexAt(clamped);
47
+ return { line, character: clamped - this.#lineStartAt(line) };
48
+ }
49
+
50
+ offsetAt(position: Position): number {
51
+ const line = clamp(position.line, 0, this.#lineStarts.length - 1);
52
+ const lineStart = this.#lineStartAt(line);
53
+ const lineEnd = this.#lineEndAt(line);
54
+ return clamp(lineStart + position.character, lineStart, lineEnd);
55
+ }
56
+
57
+ #lineStartAt(line: number): number {
58
+ return this.#lineStarts[line] ?? 0;
59
+ }
60
+
61
+ #lineEndAt(line: number): number {
62
+ return line + 1 < this.#lineStarts.length ? this.#lineStartAt(line + 1) - 1 : this.#text.length;
63
+ }
64
+
65
+ #lineIndexAt(offset: number): number {
66
+ const lineStarts = this.#lineStarts;
67
+ let low = 0;
68
+ let high = lineStarts.length - 1;
69
+ while (low < high) {
70
+ const mid = (low + high + 1) >>> 1;
71
+ if ((lineStarts[mid] ?? 0) <= offset) {
72
+ low = mid;
73
+ } else {
74
+ high = mid - 1;
75
+ }
76
+ }
77
+ return low;
78
+ }
79
+ }
80
+
81
+ function clamp(value: number, min: number, max: number): number {
82
+ if (value < min) {
83
+ return min;
84
+ }
85
+ if (value > max) {
86
+ return max;
87
+ }
88
+ return value;
89
+ }
@@ -18,14 +18,14 @@ export type NamespaceMemberAst =
18
18
  | ModelDeclarationAst
19
19
  | EnumDeclarationAst
20
20
  | CompositeTypeDeclarationAst
21
- | BlockDeclarationAst;
21
+ | GenericBlockDeclarationAst;
22
22
 
23
23
  function castNamespaceMember(node: SyntaxNode): NamespaceMemberAst | undefined {
24
24
  return (
25
25
  ModelDeclarationAst.cast(node) ??
26
26
  EnumDeclarationAst.cast(node) ??
27
27
  CompositeTypeDeclarationAst.cast(node) ??
28
- BlockDeclarationAst.cast(node)
28
+ GenericBlockDeclarationAst.cast(node)
29
29
  );
30
30
  }
31
31
 
@@ -219,7 +219,7 @@ export class TypesBlockAst implements AstNode {
219
219
  }
220
220
  }
221
221
 
222
- export class BlockDeclarationAst implements AstNode {
222
+ export class GenericBlockDeclarationAst implements AstNode {
223
223
  readonly syntax: SyntaxNode;
224
224
 
225
225
  constructor(syntax: SyntaxNode) {
@@ -246,8 +246,10 @@ export class BlockDeclarationAst implements AstNode {
246
246
  yield* filterChildren(this.syntax, KeyValuePairAst.cast);
247
247
  }
248
248
 
249
- static cast(node: SyntaxNode): BlockDeclarationAst | undefined {
250
- return node.kind === 'BlockDeclaration' ? new BlockDeclarationAst(node) : undefined;
249
+ static cast(node: SyntaxNode): GenericBlockDeclarationAst | undefined {
250
+ return node.kind === 'GenericBlockDeclaration'
251
+ ? new GenericBlockDeclarationAst(node)
252
+ : undefined;
251
253
  }
252
254
  }
253
255
 
@@ -56,6 +56,78 @@ export class ArrayLiteralAst implements AstNode {
56
56
  }
57
57
  }
58
58
 
59
+ const HEX = /^[0-9a-fA-F]+$/;
60
+
61
+ function decodeFixedHex(raw: string, start: number, width: number): string | undefined {
62
+ if (start + width > raw.length) return undefined;
63
+ const hex = raw.slice(start, start + width);
64
+ if (!HEX.test(hex)) return undefined;
65
+ return String.fromCharCode(Number.parseInt(hex, 16));
66
+ }
67
+
68
+ function decodeStringLiteral(raw: string): string {
69
+ let out = '';
70
+ let i = 0;
71
+ while (i < raw.length) {
72
+ const ch = raw.charAt(i);
73
+ if (ch !== '\\' || i + 1 >= raw.length) {
74
+ out += ch;
75
+ i++;
76
+ continue;
77
+ }
78
+ const next = raw.charAt(i + 1);
79
+ switch (next) {
80
+ case 'n':
81
+ out += '\n';
82
+ i += 2;
83
+ continue;
84
+ case 'r':
85
+ out += '\r';
86
+ i += 2;
87
+ continue;
88
+ case 't':
89
+ out += '\t';
90
+ i += 2;
91
+ continue;
92
+ case '"':
93
+ out += '"';
94
+ i += 2;
95
+ continue;
96
+ case '\\':
97
+ out += '\\';
98
+ i += 2;
99
+ continue;
100
+ case 'x': {
101
+ const decoded = decodeFixedHex(raw, i + 2, 2);
102
+ if (decoded === undefined) {
103
+ out += '\\x';
104
+ i += 2;
105
+ continue;
106
+ }
107
+ out += decoded;
108
+ i += 4;
109
+ continue;
110
+ }
111
+ case 'u': {
112
+ const decoded = decodeFixedHex(raw, i + 2, 4);
113
+ if (decoded === undefined) {
114
+ out += '\\u';
115
+ i += 2;
116
+ continue;
117
+ }
118
+ out += decoded;
119
+ i += 6;
120
+ continue;
121
+ }
122
+ default:
123
+ out += `\\${next}`;
124
+ i += 2;
125
+ continue;
126
+ }
127
+ }
128
+ return out;
129
+ }
130
+
59
131
  export class StringLiteralExprAst implements AstNode {
60
132
  readonly syntax: SyntaxNode;
61
133
 
@@ -70,23 +142,7 @@ export class StringLiteralExprAst implements AstNode {
70
142
  value(): string | undefined {
71
143
  const tok = this.token();
72
144
  if (!tok) return undefined;
73
- const raw = tok.text.slice(1, -1);
74
- return raw.replace(/\\(.)/g, (_match, char: string) => {
75
- switch (char) {
76
- case 'n':
77
- return '\n';
78
- case 'r':
79
- return '\r';
80
- case 't':
81
- return '\t';
82
- case '"':
83
- return '"';
84
- case '\\':
85
- return '\\';
86
- default:
87
- return `\\${char}`;
88
- }
89
- });
145
+ return decodeStringLiteral(tok.text.slice(1, -1));
90
146
  }
91
147
 
92
148
  static cast(node: SyntaxNode): StringLiteralExprAst | undefined {
@@ -140,12 +196,82 @@ export class BooleanLiteralExprAst implements AstNode {
140
196
  }
141
197
  }
142
198
 
199
+ export class ObjectLiteralExprAst implements AstNode {
200
+ readonly syntax: SyntaxNode;
201
+
202
+ constructor(syntax: SyntaxNode) {
203
+ this.syntax = syntax;
204
+ }
205
+
206
+ lbrace(): Token | undefined {
207
+ return findChildToken(this.syntax, 'LBrace');
208
+ }
209
+
210
+ rbrace(): Token | undefined {
211
+ return findChildToken(this.syntax, 'RBrace');
212
+ }
213
+
214
+ *fields(): Iterable<ObjectFieldAst> {
215
+ yield* filterChildren(this.syntax, ObjectFieldAst.cast);
216
+ }
217
+
218
+ static cast(node: SyntaxNode): ObjectLiteralExprAst | undefined {
219
+ return node.kind === 'ObjectLiteralExpr' ? new ObjectLiteralExprAst(node) : undefined;
220
+ }
221
+ }
222
+
223
+ export class ObjectFieldAst implements AstNode {
224
+ readonly syntax: SyntaxNode;
225
+
226
+ constructor(syntax: SyntaxNode) {
227
+ this.syntax = syntax;
228
+ }
229
+
230
+ key(): IdentifierAst | undefined {
231
+ for (const child of this.syntax.children()) {
232
+ if (!(child instanceof SyntaxNode)) {
233
+ if (child.kind === 'Colon') break;
234
+ continue;
235
+ }
236
+ return IdentifierAst.cast(child);
237
+ }
238
+ return undefined;
239
+ }
240
+
241
+ colon(): Token | undefined {
242
+ return findChildToken(this.syntax, 'Colon');
243
+ }
244
+
245
+ value(): ExpressionAst | undefined {
246
+ if (this.colon()) {
247
+ let pastColon = false;
248
+ for (const child of this.syntax.children()) {
249
+ if (!(child instanceof SyntaxNode)) {
250
+ if (child.kind === 'Colon') pastColon = true;
251
+ continue;
252
+ }
253
+ if (pastColon) {
254
+ const expr = castExpression(child);
255
+ if (expr) return expr;
256
+ }
257
+ }
258
+ return undefined;
259
+ }
260
+ return findFirstChild(this.syntax, castExpression);
261
+ }
262
+
263
+ static cast(node: SyntaxNode): ObjectFieldAst | undefined {
264
+ return node.kind === 'ObjectField' ? new ObjectFieldAst(node) : undefined;
265
+ }
266
+ }
267
+
143
268
  export type ExpressionAst =
144
269
  | FunctionCallAst
145
270
  | ArrayLiteralAst
146
271
  | StringLiteralExprAst
147
272
  | NumberLiteralExprAst
148
273
  | BooleanLiteralExprAst
274
+ | ObjectLiteralExprAst
149
275
  | IdentifierAst;
150
276
 
151
277
  export function castExpression(node: SyntaxNode): ExpressionAst | undefined {
@@ -155,6 +281,7 @@ export function castExpression(node: SyntaxNode): ExpressionAst | undefined {
155
281
  StringLiteralExprAst.cast(node) ??
156
282
  NumberLiteralExprAst.cast(node) ??
157
283
  BooleanLiteralExprAst.cast(node) ??
284
+ ObjectLiteralExprAst.cast(node) ??
158
285
  IdentifierAst.cast(node)
159
286
  );
160
287
  }
@@ -5,7 +5,10 @@ export type SyntaxKind =
5
5
  | 'CompositeTypeDeclaration'
6
6
  | 'Namespace'
7
7
  | 'TypesBlock'
8
- | 'BlockDeclaration'
8
+ // The generic/extension block node — the `kw [name] { key = value }` form
9
+ // produced by `parseGenericBlock`. Deliberately distinct from the reserved
10
+ // `model`/`enum`/`namespace`/`type`/`types` declarations above.
11
+ | 'GenericBlockDeclaration'
9
12
  | 'FieldDeclaration'
10
13
  | 'EnumValueDeclaration'
11
14
  | 'NamedTypeDeclaration'
@@ -20,4 +23,6 @@ export type SyntaxKind =
20
23
  | 'ArrayLiteral'
21
24
  | 'StringLiteralExpr'
22
25
  | 'NumberLiteralExpr'
23
- | 'BooleanLiteralExpr';
26
+ | 'BooleanLiteralExpr'
27
+ | 'ObjectLiteralExpr'
28
+ | 'ObjectField';
package/src/tokenizer.ts CHANGED
@@ -86,6 +86,7 @@ function scan(source: string, pos: number): Token {
86
86
  scanWhitespace(source, pos) ??
87
87
  scanComment(source, pos) ??
88
88
  scanAt(source, pos) ??
89
+ scanKeywordNumber(source, pos) ??
89
90
  scanIdent(source, pos) ??
90
91
  scanNumber(source, pos) ??
91
92
  scanString(source, pos) ??
@@ -151,6 +152,22 @@ function scanIdent(source: string, pos: number): Token | undefined {
151
152
  return { kind: 'Ident', text: source.slice(pos, end) };
152
153
  }
153
154
 
155
+ const KEYWORD_NUMBERS = ['-Infinity', 'Infinity', 'NaN'] as const;
156
+
157
+ // `NaN`, `Infinity`, and `-Infinity` are numeric literals, not identifiers.
158
+ // They must match before `scanIdent` (which would otherwise claim the
159
+ // identifier-led words) and are word-bounded: a following identifier-part char
160
+ // (so `Infinityx` / `NaNxyz`) keeps the run an `Ident` rather than a number.
161
+ function scanKeywordNumber(source: string, pos: number): Token | undefined {
162
+ for (const word of KEYWORD_NUMBERS) {
163
+ if (!source.startsWith(word, pos)) continue;
164
+ const after = readChar(source, pos + word.length);
165
+ if (after !== '' && isIdentPart(after)) return undefined;
166
+ return { kind: 'NumberLiteral', text: word };
167
+ }
168
+ return undefined;
169
+ }
170
+
154
171
  function scanNumber(source: string, pos: number): Token | undefined {
155
172
  let end = pos;
156
173
  if (source.charAt(end) === '-') {
@@ -195,6 +212,37 @@ function scanString(source: string, pos: number): Token | undefined {
195
212
  return { kind: 'StringLiteral', text: source.slice(pos, end) };
196
213
  }
197
214
 
215
+ /**
216
+ * Whether a `StringLiteral` token's text is properly closed. `scanString` emits
217
+ * the same `StringLiteral` kind for both well-formed and unterminated strings —
218
+ * it stops at a newline or EOF when no closing quote is found — so callers that
219
+ * need to distinguish the two ask here.
220
+ *
221
+ * Because `scanString` stops at the *first* unescaped `"`, the only quote whose
222
+ * escaping can be in question is the **last character**: the text is terminated
223
+ * iff it opens with `"`, ends with `"`, and that closing `"` is not escaped.
224
+ * Under the `\\`-escapes-the-next-character rule, a `"` is unescaped iff an
225
+ * **even** number of backslashes immediately precede it — each `\\` pair cancels,
226
+ * and an odd run leaves the final `\` escaping the quote. So it suffices to
227
+ * count the trailing backslash run; no full re-scan is needed:
228
+ *
229
+ * - `"ok"` → 0 backslashes (even) → closing quote stands → terminated
230
+ * - `"a\"` → 1 backslash (odd) → the `"` is escaped → unterminated
231
+ * - `"a\\"` → 2 backslashes (even) → escaped `\`, real `"` → terminated
232
+ *
233
+ * A lone `"` (length 1) or a text with no closing `"` is unterminated.
234
+ */
235
+ export function isTerminatedStringLiteral(text: string): boolean {
236
+ if (text.length < 2 || text.charAt(0) !== '"' || text.charAt(text.length - 1) !== '"') {
237
+ return false;
238
+ }
239
+ let backslashes = 0;
240
+ for (let i = text.length - 2; i >= 1 && text.charAt(i) === '\\'; i--) {
241
+ backslashes++;
242
+ }
243
+ return backslashes % 2 === 0;
244
+ }
245
+
198
246
  function scanPunctuation(source: string, pos: number): Token | undefined {
199
247
  const kind = PUNCTUATION[source.charAt(pos)];
200
248
  if (kind === undefined) return undefined;
@@ -1 +0,0 @@
1
- {"version":3,"file":"tokenizer.mjs","names":["#source","#buffer","#pos","#scanNext"],"sources":["../src/tokenizer.ts"],"sourcesContent":["export type TokenKind =\n | 'Ident'\n | 'StringLiteral'\n | 'NumberLiteral'\n | 'At'\n | 'DoubleAt'\n | 'LBrace'\n | 'RBrace'\n | 'LParen'\n | 'RParen'\n | 'LBracket'\n | 'RBracket'\n | 'Equals'\n | 'Question'\n | 'Dot'\n | 'Comma'\n | 'Colon'\n | 'Whitespace'\n | 'Newline'\n | 'Comment'\n | 'Invalid'\n | 'Eof';\n\nexport interface Token {\n readonly kind: TokenKind;\n readonly text: string;\n}\n\nexport class Tokenizer {\n readonly #source: string;\n #pos: number;\n readonly #buffer: Token[];\n\n constructor(source: string) {\n this.#source = source;\n this.#pos = 0;\n this.#buffer = [];\n }\n\n next(): Token {\n const next = this.#buffer.shift();\n if (next) {\n return next;\n }\n return this.#scanNext();\n }\n\n peek(offset = 0): Token {\n if (offset > this.#buffer.length) {\n const last = this.#buffer.at(-1);\n if (last?.kind === 'Eof') {\n return last;\n }\n }\n\n const token = this.#buffer[offset];\n if (token) {\n return token;\n }\n\n while (this.#buffer.length <= offset) {\n const token = this.#scanNext();\n if (token.kind === 'Eof') {\n return token;\n }\n this.#buffer.push(token);\n }\n\n return this.#buffer[offset] as Token;\n }\n\n #scanNext(): Token {\n const token = scan(this.#source, this.#pos);\n this.#pos += token.text.length;\n return token;\n }\n}\n\nfunction scan(source: string, pos: number): Token {\n if (pos >= source.length) {\n return { kind: 'Eof', text: '' };\n }\n\n return (\n scanNewline(source, pos) ??\n scanWhitespace(source, pos) ??\n scanComment(source, pos) ??\n scanAt(source, pos) ??\n scanIdent(source, pos) ??\n scanNumber(source, pos) ??\n scanString(source, pos) ??\n scanPunctuation(source, pos) ?? {\n kind: 'Invalid' as const,\n text: readChar(source, pos),\n }\n );\n}\n\nfunction scanNewline(source: string, pos: number): Token | undefined {\n const ch = source.charAt(pos);\n if (ch !== '\\r' && ch !== '\\n') return undefined;\n if (ch === '\\r' && source.charAt(pos + 1) === '\\n') {\n return { kind: 'Newline', text: '\\r\\n' };\n }\n return { kind: 'Newline', text: ch };\n}\n\nfunction scanWhitespace(source: string, pos: number): Token | undefined {\n const ch = source.charAt(pos);\n if (ch !== ' ' && ch !== '\\t') return undefined;\n let end = pos + 1;\n while (end < source.length) {\n const c = source.charAt(end);\n if (c !== ' ' && c !== '\\t') break;\n end++;\n }\n return { kind: 'Whitespace', text: source.slice(pos, end) };\n}\n\nfunction scanComment(source: string, pos: number): Token | undefined {\n if (source.charAt(pos) !== '/' || source.charAt(pos + 1) !== '/') return undefined;\n let end = pos + 2;\n while (end < source.length) {\n const c = source.charAt(end);\n if (c === '\\n' || c === '\\r') break;\n end++;\n }\n return { kind: 'Comment', text: source.slice(pos, end) };\n}\n\nfunction scanAt(source: string, pos: number): Token | undefined {\n if (source.charAt(pos) !== '@') return undefined;\n if (source.charAt(pos + 1) === '@') {\n return { kind: 'DoubleAt', text: '@@' };\n }\n return { kind: 'At', text: '@' };\n}\n\nfunction scanIdent(source: string, pos: number): Token | undefined {\n const ch = readChar(source, pos);\n if (!isIdentStart(ch)) return undefined;\n let end = pos + ch.length;\n while (end < source.length) {\n const c = readChar(source, end);\n if (isIdentPart(c)) {\n end += c.length;\n } else {\n break;\n }\n }\n return { kind: 'Ident', text: source.slice(pos, end) };\n}\n\nfunction scanNumber(source: string, pos: number): Token | undefined {\n let end = pos;\n if (source.charAt(end) === '-') {\n if (end + 1 >= source.length || !isDigit(source.charAt(end + 1))) return undefined;\n end++;\n } else if (!isDigit(source.charAt(end))) {\n return undefined;\n }\n end++;\n while (end < source.length && isDigit(source.charAt(end))) {\n end++;\n }\n if (source.charAt(end) === '.' && end + 1 < source.length && isDigit(source.charAt(end + 1))) {\n end++; // consume the dot\n while (end < source.length && isDigit(source.charAt(end))) {\n end++;\n }\n }\n return { kind: 'NumberLiteral', text: source.slice(pos, end) };\n}\n\nfunction scanString(source: string, pos: number): Token | undefined {\n if (source.charAt(pos) !== '\"') return undefined;\n let end = pos + 1;\n while (end < source.length) {\n const c = source.charAt(end);\n if (c === '\\\\' && end + 1 < source.length) {\n end += 2; // skip escape sequence\n continue;\n }\n if (c === '\"') {\n end++; // include closing quote\n return { kind: 'StringLiteral', text: source.slice(pos, end) };\n }\n if (c === '\\n' || c === '\\r') {\n // Unterminated: stop before newline\n return { kind: 'StringLiteral', text: source.slice(pos, end) };\n }\n end++;\n }\n // Unterminated at EOF\n return { kind: 'StringLiteral', text: source.slice(pos, end) };\n}\n\nfunction scanPunctuation(source: string, pos: number): Token | undefined {\n const kind = PUNCTUATION[source.charAt(pos)];\n if (kind === undefined) return undefined;\n return { kind, text: source.charAt(pos) };\n}\n\nfunction readChar(source: string, pos: number): string {\n const cp = source.codePointAt(pos);\n return cp !== undefined ? String.fromCodePoint(cp) : '';\n}\n\nfunction isIdentStart(ch: string): boolean {\n return /\\p{L}/u.test(ch) || ch === '_';\n}\n\nfunction isIdentPart(ch: string): boolean {\n return isIdentStart(ch) || isDigit(ch) || ch === '-';\n}\n\nfunction isDigit(ch: string): boolean {\n return ch >= '0' && ch <= '9';\n}\n\nconst PUNCTUATION: Record<string, TokenKind> = {\n '{': 'LBrace',\n '}': 'RBrace',\n '(': 'LParen',\n ')': 'RParen',\n '[': 'LBracket',\n ']': 'RBracket',\n '=': 'Equals',\n '?': 'Question',\n '.': 'Dot',\n ',': 'Comma',\n ':': 'Colon',\n};\n"],"mappings":"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"}