@prisma-next/psl-parser 0.9.0-dev.8 → 0.9.0-dev.9

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.
package/dist/index.d.mts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { t as parsePslDocument } from "./parser-Bjdnhl7C.mjs";
2
- import { ParsePslDocumentInput, ParsePslDocumentResult, PslAttribute, PslAttribute as PslAttribute$1, PslAttributeArgument, PslAttributeNamedArgument, PslAttributePositionalArgument, PslAttributeTarget, PslCompositeType, PslDefaultFunctionValue, PslDefaultLiteralValue, PslDefaultValue, PslDiagnostic, PslDiagnosticCode, PslDocumentAst, PslEnum, PslEnumValue, PslField, PslFieldAttribute, PslModel, PslModelAttribute, PslNamedTypeDeclaration, PslPosition, PslSpan, PslTypeConstructorCall, PslTypesBlock } from "@prisma-next/framework-components/psl-ast";
2
+ import { ParsePslDocumentInput, ParsePslDocumentResult, PslAttribute, PslAttribute as PslAttribute$1, PslAttributeArgument, PslAttributeNamedArgument, PslAttributePositionalArgument, PslAttributeTarget, PslCompositeType, PslDefaultFunctionValue, PslDefaultLiteralValue, PslDefaultValue, PslDiagnostic, PslDiagnosticCode, PslDocumentAst, PslEnum, PslEnumValue, PslField, PslFieldAttribute, PslModel, PslModelAttribute, PslNamedTypeDeclaration, PslNamespace, PslPosition, PslSpan, PslTypeConstructorCall, PslTypesBlock } from "@prisma-next/framework-components/psl-ast";
3
3
 
4
4
  //#region src/attribute-helpers.d.ts
5
5
  declare function getPositionalArgument(attribute: PslAttribute$1, index?: number): string | undefined;
6
6
  declare function parseQuotedStringLiteral(value: string): string | undefined;
7
7
  //#endregion
8
- export { type ParsePslDocumentInput, type ParsePslDocumentResult, type PslAttribute, type PslAttributeArgument, type PslAttributeNamedArgument, type PslAttributePositionalArgument, type PslAttributeTarget, type PslCompositeType, type PslDefaultFunctionValue, type PslDefaultLiteralValue, type PslDefaultValue, type PslDiagnostic, type PslDiagnosticCode, type PslDocumentAst, type PslEnum, type PslEnumValue, type PslField, type PslFieldAttribute, type PslModel, type PslModelAttribute, type PslNamedTypeDeclaration, type PslPosition, type PslSpan, type PslTypeConstructorCall, type PslTypesBlock, getPositionalArgument, parsePslDocument, parseQuotedStringLiteral };
8
+ export { type ParsePslDocumentInput, type ParsePslDocumentResult, type PslAttribute, type PslAttributeArgument, type PslAttributeNamedArgument, type PslAttributePositionalArgument, type PslAttributeTarget, type PslCompositeType, type PslDefaultFunctionValue, type PslDefaultLiteralValue, type PslDefaultValue, type PslDiagnostic, type PslDiagnosticCode, type PslDocumentAst, type PslEnum, type PslEnumValue, type PslField, type PslFieldAttribute, type PslModel, type PslModelAttribute, type PslNamedTypeDeclaration, type PslNamespace, type PslPosition, type PslSpan, type PslTypeConstructorCall, type PslTypesBlock, getPositionalArgument, parsePslDocument, parseQuotedStringLiteral };
9
9
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as parsePslDocument } from "./parser-1DZHweIq.mjs";
1
+ import { t as parsePslDocument } from "./parser-R7ldFfcr.mjs";
2
2
  //#region src/attribute-helpers.ts
3
3
  function getPositionalArgument(attribute, index = 0) {
4
4
  return attribute.args.filter((arg) => arg.kind === "positional")[index]?.value;
@@ -1 +1 @@
1
- {"version":3,"file":"parser-Bjdnhl7C.d.mts","names":[],"sources":["../src/parser.ts"],"mappings":";;;iBAkDgB,gBAAA,CAAiB,KAAA,EAAO,qBAAA,GAAwB,sBAAA"}
1
+ {"version":3,"file":"parser-Bjdnhl7C.d.mts","names":[],"sources":["../src/parser.ts"],"mappings":";;;iBAoDgB,gBAAA,CAAiB,KAAA,EAAO,qBAAA,GAAwB,sBAAA"}
@@ -1,3 +1,4 @@
1
+ import { UNSPECIFIED_PSL_NAMESPACE_ID } from "@prisma-next/framework-components/psl-ast";
1
2
  import { ifDefined } from "@prisma-next/utils/defined";
2
3
  //#region src/parser.ts
3
4
  const SCALAR_TYPES = new Set([
@@ -23,79 +24,125 @@ function parsePslDocument(input) {
23
24
  lineOffsets,
24
25
  diagnostics
25
26
  };
26
- const models = [];
27
- const enums = [];
28
- const compositeTypes = [];
29
- let typesBlock;
30
- let lineIndex = 0;
31
- while (lineIndex < lines.length) {
32
- const line = stripInlineComment(lines[lineIndex] ?? "").trim();
33
- if (line.length === 0) {
34
- lineIndex += 1;
35
- continue;
27
+ const namespaceOrder = [];
28
+ const namespacesByName = /* @__PURE__ */ new Map();
29
+ const getOrCreateNamespace = (name, spanIfNew) => {
30
+ let acc = namespacesByName.get(name);
31
+ if (!acc) {
32
+ acc = {
33
+ name,
34
+ models: [],
35
+ enums: [],
36
+ compositeTypes: [],
37
+ span: spanIfNew
38
+ };
39
+ namespacesByName.set(name, acc);
40
+ namespaceOrder.push(name);
36
41
  }
37
- const modelMatch = line.match(/^model\s+([A-Za-z_]\w*)\s*\{$/);
38
- if (modelMatch) {
39
- const bounds = findBlockBounds(context, lineIndex);
40
- const name = modelMatch[1] ?? "";
41
- if (name.length === 0) {
42
+ return acc;
43
+ };
44
+ let typesBlock;
45
+ const parseBody = (startLine, endLineExclusive, currentNamespaceName, isInsideNamespace) => {
46
+ let lineIndex = startLine;
47
+ while (lineIndex < endLineExclusive) {
48
+ const line = stripInlineComment(context.lines[lineIndex] ?? "").trim();
49
+ if (line.length === 0) {
50
+ lineIndex += 1;
51
+ continue;
52
+ }
53
+ const modelMatch = line.match(/^model\s+([A-Za-z_]\w*)\s*\{$/);
54
+ if (modelMatch) {
55
+ const bounds = findBlockBounds(context, lineIndex);
56
+ const name = modelMatch[1] ?? "";
57
+ if (name.length > 0) getOrCreateNamespace(currentNamespaceName, createTrimmedLineSpan(context, lineIndex)).models.push(parseModelBlock(context, name, bounds));
42
58
  lineIndex = bounds.endLine + 1;
43
59
  continue;
44
60
  }
45
- models.push(parseModelBlock(context, name, bounds));
46
- lineIndex = bounds.endLine + 1;
47
- continue;
48
- }
49
- const enumMatch = line.match(/^enum\s+([A-Za-z_]\w*)\s*\{$/);
50
- if (enumMatch) {
51
- const bounds = findBlockBounds(context, lineIndex);
52
- const name = enumMatch[1] ?? "";
53
- if (name.length === 0) {
61
+ const enumMatch = line.match(/^enum\s+([A-Za-z_]\w*)\s*\{$/);
62
+ if (enumMatch) {
63
+ const bounds = findBlockBounds(context, lineIndex);
64
+ const name = enumMatch[1] ?? "";
65
+ if (name.length > 0) getOrCreateNamespace(currentNamespaceName, createTrimmedLineSpan(context, lineIndex)).enums.push(parseEnumBlock(context, name, bounds));
54
66
  lineIndex = bounds.endLine + 1;
55
67
  continue;
56
68
  }
57
- enums.push(parseEnumBlock(context, name, bounds));
58
- lineIndex = bounds.endLine + 1;
59
- continue;
60
- }
61
- const compositeTypeMatch = line.match(/^type\s+([A-Za-z_]\w*)\s*\{$/);
62
- if (compositeTypeMatch) {
63
- const bounds = findBlockBounds(context, lineIndex);
64
- const name = compositeTypeMatch[1] ?? "";
65
- if (name.length === 0) {
69
+ const compositeTypeMatch = line.match(/^type\s+([A-Za-z_]\w*)\s*\{$/);
70
+ if (compositeTypeMatch) {
71
+ const bounds = findBlockBounds(context, lineIndex);
72
+ const name = compositeTypeMatch[1] ?? "";
73
+ if (name.length > 0) getOrCreateNamespace(currentNamespaceName, createTrimmedLineSpan(context, lineIndex)).compositeTypes.push(parseCompositeTypeBlock(context, name, bounds));
66
74
  lineIndex = bounds.endLine + 1;
67
75
  continue;
68
76
  }
69
- compositeTypes.push(parseCompositeTypeBlock(context, name, bounds));
70
- lineIndex = bounds.endLine + 1;
71
- continue;
72
- }
73
- if (/^types\s*\{$/.test(line)) {
74
- const bounds = findBlockBounds(context, lineIndex);
75
- typesBlock = parseTypesBlock(context, bounds);
76
- lineIndex = bounds.endLine + 1;
77
- continue;
78
- }
79
- if (line.includes("{")) {
77
+ const namespaceMatch = line.match(/^namespace\s+([A-Za-z_]\w*)\s*\{$/);
78
+ if (namespaceMatch) {
79
+ const bounds = findBlockBounds(context, lineIndex);
80
+ const name = namespaceMatch[1] ?? "";
81
+ if (isInsideNamespace) pushDiagnostic(context, {
82
+ code: "PSL_INVALID_NAMESPACE_BLOCK",
83
+ message: `Recursive "namespace ${name}" block is not allowed; namespace blocks may not nest`,
84
+ span: createTrimmedLineSpan(context, lineIndex)
85
+ });
86
+ else if (name === UNSPECIFIED_PSL_NAMESPACE_ID) pushDiagnostic(context, {
87
+ code: "PSL_INVALID_NAMESPACE_BLOCK",
88
+ message: `Namespace name "${UNSPECIFIED_PSL_NAMESPACE_ID}" is reserved for the parser-synthesised bucket for top-level declarations`,
89
+ span: createTrimmedLineSpan(context, lineIndex)
90
+ });
91
+ else if (name.length > 0) {
92
+ getOrCreateNamespace(name, createTrimmedLineSpan(context, lineIndex));
93
+ parseBody(bounds.startLine + 1, bounds.endLine, name, true);
94
+ }
95
+ lineIndex = bounds.endLine + 1;
96
+ continue;
97
+ }
98
+ if (/^types\s*\{$/.test(line)) {
99
+ const bounds = findBlockBounds(context, lineIndex);
100
+ if (isInsideNamespace) pushDiagnostic(context, {
101
+ code: "PSL_INVALID_NAMESPACE_BLOCK",
102
+ message: "`types` blocks must be declared at the document top level, not inside a namespace block",
103
+ span: createTrimmedLineSpan(context, lineIndex)
104
+ });
105
+ else if (typesBlock !== void 0) pushDiagnostic(context, {
106
+ code: "PSL_INVALID_TYPES_MEMBER",
107
+ message: "Only one top-level `types` block is allowed per document",
108
+ span: createTrimmedLineSpan(context, lineIndex)
109
+ });
110
+ else typesBlock = parseTypesBlock(context, bounds);
111
+ lineIndex = bounds.endLine + 1;
112
+ continue;
113
+ }
114
+ if (line.includes("{")) {
115
+ pushDiagnostic(context, {
116
+ code: "PSL_UNSUPPORTED_TOP_LEVEL_BLOCK",
117
+ message: `Unsupported top-level block "${line.split(/\s+/)[0] ?? "block"}"`,
118
+ span: createTrimmedLineSpan(context, lineIndex)
119
+ });
120
+ lineIndex = findBlockBounds(context, lineIndex).endLine + 1;
121
+ continue;
122
+ }
80
123
  pushDiagnostic(context, {
81
124
  code: "PSL_UNSUPPORTED_TOP_LEVEL_BLOCK",
82
- message: `Unsupported top-level block "${line.split(/\s+/)[0] ?? "block"}"`,
125
+ message: `Unsupported top-level declaration "${line}"`,
83
126
  span: createTrimmedLineSpan(context, lineIndex)
84
127
  });
85
- lineIndex = findBlockBounds(context, lineIndex).endLine + 1;
86
- continue;
128
+ lineIndex += 1;
87
129
  }
88
- pushDiagnostic(context, {
89
- code: "PSL_UNSUPPORTED_TOP_LEVEL_BLOCK",
90
- message: `Unsupported top-level declaration "${line}"`,
91
- span: createTrimmedLineSpan(context, lineIndex)
92
- });
93
- lineIndex += 1;
130
+ };
131
+ parseBody(0, lines.length, UNSPECIFIED_PSL_NAMESPACE_ID, false);
132
+ const allModels = [];
133
+ const allEnums = [];
134
+ const allCompositeTypes = [];
135
+ for (const name of namespaceOrder) {
136
+ const acc = namespacesByName.get(name);
137
+ if (!acc) continue;
138
+ allModels.push(...acc.models);
139
+ allEnums.push(...acc.enums);
140
+ allCompositeTypes.push(...acc.compositeTypes);
94
141
  }
95
142
  const namedTypeNames = new Set((typesBlock?.declarations ?? []).map((declaration) => declaration.name));
96
- const modelNames = new Set(models.map((model) => model.name));
97
- const enumNames = new Set(enums.map((enumBlock) => enumBlock.name));
98
- const compositeTypeNames = new Set(compositeTypes.map((ct) => ct.name));
143
+ const modelNames = new Set(allModels.map((model) => model.name));
144
+ const enumNames = new Set(allEnums.map((enumBlock) => enumBlock.name));
145
+ const compositeTypeNames = new Set(allCompositeTypes.map((ct) => ct.name));
99
146
  for (const declaration of typesBlock?.declarations ?? []) {
100
147
  if (SCALAR_TYPES.has(declaration.name)) {
101
148
  pushDiagnostic(context, {
@@ -119,29 +166,42 @@ function parsePslDocument(input) {
119
166
  span: declaration.span
120
167
  });
121
168
  }
122
- const normalizedModels = models.map((model) => ({
123
- ...model,
124
- fields: model.fields.map((field) => {
125
- if (!namedTypeNames.has(field.typeName)) return field;
126
- if (field.attributes.some((attribute) => attribute.name === "relation") || modelNames.has(field.typeName) || enumNames.has(field.typeName) || compositeTypeNames.has(field.typeName) || SCALAR_TYPES.has(field.typeName)) return field;
127
- return {
128
- ...field,
129
- typeRef: field.typeName
130
- };
131
- })
132
- }));
169
+ const documentSpan = {
170
+ start: createPosition(context, 0, 0),
171
+ end: createPosition(context, Math.max(lines.length - 1, 0), (lines[Math.max(lines.length - 1, 0)] ?? "").length)
172
+ };
173
+ const namespaces = [];
174
+ for (const name of namespaceOrder) {
175
+ const acc = namespacesByName.get(name);
176
+ if (!acc) continue;
177
+ if (name === UNSPECIFIED_PSL_NAMESPACE_ID && acc.models.length === 0 && acc.enums.length === 0 && acc.compositeTypes.length === 0) continue;
178
+ const normalizedModels = acc.models.map((model) => ({
179
+ ...model,
180
+ fields: model.fields.map((field) => {
181
+ if (!namedTypeNames.has(field.typeName)) return field;
182
+ if (field.attributes.some((attribute) => attribute.name === "relation") || modelNames.has(field.typeName) || enumNames.has(field.typeName) || compositeTypeNames.has(field.typeName) || SCALAR_TYPES.has(field.typeName)) return field;
183
+ return {
184
+ ...field,
185
+ typeRef: field.typeName
186
+ };
187
+ })
188
+ }));
189
+ namespaces.push({
190
+ kind: "namespace",
191
+ name,
192
+ models: normalizedModels,
193
+ enums: acc.enums,
194
+ compositeTypes: acc.compositeTypes,
195
+ span: acc.span ?? documentSpan
196
+ });
197
+ }
133
198
  return {
134
199
  ast: {
135
200
  kind: "document",
136
201
  sourceId: input.sourceId,
137
- models: normalizedModels,
138
- enums,
139
- compositeTypes,
202
+ namespaces,
140
203
  ...ifDefined("types", typesBlock),
141
- span: {
142
- start: createPosition(context, 0, 0),
143
- end: createPosition(context, Math.max(lines.length - 1, 0), (lines[Math.max(lines.length - 1, 0)] ?? "").length)
144
- }
204
+ span: documentSpan
145
205
  },
146
206
  diagnostics,
147
207
  ok: diagnostics.length === 0
@@ -428,23 +488,40 @@ function parseField(context, line, lineIndex) {
428
488
  const list = typeSourceWithoutOptional.endsWith("[]");
429
489
  const baseTypeSource = list ? typeSourceWithoutOptional.slice(0, -2).trimEnd() : typeSourceWithoutOptional;
430
490
  const trimmedStartColumn = firstNonWhitespaceColumn(context.lines[lineIndex] ?? "");
491
+ const typeStartColumn = trimmedStartColumn + fieldName.length + separator.length;
431
492
  const typeConstructor = parseTypeConstructorCall(context, {
432
493
  declarationValue: baseTypeSource,
433
494
  lineIndex,
434
- startColumn: trimmedStartColumn + fieldName.length + separator.length,
495
+ startColumn: typeStartColumn,
435
496
  invalidCode: "PSL_INVALID_MODEL_MEMBER",
436
497
  invalidMessage: (value) => `Invalid field type constructor "${value}"`
437
498
  });
438
499
  if (typeConstructor === "malformed") return;
439
- const simpleTypeMatch = baseTypeSource.match(/^([A-Za-z_]\w*)$/);
440
- const typeName = typeConstructor?.path.join(".") ?? simpleTypeMatch?.[1];
441
- if (!typeName) {
442
- pushDiagnostic(context, {
443
- code: "PSL_INVALID_MODEL_MEMBER",
444
- message: `Invalid model member declaration "${line}"`,
445
- span: createTrimmedLineSpan(context, lineIndex)
446
- });
447
- return;
500
+ let typeName;
501
+ let typeNamespaceId;
502
+ if (typeConstructor) typeName = typeConstructor.path.join(".");
503
+ else {
504
+ if ((baseTypeSource.match(/\./g) ?? []).length > 1) {
505
+ pushDiagnostic(context, {
506
+ code: "PSL_INVALID_QUALIFIED_TYPE",
507
+ message: `Nested dot-qualified type "${baseTypeSource}" is not supported; use exactly one qualifier segment (e.g. "ns.TypeName")`,
508
+ span: createInlineSpan(context, lineIndex, typeStartColumn, typeStartColumn + baseTypeSource.length)
509
+ });
510
+ return;
511
+ }
512
+ const singleMatch = baseTypeSource.match(/^([A-Za-z_]\w*)(?:\.([A-Za-z_]\w*))?$/);
513
+ if (!singleMatch) {
514
+ pushDiagnostic(context, {
515
+ code: "PSL_INVALID_MODEL_MEMBER",
516
+ message: `Invalid model member declaration "${line}"`,
517
+ span: createTrimmedLineSpan(context, lineIndex)
518
+ });
519
+ return;
520
+ }
521
+ if (singleMatch[2] !== void 0) {
522
+ typeNamespaceId = singleMatch[1];
523
+ typeName = singleMatch[2];
524
+ } else typeName = singleMatch[1] ?? "";
448
525
  }
449
526
  const attributes = [];
450
527
  const attributeSource = attributePart.trimStart();
@@ -454,6 +531,7 @@ function parseField(context, line, lineIndex) {
454
531
  kind: "field",
455
532
  name: fieldName,
456
533
  typeName,
534
+ ...ifDefined("typeNamespaceId", typeNamespaceId),
457
535
  ...ifDefined("typeConstructor", typeConstructor),
458
536
  optional,
459
537
  list,
@@ -473,6 +551,7 @@ function parseField(context, line, lineIndex) {
473
551
  kind: "field",
474
552
  name: fieldName,
475
553
  typeName,
554
+ ...ifDefined("typeNamespaceId", typeNamespaceId),
476
555
  ...ifDefined("typeConstructor", typeConstructor),
477
556
  optional,
478
557
  list,
@@ -928,4 +1007,4 @@ function pushDiagnostic(context, diagnostic) {
928
1007
  //#endregion
929
1008
  export { parsePslDocument as t };
930
1009
 
931
- //# sourceMappingURL=parser-1DZHweIq.mjs.map
1010
+ //# sourceMappingURL=parser-R7ldFfcr.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser-R7ldFfcr.mjs","names":[],"sources":["../src/parser.ts"],"sourcesContent":["import type {\n ParsePslDocumentInput,\n ParsePslDocumentResult,\n PslAttribute,\n PslAttributeArgument,\n PslAttributeTarget,\n PslCompositeType,\n PslDiagnostic,\n PslDiagnosticCode,\n PslDocumentAst,\n PslEnum,\n PslEnumValue,\n PslField,\n PslFieldAttribute,\n PslModel,\n PslModelAttribute,\n PslNamedTypeDeclaration,\n PslNamespace,\n PslPosition,\n PslSpan,\n PslTypeConstructorCall,\n PslTypesBlock,\n} from '@prisma-next/framework-components/psl-ast';\nimport { UNSPECIFIED_PSL_NAMESPACE_ID } from '@prisma-next/framework-components/psl-ast';\nimport { ifDefined } from '@prisma-next/utils/defined';\n\nconst SCALAR_TYPES = new Set([\n 'String',\n 'Boolean',\n 'Int',\n 'BigInt',\n 'Float',\n 'Decimal',\n 'DateTime',\n 'Json',\n 'Bytes',\n]);\n\ninterface BlockBounds {\n readonly startLine: number;\n readonly endLine: number;\n readonly closed: boolean;\n}\n\ninterface ParserContext {\n readonly schema: string;\n readonly sourceId: string;\n readonly lines: readonly string[];\n readonly lineOffsets: readonly number[];\n readonly diagnostics: PslDiagnostic[];\n}\n\nexport function parsePslDocument(input: ParsePslDocumentInput): ParsePslDocumentResult {\n const normalizedSchema = input.schema.replaceAll('\\r\\n', '\\n');\n const lines = normalizedSchema.split('\\n');\n const lineOffsets = computeLineOffsets(normalizedSchema);\n const diagnostics: PslDiagnostic[] = [];\n const context: ParserContext = {\n schema: normalizedSchema,\n sourceId: input.sourceId,\n lines,\n lineOffsets,\n diagnostics,\n };\n\n interface NamespaceAccumulator {\n name: string;\n models: PslModel[];\n enums: PslEnum[];\n compositeTypes: PslCompositeType[];\n span: PslSpan | undefined;\n }\n\n const namespaceOrder: string[] = [];\n const namespacesByName = new Map<string, NamespaceAccumulator>();\n const getOrCreateNamespace = (\n name: string,\n spanIfNew: PslSpan | undefined,\n ): NamespaceAccumulator => {\n let acc = namespacesByName.get(name);\n if (!acc) {\n acc = { name, models: [], enums: [], compositeTypes: [], span: spanIfNew };\n namespacesByName.set(name, acc);\n namespaceOrder.push(name);\n }\n return acc;\n };\n\n let typesBlock: PslTypesBlock | undefined;\n\n // Walk a contiguous range of lines, routing top-level declarations into the\n // active namespace bucket. Called once for the whole document and once per\n // `namespace { … }` block body; nested `namespace { … }` or `types { … }`\n // blocks inside a namespace body are rejected with a diagnostic.\n const parseBody = (\n startLine: number,\n endLineExclusive: number,\n currentNamespaceName: string,\n isInsideNamespace: boolean,\n ): void => {\n let lineIndex = startLine;\n while (lineIndex < endLineExclusive) {\n const rawLine = context.lines[lineIndex] ?? '';\n const line = stripInlineComment(rawLine).trim();\n if (line.length === 0) {\n lineIndex += 1;\n continue;\n }\n\n const modelMatch = line.match(/^model\\s+([A-Za-z_]\\w*)\\s*\\{$/);\n if (modelMatch) {\n const bounds = findBlockBounds(context, lineIndex);\n const name = modelMatch[1] ?? '';\n if (name.length > 0) {\n const acc = getOrCreateNamespace(\n currentNamespaceName,\n createTrimmedLineSpan(context, lineIndex),\n );\n acc.models.push(parseModelBlock(context, name, bounds));\n }\n lineIndex = bounds.endLine + 1;\n continue;\n }\n\n const enumMatch = line.match(/^enum\\s+([A-Za-z_]\\w*)\\s*\\{$/);\n if (enumMatch) {\n const bounds = findBlockBounds(context, lineIndex);\n const name = enumMatch[1] ?? '';\n if (name.length > 0) {\n const acc = getOrCreateNamespace(\n currentNamespaceName,\n createTrimmedLineSpan(context, lineIndex),\n );\n acc.enums.push(parseEnumBlock(context, name, bounds));\n }\n lineIndex = bounds.endLine + 1;\n continue;\n }\n\n const compositeTypeMatch = line.match(/^type\\s+([A-Za-z_]\\w*)\\s*\\{$/);\n if (compositeTypeMatch) {\n const bounds = findBlockBounds(context, lineIndex);\n const name = compositeTypeMatch[1] ?? '';\n if (name.length > 0) {\n const acc = getOrCreateNamespace(\n currentNamespaceName,\n createTrimmedLineSpan(context, lineIndex),\n );\n acc.compositeTypes.push(parseCompositeTypeBlock(context, name, bounds));\n }\n lineIndex = bounds.endLine + 1;\n continue;\n }\n\n const namespaceMatch = line.match(/^namespace\\s+([A-Za-z_]\\w*)\\s*\\{$/);\n if (namespaceMatch) {\n const bounds = findBlockBounds(context, lineIndex);\n const name = namespaceMatch[1] ?? '';\n if (isInsideNamespace) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_NAMESPACE_BLOCK',\n message: `Recursive \"namespace ${name}\" block is not allowed; namespace blocks may not nest`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n } else if (name === UNSPECIFIED_PSL_NAMESPACE_ID) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_NAMESPACE_BLOCK',\n message: `Namespace name \"${UNSPECIFIED_PSL_NAMESPACE_ID}\" is reserved for the parser-synthesised bucket for top-level declarations`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n } else if (name.length > 0) {\n getOrCreateNamespace(name, createTrimmedLineSpan(context, lineIndex));\n parseBody(bounds.startLine + 1, bounds.endLine, name, true);\n }\n lineIndex = bounds.endLine + 1;\n continue;\n }\n\n if (/^types\\s*\\{$/.test(line)) {\n const bounds = findBlockBounds(context, lineIndex);\n if (isInsideNamespace) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_NAMESPACE_BLOCK',\n message:\n '`types` blocks must be declared at the document top level, not inside a namespace block',\n span: createTrimmedLineSpan(context, lineIndex),\n });\n } else if (typesBlock !== undefined) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_TYPES_MEMBER',\n message: 'Only one top-level `types` block is allowed per document',\n span: createTrimmedLineSpan(context, lineIndex),\n });\n } else {\n typesBlock = parseTypesBlock(context, bounds);\n }\n lineIndex = bounds.endLine + 1;\n continue;\n }\n\n if (line.includes('{')) {\n const blockName = line.split(/\\s+/)[0] ?? 'block';\n pushDiagnostic(context, {\n code: 'PSL_UNSUPPORTED_TOP_LEVEL_BLOCK',\n message: `Unsupported top-level block \"${blockName}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n const bounds = findBlockBounds(context, lineIndex);\n lineIndex = bounds.endLine + 1;\n continue;\n }\n\n pushDiagnostic(context, {\n code: 'PSL_UNSUPPORTED_TOP_LEVEL_BLOCK',\n message: `Unsupported top-level declaration \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n lineIndex += 1;\n }\n };\n\n parseBody(0, lines.length, UNSPECIFIED_PSL_NAMESPACE_ID, false);\n\n // Named-type validation: types are document-scoped (one block, outside any\n // namespace), so collision checks compare named-type names against every\n // model/enum/composite-type in every namespace.\n const allModels: PslModel[] = [];\n const allEnums: PslEnum[] = [];\n const allCompositeTypes: PslCompositeType[] = [];\n for (const name of namespaceOrder) {\n const acc = namespacesByName.get(name);\n if (!acc) continue;\n allModels.push(...acc.models);\n allEnums.push(...acc.enums);\n allCompositeTypes.push(...acc.compositeTypes);\n }\n\n const namedTypeNames = new Set(\n (typesBlock?.declarations ?? []).map((declaration) => declaration.name),\n );\n const modelNames = new Set(allModels.map((model) => model.name));\n const enumNames = new Set(allEnums.map((enumBlock) => enumBlock.name));\n const compositeTypeNames = new Set(allCompositeTypes.map((ct) => ct.name));\n for (const declaration of typesBlock?.declarations ?? []) {\n if (SCALAR_TYPES.has(declaration.name)) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_TYPES_MEMBER',\n message: `Named type \"${declaration.name}\" conflicts with scalar type \"${declaration.name}\"`,\n span: declaration.span,\n });\n continue;\n }\n if (modelNames.has(declaration.name)) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_TYPES_MEMBER',\n message: `Named type \"${declaration.name}\" conflicts with model name \"${declaration.name}\"`,\n span: declaration.span,\n });\n continue;\n }\n if (enumNames.has(declaration.name)) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_TYPES_MEMBER',\n message: `Named type \"${declaration.name}\" conflicts with enum name \"${declaration.name}\"`,\n span: declaration.span,\n });\n }\n }\n\n const documentSpan: PslSpan = {\n start: createPosition(context, 0, 0),\n end: createPosition(\n context,\n Math.max(lines.length - 1, 0),\n (lines[Math.max(lines.length - 1, 0)] ?? '').length,\n ),\n };\n\n const namespaces: PslNamespace[] = [];\n for (const name of namespaceOrder) {\n const acc = namespacesByName.get(name);\n if (!acc) continue;\n // Drop the synthesised __unspecified__ entry when it ended up empty (e.g.\n // every declaration in the document lived inside an explicit\n // `namespace { … }` block). Keeping a phantom bucket would force every\n // downstream consumer to special-case \"namespace with no members\".\n if (\n name === UNSPECIFIED_PSL_NAMESPACE_ID &&\n acc.models.length === 0 &&\n acc.enums.length === 0 &&\n acc.compositeTypes.length === 0\n ) {\n continue;\n }\n const normalizedModels = acc.models.map((model) => ({\n ...model,\n fields: model.fields.map((field) => {\n if (!namedTypeNames.has(field.typeName)) {\n return field;\n }\n const hasRelationAttribute = field.attributes.some(\n (attribute) => attribute.name === 'relation',\n );\n if (\n hasRelationAttribute ||\n modelNames.has(field.typeName) ||\n enumNames.has(field.typeName) ||\n compositeTypeNames.has(field.typeName) ||\n SCALAR_TYPES.has(field.typeName)\n ) {\n return field;\n }\n return {\n ...field,\n typeRef: field.typeName,\n };\n }),\n }));\n namespaces.push({\n kind: 'namespace',\n name,\n models: normalizedModels,\n enums: acc.enums,\n compositeTypes: acc.compositeTypes,\n span: acc.span ?? documentSpan,\n });\n }\n\n const ast: PslDocumentAst = {\n kind: 'document',\n sourceId: input.sourceId,\n namespaces,\n ...ifDefined('types', typesBlock),\n span: documentSpan,\n };\n\n return {\n ast,\n diagnostics,\n ok: diagnostics.length === 0,\n };\n}\n\nfunction parseModelBlock(context: ParserContext, name: string, bounds: BlockBounds): PslModel {\n const fields: PslField[] = [];\n const attributes: PslModelAttribute[] = [];\n\n for (let lineIndex = bounds.startLine + 1; lineIndex < bounds.endLine; lineIndex += 1) {\n const raw = context.lines[lineIndex] ?? '';\n const line = stripInlineComment(raw).trim();\n if (line.length === 0) {\n continue;\n }\n\n if (line.startsWith('@@')) {\n const attribute = parseModelAttribute(context, line, lineIndex);\n if (attribute) {\n attributes.push(attribute);\n }\n continue;\n }\n\n const field = parseField(context, line, lineIndex);\n if (field) {\n fields.push(field);\n }\n }\n\n return {\n kind: 'model',\n name,\n fields,\n attributes,\n span: createLineRangeSpan(context, bounds.startLine, bounds.endLine),\n };\n}\n\nfunction parseCompositeTypeBlock(\n context: ParserContext,\n name: string,\n bounds: BlockBounds,\n): PslCompositeType {\n const fields: PslField[] = [];\n const attributes: PslAttribute[] = [];\n\n for (let lineIndex = bounds.startLine + 1; lineIndex < bounds.endLine; lineIndex += 1) {\n const raw = context.lines[lineIndex] ?? '';\n const line = stripInlineComment(raw).trim();\n if (line.length === 0) {\n continue;\n }\n\n if (line.startsWith('@@')) {\n const attribute = parseModelAttribute(context, line, lineIndex);\n if (attribute) {\n attributes.push(attribute);\n }\n continue;\n }\n\n const field = parseField(context, line, lineIndex);\n if (field) {\n fields.push(field);\n }\n }\n\n return {\n kind: 'compositeType',\n name,\n fields,\n attributes,\n span: createLineRangeSpan(context, bounds.startLine, bounds.endLine),\n };\n}\n\nfunction parseEnumBlock(context: ParserContext, name: string, bounds: BlockBounds): PslEnum {\n const values: PslEnumValue[] = [];\n const attributes: PslAttribute[] = [];\n\n for (let lineIndex = bounds.startLine + 1; lineIndex < bounds.endLine; lineIndex += 1) {\n const raw = context.lines[lineIndex] ?? '';\n const line = stripInlineComment(raw).trim();\n if (line.length === 0) {\n continue;\n }\n\n if (line.startsWith('@@')) {\n const attribute = parseEnumAttribute(context, line, lineIndex);\n if (attribute) {\n attributes.push(attribute);\n }\n continue;\n }\n\n // An enum member line is the bare member identifier, optionally followed\n // by a `@map(\"storage-label\")` attribute. The map attribute lets the\n // printer round-trip enum values whose original storage label is not a\n // valid PSL identifier (e.g. PostgreSQL enum labels with hyphens).\n const valueMatch = line.match(/^([A-Za-z_]\\w*)(?:\\s+@map\\(\\s*\"((?:[^\"\\\\]|\\\\.)*)\"\\s*\\))?$/);\n if (!valueMatch) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ENUM_MEMBER',\n message: `Invalid enum value declaration \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n continue;\n }\n\n const mapName = valueMatch[2] !== undefined ? unescapePslString(valueMatch[2]) : undefined;\n\n values.push({\n kind: 'enumValue',\n name: valueMatch[1] ?? '',\n ...(mapName !== undefined ? { mapName } : {}),\n span: createTrimmedLineSpan(context, lineIndex),\n });\n }\n\n return {\n kind: 'enum',\n name,\n values,\n attributes,\n span: createLineRangeSpan(context, bounds.startLine, bounds.endLine),\n };\n}\n\n/**\n * Decode PSL escape sequences (`\\\\`, `\\\"`, `\\'`, `\\n`, `\\r`) inside a\n * quoted-literal body. The argument is the body of the literal with the\n * surrounding quotes already stripped by the caller. Mirrors the inverse\n * helper in `@prisma-next/psl-printer`'s `escapePslString` so a string\n * round-trips parser → printer → parser unchanged.\n */\nfunction unescapePslString(value: string): string {\n let result = '';\n for (let i = 0; i < value.length; i++) {\n const ch = value.charCodeAt(i);\n if (ch !== 0x5c /* '\\\\' */ || i + 1 >= value.length) {\n result += value[i];\n continue;\n }\n const next = value[i + 1];\n if (next === '\\\\' || next === '\"' || next === \"'\") {\n result += next;\n } else if (next === 'n') {\n result += '\\n';\n } else if (next === 'r') {\n result += '\\r';\n } else {\n result += '\\\\';\n result += next;\n }\n i++;\n }\n return result;\n}\n\nfunction parseTypesBlock(context: ParserContext, bounds: BlockBounds): PslTypesBlock {\n const declarations: PslNamedTypeDeclaration[] = [];\n\n for (let lineIndex = bounds.startLine + 1; lineIndex < bounds.endLine; lineIndex += 1) {\n const raw = context.lines[lineIndex] ?? '';\n const lineWithoutComment = stripInlineComment(raw);\n const line = lineWithoutComment.trim();\n if (line.length === 0) {\n continue;\n }\n\n const declarationMatch = line.match(/^([A-Za-z_]\\w*)\\s*=\\s*(.+)$/);\n if (!declarationMatch) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_TYPES_MEMBER',\n message: `Invalid types declaration \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n continue;\n }\n\n const declarationName = declarationMatch[1] ?? '';\n const trimmedStartColumn = firstNonWhitespaceColumn(raw);\n const declarationValue = (declarationMatch[2] ?? '').trim();\n const valueOffset = line.indexOf(declarationValue);\n const declarationValueColumn = trimmedStartColumn + Math.max(valueOffset, 0);\n\n const typeAndAttributeSplit = splitTypeAndAttributes(declarationValue);\n const typeSource = typeAndAttributeSplit.typeSource.trim();\n const attributeSource = typeAndAttributeSplit.attributeSource.trimStart();\n const leadingAttributeWhitespace =\n typeAndAttributeSplit.attributeSource.length - attributeSource.length;\n\n const typeConstructor = parseTypeConstructorCall(context, {\n declarationValue: typeSource,\n lineIndex,\n startColumn: declarationValueColumn,\n invalidCode: 'PSL_INVALID_TYPES_MEMBER',\n invalidMessage: (value) => `Invalid types declaration \"${value}\"`,\n });\n if (typeConstructor === 'malformed') {\n continue;\n }\n\n const attributeParse = extractAttributeTokensWithSpans(\n context,\n lineIndex,\n attributeSource,\n declarationValueColumn + typeAndAttributeSplit.attributeOffset + leadingAttributeWhitespace,\n );\n if (!attributeParse.ok) {\n continue;\n }\n const attributes = attributeParse.tokens\n .map((token) =>\n parseAttributeToken(context, {\n token: token.text,\n target: 'namedType',\n lineIndex,\n span: token.span,\n }),\n )\n .filter((attribute): attribute is PslAttribute => Boolean(attribute));\n\n if (typeConstructor) {\n declarations.push({\n kind: 'namedType',\n name: declarationName,\n typeConstructor,\n attributes,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n continue;\n }\n\n const baseTypeMatch = typeSource.match(/^([A-Za-z_]\\w*)$/);\n if (!baseTypeMatch) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_TYPES_MEMBER',\n message: `Invalid types declaration \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n continue;\n }\n\n const baseType = baseTypeMatch[1] ?? '';\n\n declarations.push({\n kind: 'namedType',\n name: declarationName,\n baseType,\n attributes,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n }\n\n return {\n kind: 'types',\n declarations,\n span: createLineRangeSpan(context, bounds.startLine, bounds.endLine),\n };\n}\n\nfunction parseTypeConstructorCall(\n context: ParserContext,\n input: {\n readonly declarationValue: string;\n readonly lineIndex: number;\n readonly startColumn: number;\n readonly invalidCode: PslDiagnosticCode;\n readonly invalidMessage: (value: string) => string;\n },\n): PslTypeConstructorCall | 'malformed' | undefined {\n const value = input.declarationValue.trim();\n const constructorMatch = value.match(\n /^([A-Za-z_][A-Za-z0-9_-]*(?:\\.[A-Za-z_][A-Za-z0-9_-]*)*)\\s*\\(/,\n );\n if (!constructorMatch) {\n return undefined;\n }\n\n // constructorMatch already required `(`; openParen is guaranteed ≥ 0.\n const openParen = value.indexOf('(');\n const closeParen = value.lastIndexOf(')');\n\n if (closeParen !== value.length - 1) {\n pushDiagnostic(context, {\n code: input.invalidCode,\n message: input.invalidMessage(value),\n span: createInlineSpan(\n context,\n input.lineIndex,\n input.startColumn,\n input.startColumn + value.length,\n ),\n });\n return 'malformed';\n }\n\n const constructorPath = constructorMatch[1] ?? '';\n\n const argsRaw = value.slice(openParen + 1, closeParen);\n const args = parseArgumentList(context, {\n argsRaw,\n argsOffset: input.startColumn + openParen + 1,\n lineIndex: input.lineIndex,\n token: value,\n span: createInlineSpan(\n context,\n input.lineIndex,\n input.startColumn,\n input.startColumn + value.length,\n ),\n invalidCode: input.invalidCode,\n invalidEmptyArgumentMessage: `Invalid empty argument in type constructor \"${value}\"`,\n invalidNamedArgumentMessage: (part) =>\n `Invalid named argument syntax \"${part}\" in type constructor \"${value}\"`,\n });\n if (!args) {\n return 'malformed';\n }\n\n return {\n kind: 'typeConstructor',\n path: constructorPath.split('.'),\n args,\n span: createInlineSpan(\n context,\n input.lineIndex,\n input.startColumn,\n input.startColumn + value.length,\n ),\n };\n}\n\nfunction parseModelAttribute(\n context: ParserContext,\n line: string,\n lineIndex: number,\n): PslModelAttribute | undefined {\n const rawLine = context.lines[lineIndex] ?? '';\n const tokenParse = extractAttributeTokensWithSpans(\n context,\n lineIndex,\n line,\n firstNonWhitespaceColumn(rawLine),\n );\n if (!tokenParse.ok || tokenParse.tokens.length !== 1) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Invalid model attribute syntax \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n return undefined;\n }\n const token = tokenParse.tokens[0];\n if (!token) {\n return undefined;\n }\n return parseAttributeToken(context, {\n token: token.text,\n target: 'model',\n lineIndex,\n span: token.span,\n });\n}\n\nfunction parseEnumAttribute(\n context: ParserContext,\n line: string,\n lineIndex: number,\n): PslAttribute | undefined {\n const rawLine = context.lines[lineIndex] ?? '';\n const tokenParse = extractAttributeTokensWithSpans(\n context,\n lineIndex,\n line,\n firstNonWhitespaceColumn(rawLine),\n );\n if (!tokenParse.ok || tokenParse.tokens.length !== 1) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ENUM_MEMBER',\n message: `Invalid enum value declaration \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n return undefined;\n }\n const token = tokenParse.tokens[0];\n if (!token) {\n return undefined;\n }\n const parsed = parseAttributeToken(context, {\n token: token.text,\n target: 'enum',\n lineIndex,\n span: token.span,\n });\n if (!parsed) {\n return undefined;\n }\n if (parsed.name !== 'map') {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ENUM_MEMBER',\n message: `Invalid enum value declaration \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n return undefined;\n }\n return parsed;\n}\n\nfunction parseField(context: ParserContext, line: string, lineIndex: number): PslField | undefined {\n const fieldMatch = line.match(/^([A-Za-z_]\\w*)(\\s+)(.+)$/);\n if (!fieldMatch) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_MODEL_MEMBER',\n message: `Invalid model member declaration \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n return undefined;\n }\n\n const fieldName = fieldMatch[1] ?? '';\n const separator = fieldMatch[2] ?? '';\n const remainder = fieldMatch[3] ?? '';\n const typeAndAttributeSplit = splitTypeAndAttributes(remainder);\n const rawTypeSource = typeAndAttributeSplit.typeSource.trim();\n const attributePart = typeAndAttributeSplit.attributeSource;\n const optional = rawTypeSource.endsWith('?');\n const typeSourceWithoutOptional = optional ? rawTypeSource.slice(0, -1).trimEnd() : rawTypeSource;\n const list = typeSourceWithoutOptional.endsWith('[]');\n const baseTypeSource = list\n ? typeSourceWithoutOptional.slice(0, -2).trimEnd()\n : typeSourceWithoutOptional;\n const rawLine = context.lines[lineIndex] ?? '';\n const trimmedStartColumn = firstNonWhitespaceColumn(rawLine);\n const typeStartColumn = trimmedStartColumn + fieldName.length + separator.length;\n\n const typeConstructor = parseTypeConstructorCall(context, {\n declarationValue: baseTypeSource,\n lineIndex,\n startColumn: typeStartColumn,\n invalidCode: 'PSL_INVALID_MODEL_MEMBER',\n invalidMessage: (value) => `Invalid field type constructor \"${value}\"`,\n });\n if (typeConstructor === 'malformed') {\n return undefined;\n }\n\n let typeName: string;\n let typeNamespaceId: string | undefined;\n\n if (typeConstructor) {\n typeName = typeConstructor.path.join('.');\n } else {\n const dotCount = (baseTypeSource.match(/\\./g) ?? []).length;\n if (dotCount > 1) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_QUALIFIED_TYPE',\n message: `Nested dot-qualified type \"${baseTypeSource}\" is not supported; use exactly one qualifier segment (e.g. \"ns.TypeName\")`,\n span: createInlineSpan(\n context,\n lineIndex,\n typeStartColumn,\n typeStartColumn + baseTypeSource.length,\n ),\n });\n return undefined;\n }\n const singleMatch = baseTypeSource.match(/^([A-Za-z_]\\w*)(?:\\.([A-Za-z_]\\w*))?$/);\n if (!singleMatch) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_MODEL_MEMBER',\n message: `Invalid model member declaration \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n return undefined;\n }\n if (singleMatch[2] !== undefined) {\n typeNamespaceId = singleMatch[1];\n typeName = singleMatch[2];\n } else {\n typeName = singleMatch[1] ?? '';\n }\n }\n\n const attributes: PslFieldAttribute[] = [];\n const attributeSource = attributePart.trimStart();\n const leadingAttributeWhitespace = attributePart.length - attributeSource.length;\n const tokenParse = extractAttributeTokensWithSpans(\n context,\n lineIndex,\n attributeSource,\n trimmedStartColumn +\n fieldName.length +\n separator.length +\n typeAndAttributeSplit.attributeOffset +\n leadingAttributeWhitespace,\n );\n if (!tokenParse.ok) {\n return {\n kind: 'field',\n name: fieldName,\n typeName,\n ...ifDefined('typeNamespaceId', typeNamespaceId),\n ...ifDefined('typeConstructor', typeConstructor),\n optional,\n list,\n attributes,\n span: createTrimmedLineSpan(context, lineIndex),\n };\n }\n\n for (const token of tokenParse.tokens) {\n const parsed = parseAttributeToken(context, {\n token: token.text,\n target: 'field',\n lineIndex,\n span: token.span,\n });\n if (parsed) {\n attributes.push(parsed);\n }\n }\n\n return {\n kind: 'field',\n name: fieldName,\n typeName,\n ...ifDefined('typeNamespaceId', typeNamespaceId),\n ...ifDefined('typeConstructor', typeConstructor),\n optional,\n list,\n attributes,\n span: createTrimmedLineSpan(context, lineIndex),\n };\n}\n\nfunction isQuoteEscaped(value: string, quoteIndex: number): boolean {\n let backslashCount = 0;\n\n for (let index = quoteIndex - 1; index >= 0 && value[index] === '\\\\'; index -= 1) {\n backslashCount += 1;\n }\n\n return backslashCount % 2 === 1;\n}\n\nfunction splitTypeAndAttributes(value: string): {\n readonly typeSource: string;\n readonly attributeSource: string;\n readonly attributeOffset: number;\n} {\n let depthParen = 0;\n let depthBracket = 0;\n let depthBrace = 0;\n let quote: '\"' | \"'\" | null = null;\n\n for (let index = 0; index < value.length; index += 1) {\n const character = value[index] ?? '';\n if (quote) {\n if (character === quote && !isQuoteEscaped(value, index)) {\n quote = null;\n }\n continue;\n }\n\n if (character === '\"' || character === \"'\") {\n quote = character;\n continue;\n }\n if (character === '(') {\n depthParen += 1;\n continue;\n }\n if (character === ')') {\n depthParen = Math.max(0, depthParen - 1);\n continue;\n }\n if (character === '[') {\n depthBracket += 1;\n continue;\n }\n if (character === ']') {\n depthBracket = Math.max(0, depthBracket - 1);\n continue;\n }\n if (character === '{') {\n depthBrace += 1;\n continue;\n }\n if (character === '}') {\n depthBrace = Math.max(0, depthBrace - 1);\n continue;\n }\n\n if (character === '@' && depthParen === 0 && depthBracket === 0 && depthBrace === 0) {\n return {\n typeSource: value.slice(0, index).trimEnd(),\n attributeSource: value.slice(index),\n attributeOffset: index,\n };\n }\n }\n\n return {\n typeSource: value.trimEnd(),\n attributeSource: '',\n attributeOffset: value.length,\n };\n}\n\nfunction parseAttributeToken(\n context: ParserContext,\n input: {\n readonly token: string;\n readonly target: PslAttributeTarget;\n readonly lineIndex: number;\n readonly span: PslSpan;\n },\n): PslAttribute | undefined {\n const expectsBlockPrefix = input.target === 'model' || input.target === 'enum';\n const targetLabel = input.target === 'enum' ? 'Enum' : 'Model';\n if (expectsBlockPrefix && !input.token.startsWith('@@')) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `${targetLabel} attribute \"${input.token}\" must use @@ prefix`,\n span: input.span,\n });\n return undefined;\n }\n if (!expectsBlockPrefix && !input.token.startsWith('@')) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Attribute \"${input.token}\" must use @ prefix`,\n span: input.span,\n });\n return undefined;\n }\n if (!expectsBlockPrefix && input.token.startsWith('@@')) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Attribute \"${input.token}\" is not valid in ${input.target} context`,\n span: input.span,\n });\n return undefined;\n }\n\n const rawBody = expectsBlockPrefix ? input.token.slice(2) : input.token.slice(1);\n const openParen = rawBody.indexOf('(');\n const closeParen = rawBody.lastIndexOf(')');\n const hasArgs = openParen >= 0 || closeParen >= 0;\n if ((openParen >= 0 && closeParen === -1) || (openParen === -1 && closeParen >= 0)) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Invalid attribute syntax \"${input.token}\"`,\n span: input.span,\n });\n return undefined;\n }\n\n const name = (openParen >= 0 ? rawBody.slice(0, openParen) : rawBody).trim();\n if (!/^[A-Za-z_][A-Za-z0-9_-]*(\\.[A-Za-z_][A-Za-z0-9_-]*)*$/.test(name)) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Invalid attribute name \"${name || input.token}\"`,\n span: input.span,\n });\n return undefined;\n }\n\n let args: readonly PslAttributeArgument[] = [];\n if (hasArgs && openParen >= 0 && closeParen >= openParen) {\n if (closeParen !== rawBody.length - 1) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Invalid trailing syntax in attribute \"${input.token}\"`,\n span: input.span,\n });\n return undefined;\n }\n const argsRaw = rawBody.slice(openParen + 1, closeParen);\n const parsedArgs = parseArgumentList(context, {\n argsRaw,\n argsOffset: input.span.start.column - 1 + (expectsBlockPrefix ? 2 : 1) + openParen + 1,\n lineIndex: input.lineIndex,\n token: input.token,\n span: input.span,\n invalidCode: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n invalidEmptyArgumentMessage: `Invalid empty argument in attribute \"${input.token}\"`,\n invalidNamedArgumentMessage: (part) => `Invalid named argument syntax \"${part}\"`,\n });\n if (!parsedArgs) {\n return undefined;\n }\n args = parsedArgs;\n }\n\n return {\n kind: 'attribute',\n target: input.target,\n name,\n args,\n span: input.span,\n };\n}\n\nfunction parseArgumentList(\n context: ParserContext,\n input: {\n readonly argsRaw: string;\n readonly argsOffset: number;\n readonly lineIndex: number;\n readonly token: string;\n readonly span: PslSpan;\n readonly invalidCode: PslDiagnosticCode;\n readonly invalidEmptyArgumentMessage: string;\n readonly invalidNamedArgumentMessage: (part: string) => string;\n },\n): readonly PslAttributeArgument[] | undefined {\n const trimmed = input.argsRaw.trim();\n if (trimmed.length === 0) {\n return [];\n }\n\n const parts = splitTopLevelSegments(input.argsRaw, ',');\n const args: PslAttributeArgument[] = [];\n\n for (const part of parts) {\n const original = part.value;\n const trimmedPart = original.trim();\n if (trimmedPart.length === 0) {\n pushDiagnostic(context, {\n code: input.invalidCode,\n message: input.invalidEmptyArgumentMessage,\n span: input.span,\n });\n return undefined;\n }\n\n const leadingWhitespace = original.length - original.trimStart().length;\n const partStart = input.argsOffset + part.start + leadingWhitespace;\n const partEnd = partStart + trimmedPart.length;\n const partSpan = createInlineSpan(context, input.lineIndex, partStart, partEnd);\n\n const namedSplit = splitTopLevelSegments(trimmedPart, ':');\n if (namedSplit.length > 1) {\n const first = namedSplit[0];\n if (!first) {\n pushDiagnostic(context, {\n code: input.invalidCode,\n message: input.invalidNamedArgumentMessage(trimmedPart),\n span: partSpan,\n });\n return undefined;\n }\n const name = first.value.trim();\n const rawValue = trimmedPart.slice(first.end + 1).trim();\n if (!name || rawValue.length === 0) {\n pushDiagnostic(context, {\n code: input.invalidCode,\n message: input.invalidNamedArgumentMessage(trimmedPart),\n span: partSpan,\n });\n return undefined;\n }\n args.push({\n kind: 'named',\n name,\n value: normalizeAttributeArgumentValue(rawValue),\n span: partSpan,\n });\n continue;\n }\n\n args.push({\n kind: 'positional',\n value: normalizeAttributeArgumentValue(trimmedPart),\n span: partSpan,\n });\n }\n\n return args;\n}\n\nfunction normalizeAttributeArgumentValue(value: string): string {\n return value.trim();\n}\n\nfunction findBlockBounds(context: ParserContext, startLine: number): BlockBounds {\n let depth = 0;\n\n for (let lineIndex = startLine; lineIndex < context.lines.length; lineIndex += 1) {\n const line = stripInlineComment(context.lines[lineIndex] ?? '');\n let quote: '\"' | \"'\" | null = null;\n for (let index = 0; index < line.length; index += 1) {\n const character = line[index] ?? '';\n if (quote) {\n if (character === quote && !isQuoteEscaped(line, index)) {\n quote = null;\n }\n continue;\n }\n\n if (character === '\"' || character === \"'\") {\n quote = character;\n continue;\n }\n\n if (character === '{') {\n depth += 1;\n }\n if (character === '}') {\n depth -= 1;\n if (depth === 0) {\n return { startLine, endLine: lineIndex, closed: true };\n }\n }\n }\n }\n\n pushDiagnostic(context, {\n code: 'PSL_UNTERMINATED_BLOCK',\n message: 'Unterminated block declaration',\n span: createTrimmedLineSpan(context, startLine),\n });\n return {\n startLine,\n endLine: context.lines.length - 1,\n closed: false,\n };\n}\n\ninterface TopLevelSegment {\n readonly value: string;\n readonly start: number;\n readonly end: number;\n}\n\nfunction splitTopLevelSegments(value: string, separator: ',' | ':'): TopLevelSegment[] {\n const parts: TopLevelSegment[] = [];\n let depthParen = 0;\n let depthBracket = 0;\n let depthBrace = 0;\n let quote: '\"' | \"'\" | null = null;\n let start = 0;\n\n for (let index = 0; index < value.length; index += 1) {\n const character = value[index] ?? '';\n if (quote) {\n if (character === quote && !isQuoteEscaped(value, index)) {\n quote = null;\n }\n continue;\n }\n\n if (character === '\"' || character === \"'\") {\n quote = character;\n continue;\n }\n\n if (character === '(') {\n depthParen += 1;\n continue;\n }\n if (character === ')') {\n depthParen = Math.max(0, depthParen - 1);\n continue;\n }\n if (character === '[') {\n depthBracket += 1;\n continue;\n }\n if (character === ']') {\n depthBracket = Math.max(0, depthBracket - 1);\n continue;\n }\n if (character === '{') {\n depthBrace += 1;\n continue;\n }\n if (character === '}') {\n depthBrace = Math.max(0, depthBrace - 1);\n continue;\n }\n\n if (character === separator && depthParen === 0 && depthBracket === 0 && depthBrace === 0) {\n parts.push({\n value: value.slice(start, index),\n start,\n end: index,\n });\n start = index + 1;\n }\n }\n\n parts.push({\n value: value.slice(start),\n start,\n end: value.length,\n });\n return parts;\n}\n\nfunction extractAttributeTokensWithSpans(\n context: ParserContext,\n lineIndex: number,\n value: string,\n startColumn: number,\n): { readonly ok: boolean; readonly tokens: readonly { text: string; span: PslSpan }[] } {\n const tokens: { text: string; span: PslSpan }[] = [];\n let index = 0;\n while (index < value.length) {\n while (index < value.length && /\\s/.test(value[index] ?? '')) {\n index += 1;\n }\n if (index >= value.length) {\n break;\n }\n\n if (value[index] !== '@') {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Invalid attribute syntax \"${value.trim()}\"`,\n span: createInlineSpan(context, lineIndex, startColumn + index, startColumn + value.length),\n });\n return { ok: false, tokens };\n }\n\n const start = index;\n index += 1;\n if (value[index] === '@') {\n index += 1;\n }\n\n const nameStart = index;\n while (index < value.length && /[A-Za-z0-9_.-]/.test(value[index] ?? '')) {\n index += 1;\n }\n\n if (index === nameStart) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Invalid attribute syntax \"${value.slice(start).trim()}\"`,\n span: createInlineSpan(context, lineIndex, startColumn + start, startColumn + value.length),\n });\n return { ok: false, tokens };\n }\n\n if (value[index] === '(') {\n let depth = 0;\n let quote: '\"' | \"'\" | null = null;\n while (index < value.length) {\n const char = value[index] ?? '';\n if (quote) {\n if (char === quote && !isQuoteEscaped(value, index)) {\n quote = null;\n }\n index += 1;\n continue;\n }\n\n if (char === '\"' || char === \"'\") {\n quote = char;\n index += 1;\n continue;\n }\n\n if (char === '(') {\n depth += 1;\n } else if (char === ')') {\n depth -= 1;\n if (depth === 0) {\n index += 1;\n break;\n }\n }\n index += 1;\n }\n if (depth !== 0) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Unterminated attribute argument list in \"${value.slice(start).trim()}\"`,\n span: createInlineSpan(\n context,\n lineIndex,\n startColumn + start,\n startColumn + value.length,\n ),\n });\n return { ok: false, tokens };\n }\n }\n\n const tokenText = value.slice(start, index).trim();\n tokens.push({\n text: tokenText,\n span: createInlineSpan(context, lineIndex, startColumn + start, startColumn + index),\n });\n\n while (index < value.length && /\\s/.test(value[index] ?? '')) {\n index += 1;\n }\n\n if (index < value.length && value[index] !== '@') {\n break;\n }\n }\n\n if (index < value.length && value[index] !== '@') {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Invalid attribute syntax \"${value.trim()}\"`,\n span: createInlineSpan(context, lineIndex, startColumn + index, startColumn + value.length),\n });\n return { ok: false, tokens };\n }\n\n return { ok: true, tokens };\n}\n\nfunction stripInlineComment(line: string): string {\n let quote: '\"' | \"'\" | null = null;\n for (let index = 0; index < line.length - 1; index += 1) {\n const current = line[index] ?? '';\n const next = line[index + 1] ?? '';\n\n if (quote) {\n if (current === quote && !isQuoteEscaped(line, index)) {\n quote = null;\n }\n continue;\n }\n\n if (current === '\"' || current === \"'\") {\n quote = current;\n continue;\n }\n\n if (current === '/' && next === '/') {\n return line.slice(0, index);\n }\n }\n\n return line;\n}\n\nfunction computeLineOffsets(schema: string): number[] {\n const offsets = [0];\n for (let index = 0; index < schema.length; index += 1) {\n if (schema[index] === '\\n') {\n offsets.push(index + 1);\n }\n }\n return offsets;\n}\n\nfunction firstNonWhitespaceColumn(line: string): number {\n const first = line.search(/\\S/);\n return first === -1 ? 0 : first;\n}\n\nfunction createInlineSpan(\n context: ParserContext,\n lineIndex: number,\n startColumn: number,\n endColumn: number,\n): PslSpan {\n return {\n start: createPosition(context, lineIndex, startColumn),\n end: createPosition(context, lineIndex, endColumn),\n };\n}\n\nfunction createTrimmedLineSpan(context: ParserContext, lineIndex: number): PslSpan {\n const line = context.lines[lineIndex] ?? '';\n const startColumn = firstNonWhitespaceColumn(line);\n return {\n start: createPosition(context, lineIndex, startColumn),\n end: createPosition(context, lineIndex, line.length),\n };\n}\n\nfunction createLineRangeSpan(context: ParserContext, startLine: number, endLine: number): PslSpan {\n const startLineText = context.lines[startLine] ?? '';\n const endLineText = context.lines[endLine] ?? '';\n const startColumn = firstNonWhitespaceColumn(startLineText);\n return {\n start: createPosition(context, startLine, startColumn),\n end: createPosition(context, endLine, endLineText.length),\n };\n}\n\nfunction createPosition(\n context: ParserContext,\n lineIndex: number,\n columnIndex: number,\n): PslPosition {\n const clampedLineIndex = Math.max(0, Math.min(lineIndex, context.lineOffsets.length - 1));\n const lineText = context.lines[clampedLineIndex] ?? '';\n const clampedColumnIndex = Math.max(0, Math.min(columnIndex, lineText.length));\n return {\n offset: (context.lineOffsets[clampedLineIndex] ?? 0) + clampedColumnIndex,\n line: clampedLineIndex + 1,\n column: clampedColumnIndex + 1,\n };\n}\n\nfunction pushDiagnostic(\n context: ParserContext,\n diagnostic: Omit<PslDiagnostic, 'sourceId'> & { readonly code: PslDiagnosticCode },\n): void {\n context.diagnostics.push({\n ...diagnostic,\n sourceId: context.sourceId,\n });\n}\n"],"mappings":"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"}
package/dist/parser.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { t as parsePslDocument } from "./parser-1DZHweIq.mjs";
1
+ import { t as parsePslDocument } from "./parser-R7ldFfcr.mjs";
2
2
  export { parsePslDocument };
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@prisma-next/psl-parser",
3
- "version": "0.9.0-dev.8",
3
+ "version": "0.9.0-dev.9",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "sideEffects": false,
7
7
  "description": "Reusable parser for Prisma Schema Language (PSL)",
8
8
  "dependencies": {
9
- "@prisma-next/framework-components": "0.9.0-dev.8",
10
- "@prisma-next/utils": "0.9.0-dev.8"
9
+ "@prisma-next/framework-components": "0.9.0-dev.9",
10
+ "@prisma-next/utils": "0.9.0-dev.9"
11
11
  },
12
12
  "devDependencies": {
13
- "@prisma-next/tsconfig": "0.9.0-dev.8",
14
- "@prisma-next/tsdown": "0.9.0-dev.8",
13
+ "@prisma-next/tsconfig": "0.9.0-dev.9",
14
+ "@prisma-next/tsdown": "0.9.0-dev.9",
15
15
  "tsdown": "0.22.0",
16
16
  "typescript": "5.9.3",
17
17
  "vitest": "4.1.6"
@@ -20,6 +20,7 @@ export type {
20
20
  PslModel,
21
21
  PslModelAttribute,
22
22
  PslNamedTypeDeclaration,
23
+ PslNamespace,
23
24
  PslPosition,
24
25
  PslSpan,
25
26
  PslTypeConstructorCall,
package/src/parser.ts CHANGED
@@ -15,11 +15,13 @@ import type {
15
15
  PslModel,
16
16
  PslModelAttribute,
17
17
  PslNamedTypeDeclaration,
18
+ PslNamespace,
18
19
  PslPosition,
19
20
  PslSpan,
20
21
  PslTypeConstructorCall,
21
22
  PslTypesBlock,
22
23
  } from '@prisma-next/framework-components/psl-ast';
24
+ import { UNSPECIFIED_PSL_NAMESPACE_ID } from '@prisma-next/framework-components/psl-ast';
23
25
  import { ifDefined } from '@prisma-next/utils/defined';
24
26
 
25
27
  const SCALAR_TYPES = new Set([
@@ -61,92 +63,184 @@ export function parsePslDocument(input: ParsePslDocumentInput): ParsePslDocument
61
63
  diagnostics,
62
64
  };
63
65
 
64
- const models: PslModel[] = [];
65
- const enums: PslEnum[] = [];
66
- const compositeTypes: PslCompositeType[] = [];
67
- let typesBlock: PslTypesBlock | undefined;
66
+ interface NamespaceAccumulator {
67
+ name: string;
68
+ models: PslModel[];
69
+ enums: PslEnum[];
70
+ compositeTypes: PslCompositeType[];
71
+ span: PslSpan | undefined;
72
+ }
68
73
 
69
- let lineIndex = 0;
70
- while (lineIndex < lines.length) {
71
- const rawLine = lines[lineIndex] ?? '';
72
- const line = stripInlineComment(rawLine).trim();
73
- if (line.length === 0) {
74
- lineIndex += 1;
75
- continue;
74
+ const namespaceOrder: string[] = [];
75
+ const namespacesByName = new Map<string, NamespaceAccumulator>();
76
+ const getOrCreateNamespace = (
77
+ name: string,
78
+ spanIfNew: PslSpan | undefined,
79
+ ): NamespaceAccumulator => {
80
+ let acc = namespacesByName.get(name);
81
+ if (!acc) {
82
+ acc = { name, models: [], enums: [], compositeTypes: [], span: spanIfNew };
83
+ namespacesByName.set(name, acc);
84
+ namespaceOrder.push(name);
76
85
  }
86
+ return acc;
87
+ };
88
+
89
+ let typesBlock: PslTypesBlock | undefined;
90
+
91
+ // Walk a contiguous range of lines, routing top-level declarations into the
92
+ // active namespace bucket. Called once for the whole document and once per
93
+ // `namespace { … }` block body; nested `namespace { … }` or `types { … }`
94
+ // blocks inside a namespace body are rejected with a diagnostic.
95
+ const parseBody = (
96
+ startLine: number,
97
+ endLineExclusive: number,
98
+ currentNamespaceName: string,
99
+ isInsideNamespace: boolean,
100
+ ): void => {
101
+ let lineIndex = startLine;
102
+ while (lineIndex < endLineExclusive) {
103
+ const rawLine = context.lines[lineIndex] ?? '';
104
+ const line = stripInlineComment(rawLine).trim();
105
+ if (line.length === 0) {
106
+ lineIndex += 1;
107
+ continue;
108
+ }
77
109
 
78
- const modelMatch = line.match(/^model\s+([A-Za-z_]\w*)\s*\{$/);
79
- if (modelMatch) {
80
- const bounds = findBlockBounds(context, lineIndex);
81
- const name = modelMatch[1] ?? '';
82
- if (name.length === 0) {
110
+ const modelMatch = line.match(/^model\s+([A-Za-z_]\w*)\s*\{$/);
111
+ if (modelMatch) {
112
+ const bounds = findBlockBounds(context, lineIndex);
113
+ const name = modelMatch[1] ?? '';
114
+ if (name.length > 0) {
115
+ const acc = getOrCreateNamespace(
116
+ currentNamespaceName,
117
+ createTrimmedLineSpan(context, lineIndex),
118
+ );
119
+ acc.models.push(parseModelBlock(context, name, bounds));
120
+ }
83
121
  lineIndex = bounds.endLine + 1;
84
122
  continue;
85
123
  }
86
- models.push(parseModelBlock(context, name, bounds));
87
- lineIndex = bounds.endLine + 1;
88
- continue;
89
- }
90
124
 
91
- const enumMatch = line.match(/^enum\s+([A-Za-z_]\w*)\s*\{$/);
92
- if (enumMatch) {
93
- const bounds = findBlockBounds(context, lineIndex);
94
- const name = enumMatch[1] ?? '';
95
- if (name.length === 0) {
125
+ const enumMatch = line.match(/^enum\s+([A-Za-z_]\w*)\s*\{$/);
126
+ if (enumMatch) {
127
+ const bounds = findBlockBounds(context, lineIndex);
128
+ const name = enumMatch[1] ?? '';
129
+ if (name.length > 0) {
130
+ const acc = getOrCreateNamespace(
131
+ currentNamespaceName,
132
+ createTrimmedLineSpan(context, lineIndex),
133
+ );
134
+ acc.enums.push(parseEnumBlock(context, name, bounds));
135
+ }
96
136
  lineIndex = bounds.endLine + 1;
97
137
  continue;
98
138
  }
99
- enums.push(parseEnumBlock(context, name, bounds));
100
- lineIndex = bounds.endLine + 1;
101
- continue;
102
- }
103
139
 
104
- const compositeTypeMatch = line.match(/^type\s+([A-Za-z_]\w*)\s*\{$/);
105
- if (compositeTypeMatch) {
106
- const bounds = findBlockBounds(context, lineIndex);
107
- const name = compositeTypeMatch[1] ?? '';
108
- if (name.length === 0) {
140
+ const compositeTypeMatch = line.match(/^type\s+([A-Za-z_]\w*)\s*\{$/);
141
+ if (compositeTypeMatch) {
142
+ const bounds = findBlockBounds(context, lineIndex);
143
+ const name = compositeTypeMatch[1] ?? '';
144
+ if (name.length > 0) {
145
+ const acc = getOrCreateNamespace(
146
+ currentNamespaceName,
147
+ createTrimmedLineSpan(context, lineIndex),
148
+ );
149
+ acc.compositeTypes.push(parseCompositeTypeBlock(context, name, bounds));
150
+ }
109
151
  lineIndex = bounds.endLine + 1;
110
152
  continue;
111
153
  }
112
- compositeTypes.push(parseCompositeTypeBlock(context, name, bounds));
113
- lineIndex = bounds.endLine + 1;
114
- continue;
115
- }
116
154
 
117
- if (/^types\s*\{$/.test(line)) {
118
- const bounds = findBlockBounds(context, lineIndex);
119
- typesBlock = parseTypesBlock(context, bounds);
120
- lineIndex = bounds.endLine + 1;
121
- continue;
122
- }
155
+ const namespaceMatch = line.match(/^namespace\s+([A-Za-z_]\w*)\s*\{$/);
156
+ if (namespaceMatch) {
157
+ const bounds = findBlockBounds(context, lineIndex);
158
+ const name = namespaceMatch[1] ?? '';
159
+ if (isInsideNamespace) {
160
+ pushDiagnostic(context, {
161
+ code: 'PSL_INVALID_NAMESPACE_BLOCK',
162
+ message: `Recursive "namespace ${name}" block is not allowed; namespace blocks may not nest`,
163
+ span: createTrimmedLineSpan(context, lineIndex),
164
+ });
165
+ } else if (name === UNSPECIFIED_PSL_NAMESPACE_ID) {
166
+ pushDiagnostic(context, {
167
+ code: 'PSL_INVALID_NAMESPACE_BLOCK',
168
+ message: `Namespace name "${UNSPECIFIED_PSL_NAMESPACE_ID}" is reserved for the parser-synthesised bucket for top-level declarations`,
169
+ span: createTrimmedLineSpan(context, lineIndex),
170
+ });
171
+ } else if (name.length > 0) {
172
+ getOrCreateNamespace(name, createTrimmedLineSpan(context, lineIndex));
173
+ parseBody(bounds.startLine + 1, bounds.endLine, name, true);
174
+ }
175
+ lineIndex = bounds.endLine + 1;
176
+ continue;
177
+ }
178
+
179
+ if (/^types\s*\{$/.test(line)) {
180
+ const bounds = findBlockBounds(context, lineIndex);
181
+ if (isInsideNamespace) {
182
+ pushDiagnostic(context, {
183
+ code: 'PSL_INVALID_NAMESPACE_BLOCK',
184
+ message:
185
+ '`types` blocks must be declared at the document top level, not inside a namespace block',
186
+ span: createTrimmedLineSpan(context, lineIndex),
187
+ });
188
+ } else if (typesBlock !== undefined) {
189
+ pushDiagnostic(context, {
190
+ code: 'PSL_INVALID_TYPES_MEMBER',
191
+ message: 'Only one top-level `types` block is allowed per document',
192
+ span: createTrimmedLineSpan(context, lineIndex),
193
+ });
194
+ } else {
195
+ typesBlock = parseTypesBlock(context, bounds);
196
+ }
197
+ lineIndex = bounds.endLine + 1;
198
+ continue;
199
+ }
200
+
201
+ if (line.includes('{')) {
202
+ const blockName = line.split(/\s+/)[0] ?? 'block';
203
+ pushDiagnostic(context, {
204
+ code: 'PSL_UNSUPPORTED_TOP_LEVEL_BLOCK',
205
+ message: `Unsupported top-level block "${blockName}"`,
206
+ span: createTrimmedLineSpan(context, lineIndex),
207
+ });
208
+ const bounds = findBlockBounds(context, lineIndex);
209
+ lineIndex = bounds.endLine + 1;
210
+ continue;
211
+ }
123
212
 
124
- if (line.includes('{')) {
125
- const blockName = line.split(/\s+/)[0] ?? 'block';
126
213
  pushDiagnostic(context, {
127
214
  code: 'PSL_UNSUPPORTED_TOP_LEVEL_BLOCK',
128
- message: `Unsupported top-level block "${blockName}"`,
215
+ message: `Unsupported top-level declaration "${line}"`,
129
216
  span: createTrimmedLineSpan(context, lineIndex),
130
217
  });
131
- const bounds = findBlockBounds(context, lineIndex);
132
- lineIndex = bounds.endLine + 1;
133
- continue;
218
+ lineIndex += 1;
134
219
  }
220
+ };
135
221
 
136
- pushDiagnostic(context, {
137
- code: 'PSL_UNSUPPORTED_TOP_LEVEL_BLOCK',
138
- message: `Unsupported top-level declaration "${line}"`,
139
- span: createTrimmedLineSpan(context, lineIndex),
140
- });
141
- lineIndex += 1;
222
+ parseBody(0, lines.length, UNSPECIFIED_PSL_NAMESPACE_ID, false);
223
+
224
+ // Named-type validation: types are document-scoped (one block, outside any
225
+ // namespace), so collision checks compare named-type names against every
226
+ // model/enum/composite-type in every namespace.
227
+ const allModels: PslModel[] = [];
228
+ const allEnums: PslEnum[] = [];
229
+ const allCompositeTypes: PslCompositeType[] = [];
230
+ for (const name of namespaceOrder) {
231
+ const acc = namespacesByName.get(name);
232
+ if (!acc) continue;
233
+ allModels.push(...acc.models);
234
+ allEnums.push(...acc.enums);
235
+ allCompositeTypes.push(...acc.compositeTypes);
142
236
  }
143
237
 
144
238
  const namedTypeNames = new Set(
145
239
  (typesBlock?.declarations ?? []).map((declaration) => declaration.name),
146
240
  );
147
- const modelNames = new Set(models.map((model) => model.name));
148
- const enumNames = new Set(enums.map((enumBlock) => enumBlock.name));
149
- const compositeTypeNames = new Set(compositeTypes.map((ct) => ct.name));
241
+ const modelNames = new Set(allModels.map((model) => model.name));
242
+ const enumNames = new Set(allEnums.map((enumBlock) => enumBlock.name));
243
+ const compositeTypeNames = new Set(allCompositeTypes.map((ct) => ct.name));
150
244
  for (const declaration of typesBlock?.declarations ?? []) {
151
245
  if (SCALAR_TYPES.has(declaration.name)) {
152
246
  pushDiagnostic(context, {
@@ -172,46 +266,72 @@ export function parsePslDocument(input: ParsePslDocumentInput): ParsePslDocument
172
266
  });
173
267
  }
174
268
  }
175
- const normalizedModels = models.map((model) => ({
176
- ...model,
177
- fields: model.fields.map((field) => {
178
- if (!namedTypeNames.has(field.typeName)) {
179
- return field;
180
- }
181
- const hasRelationAttribute = field.attributes.some(
182
- (attribute) => attribute.name === 'relation',
183
- );
184
- if (
185
- hasRelationAttribute ||
186
- modelNames.has(field.typeName) ||
187
- enumNames.has(field.typeName) ||
188
- compositeTypeNames.has(field.typeName) ||
189
- SCALAR_TYPES.has(field.typeName)
190
- ) {
191
- return field;
192
- }
193
- return {
194
- ...field,
195
- typeRef: field.typeName,
196
- };
197
- }),
198
- }));
269
+
270
+ const documentSpan: PslSpan = {
271
+ start: createPosition(context, 0, 0),
272
+ end: createPosition(
273
+ context,
274
+ Math.max(lines.length - 1, 0),
275
+ (lines[Math.max(lines.length - 1, 0)] ?? '').length,
276
+ ),
277
+ };
278
+
279
+ const namespaces: PslNamespace[] = [];
280
+ for (const name of namespaceOrder) {
281
+ const acc = namespacesByName.get(name);
282
+ if (!acc) continue;
283
+ // Drop the synthesised __unspecified__ entry when it ended up empty (e.g.
284
+ // every declaration in the document lived inside an explicit
285
+ // `namespace { … }` block). Keeping a phantom bucket would force every
286
+ // downstream consumer to special-case "namespace with no members".
287
+ if (
288
+ name === UNSPECIFIED_PSL_NAMESPACE_ID &&
289
+ acc.models.length === 0 &&
290
+ acc.enums.length === 0 &&
291
+ acc.compositeTypes.length === 0
292
+ ) {
293
+ continue;
294
+ }
295
+ const normalizedModels = acc.models.map((model) => ({
296
+ ...model,
297
+ fields: model.fields.map((field) => {
298
+ if (!namedTypeNames.has(field.typeName)) {
299
+ return field;
300
+ }
301
+ const hasRelationAttribute = field.attributes.some(
302
+ (attribute) => attribute.name === 'relation',
303
+ );
304
+ if (
305
+ hasRelationAttribute ||
306
+ modelNames.has(field.typeName) ||
307
+ enumNames.has(field.typeName) ||
308
+ compositeTypeNames.has(field.typeName) ||
309
+ SCALAR_TYPES.has(field.typeName)
310
+ ) {
311
+ return field;
312
+ }
313
+ return {
314
+ ...field,
315
+ typeRef: field.typeName,
316
+ };
317
+ }),
318
+ }));
319
+ namespaces.push({
320
+ kind: 'namespace',
321
+ name,
322
+ models: normalizedModels,
323
+ enums: acc.enums,
324
+ compositeTypes: acc.compositeTypes,
325
+ span: acc.span ?? documentSpan,
326
+ });
327
+ }
199
328
 
200
329
  const ast: PslDocumentAst = {
201
330
  kind: 'document',
202
331
  sourceId: input.sourceId,
203
- models: normalizedModels,
204
- enums,
205
- compositeTypes,
332
+ namespaces,
206
333
  ...ifDefined('types', typesBlock),
207
- span: {
208
- start: createPosition(context, 0, 0),
209
- end: createPosition(
210
- context,
211
- Math.max(lines.length - 1, 0),
212
- (lines[Math.max(lines.length - 1, 0)] ?? '').length,
213
- ),
214
- },
334
+ span: documentSpan,
215
335
  };
216
336
 
217
337
  return {
@@ -665,15 +785,41 @@ function parseField(context: ParserContext, line: string, lineIndex: number): Ps
665
785
  return undefined;
666
786
  }
667
787
 
668
- const simpleTypeMatch = baseTypeSource.match(/^([A-Za-z_]\w*)$/);
669
- const typeName = typeConstructor?.path.join('.') ?? simpleTypeMatch?.[1];
670
- if (!typeName) {
671
- pushDiagnostic(context, {
672
- code: 'PSL_INVALID_MODEL_MEMBER',
673
- message: `Invalid model member declaration "${line}"`,
674
- span: createTrimmedLineSpan(context, lineIndex),
675
- });
676
- return undefined;
788
+ let typeName: string;
789
+ let typeNamespaceId: string | undefined;
790
+
791
+ if (typeConstructor) {
792
+ typeName = typeConstructor.path.join('.');
793
+ } else {
794
+ const dotCount = (baseTypeSource.match(/\./g) ?? []).length;
795
+ if (dotCount > 1) {
796
+ pushDiagnostic(context, {
797
+ code: 'PSL_INVALID_QUALIFIED_TYPE',
798
+ message: `Nested dot-qualified type "${baseTypeSource}" is not supported; use exactly one qualifier segment (e.g. "ns.TypeName")`,
799
+ span: createInlineSpan(
800
+ context,
801
+ lineIndex,
802
+ typeStartColumn,
803
+ typeStartColumn + baseTypeSource.length,
804
+ ),
805
+ });
806
+ return undefined;
807
+ }
808
+ const singleMatch = baseTypeSource.match(/^([A-Za-z_]\w*)(?:\.([A-Za-z_]\w*))?$/);
809
+ if (!singleMatch) {
810
+ pushDiagnostic(context, {
811
+ code: 'PSL_INVALID_MODEL_MEMBER',
812
+ message: `Invalid model member declaration "${line}"`,
813
+ span: createTrimmedLineSpan(context, lineIndex),
814
+ });
815
+ return undefined;
816
+ }
817
+ if (singleMatch[2] !== undefined) {
818
+ typeNamespaceId = singleMatch[1];
819
+ typeName = singleMatch[2];
820
+ } else {
821
+ typeName = singleMatch[1] ?? '';
822
+ }
677
823
  }
678
824
 
679
825
  const attributes: PslFieldAttribute[] = [];
@@ -694,6 +840,7 @@ function parseField(context: ParserContext, line: string, lineIndex: number): Ps
694
840
  kind: 'field',
695
841
  name: fieldName,
696
842
  typeName,
843
+ ...ifDefined('typeNamespaceId', typeNamespaceId),
697
844
  ...ifDefined('typeConstructor', typeConstructor),
698
845
  optional,
699
846
  list,
@@ -718,6 +865,7 @@ function parseField(context: ParserContext, line: string, lineIndex: number): Ps
718
865
  kind: 'field',
719
866
  name: fieldName,
720
867
  typeName,
868
+ ...ifDefined('typeNamespaceId', typeNamespaceId),
721
869
  ...ifDefined('typeConstructor', typeConstructor),
722
870
  optional,
723
871
  list,
@@ -1 +0,0 @@
1
- {"version":3,"file":"parser-1DZHweIq.mjs","names":[],"sources":["../src/parser.ts"],"sourcesContent":["import type {\n ParsePslDocumentInput,\n ParsePslDocumentResult,\n PslAttribute,\n PslAttributeArgument,\n PslAttributeTarget,\n PslCompositeType,\n PslDiagnostic,\n PslDiagnosticCode,\n PslDocumentAst,\n PslEnum,\n PslEnumValue,\n PslField,\n PslFieldAttribute,\n PslModel,\n PslModelAttribute,\n PslNamedTypeDeclaration,\n PslPosition,\n PslSpan,\n PslTypeConstructorCall,\n PslTypesBlock,\n} from '@prisma-next/framework-components/psl-ast';\nimport { ifDefined } from '@prisma-next/utils/defined';\n\nconst SCALAR_TYPES = new Set([\n 'String',\n 'Boolean',\n 'Int',\n 'BigInt',\n 'Float',\n 'Decimal',\n 'DateTime',\n 'Json',\n 'Bytes',\n]);\n\ninterface BlockBounds {\n readonly startLine: number;\n readonly endLine: number;\n readonly closed: boolean;\n}\n\ninterface ParserContext {\n readonly schema: string;\n readonly sourceId: string;\n readonly lines: readonly string[];\n readonly lineOffsets: readonly number[];\n readonly diagnostics: PslDiagnostic[];\n}\n\nexport function parsePslDocument(input: ParsePslDocumentInput): ParsePslDocumentResult {\n const normalizedSchema = input.schema.replaceAll('\\r\\n', '\\n');\n const lines = normalizedSchema.split('\\n');\n const lineOffsets = computeLineOffsets(normalizedSchema);\n const diagnostics: PslDiagnostic[] = [];\n const context: ParserContext = {\n schema: normalizedSchema,\n sourceId: input.sourceId,\n lines,\n lineOffsets,\n diagnostics,\n };\n\n const models: PslModel[] = [];\n const enums: PslEnum[] = [];\n const compositeTypes: PslCompositeType[] = [];\n let typesBlock: PslTypesBlock | undefined;\n\n let lineIndex = 0;\n while (lineIndex < lines.length) {\n const rawLine = lines[lineIndex] ?? '';\n const line = stripInlineComment(rawLine).trim();\n if (line.length === 0) {\n lineIndex += 1;\n continue;\n }\n\n const modelMatch = line.match(/^model\\s+([A-Za-z_]\\w*)\\s*\\{$/);\n if (modelMatch) {\n const bounds = findBlockBounds(context, lineIndex);\n const name = modelMatch[1] ?? '';\n if (name.length === 0) {\n lineIndex = bounds.endLine + 1;\n continue;\n }\n models.push(parseModelBlock(context, name, bounds));\n lineIndex = bounds.endLine + 1;\n continue;\n }\n\n const enumMatch = line.match(/^enum\\s+([A-Za-z_]\\w*)\\s*\\{$/);\n if (enumMatch) {\n const bounds = findBlockBounds(context, lineIndex);\n const name = enumMatch[1] ?? '';\n if (name.length === 0) {\n lineIndex = bounds.endLine + 1;\n continue;\n }\n enums.push(parseEnumBlock(context, name, bounds));\n lineIndex = bounds.endLine + 1;\n continue;\n }\n\n const compositeTypeMatch = line.match(/^type\\s+([A-Za-z_]\\w*)\\s*\\{$/);\n if (compositeTypeMatch) {\n const bounds = findBlockBounds(context, lineIndex);\n const name = compositeTypeMatch[1] ?? '';\n if (name.length === 0) {\n lineIndex = bounds.endLine + 1;\n continue;\n }\n compositeTypes.push(parseCompositeTypeBlock(context, name, bounds));\n lineIndex = bounds.endLine + 1;\n continue;\n }\n\n if (/^types\\s*\\{$/.test(line)) {\n const bounds = findBlockBounds(context, lineIndex);\n typesBlock = parseTypesBlock(context, bounds);\n lineIndex = bounds.endLine + 1;\n continue;\n }\n\n if (line.includes('{')) {\n const blockName = line.split(/\\s+/)[0] ?? 'block';\n pushDiagnostic(context, {\n code: 'PSL_UNSUPPORTED_TOP_LEVEL_BLOCK',\n message: `Unsupported top-level block \"${blockName}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n const bounds = findBlockBounds(context, lineIndex);\n lineIndex = bounds.endLine + 1;\n continue;\n }\n\n pushDiagnostic(context, {\n code: 'PSL_UNSUPPORTED_TOP_LEVEL_BLOCK',\n message: `Unsupported top-level declaration \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n lineIndex += 1;\n }\n\n const namedTypeNames = new Set(\n (typesBlock?.declarations ?? []).map((declaration) => declaration.name),\n );\n const modelNames = new Set(models.map((model) => model.name));\n const enumNames = new Set(enums.map((enumBlock) => enumBlock.name));\n const compositeTypeNames = new Set(compositeTypes.map((ct) => ct.name));\n for (const declaration of typesBlock?.declarations ?? []) {\n if (SCALAR_TYPES.has(declaration.name)) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_TYPES_MEMBER',\n message: `Named type \"${declaration.name}\" conflicts with scalar type \"${declaration.name}\"`,\n span: declaration.span,\n });\n continue;\n }\n if (modelNames.has(declaration.name)) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_TYPES_MEMBER',\n message: `Named type \"${declaration.name}\" conflicts with model name \"${declaration.name}\"`,\n span: declaration.span,\n });\n continue;\n }\n if (enumNames.has(declaration.name)) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_TYPES_MEMBER',\n message: `Named type \"${declaration.name}\" conflicts with enum name \"${declaration.name}\"`,\n span: declaration.span,\n });\n }\n }\n const normalizedModels = models.map((model) => ({\n ...model,\n fields: model.fields.map((field) => {\n if (!namedTypeNames.has(field.typeName)) {\n return field;\n }\n const hasRelationAttribute = field.attributes.some(\n (attribute) => attribute.name === 'relation',\n );\n if (\n hasRelationAttribute ||\n modelNames.has(field.typeName) ||\n enumNames.has(field.typeName) ||\n compositeTypeNames.has(field.typeName) ||\n SCALAR_TYPES.has(field.typeName)\n ) {\n return field;\n }\n return {\n ...field,\n typeRef: field.typeName,\n };\n }),\n }));\n\n const ast: PslDocumentAst = {\n kind: 'document',\n sourceId: input.sourceId,\n models: normalizedModels,\n enums,\n compositeTypes,\n ...ifDefined('types', typesBlock),\n span: {\n start: createPosition(context, 0, 0),\n end: createPosition(\n context,\n Math.max(lines.length - 1, 0),\n (lines[Math.max(lines.length - 1, 0)] ?? '').length,\n ),\n },\n };\n\n return {\n ast,\n diagnostics,\n ok: diagnostics.length === 0,\n };\n}\n\nfunction parseModelBlock(context: ParserContext, name: string, bounds: BlockBounds): PslModel {\n const fields: PslField[] = [];\n const attributes: PslModelAttribute[] = [];\n\n for (let lineIndex = bounds.startLine + 1; lineIndex < bounds.endLine; lineIndex += 1) {\n const raw = context.lines[lineIndex] ?? '';\n const line = stripInlineComment(raw).trim();\n if (line.length === 0) {\n continue;\n }\n\n if (line.startsWith('@@')) {\n const attribute = parseModelAttribute(context, line, lineIndex);\n if (attribute) {\n attributes.push(attribute);\n }\n continue;\n }\n\n const field = parseField(context, line, lineIndex);\n if (field) {\n fields.push(field);\n }\n }\n\n return {\n kind: 'model',\n name,\n fields,\n attributes,\n span: createLineRangeSpan(context, bounds.startLine, bounds.endLine),\n };\n}\n\nfunction parseCompositeTypeBlock(\n context: ParserContext,\n name: string,\n bounds: BlockBounds,\n): PslCompositeType {\n const fields: PslField[] = [];\n const attributes: PslAttribute[] = [];\n\n for (let lineIndex = bounds.startLine + 1; lineIndex < bounds.endLine; lineIndex += 1) {\n const raw = context.lines[lineIndex] ?? '';\n const line = stripInlineComment(raw).trim();\n if (line.length === 0) {\n continue;\n }\n\n if (line.startsWith('@@')) {\n const attribute = parseModelAttribute(context, line, lineIndex);\n if (attribute) {\n attributes.push(attribute);\n }\n continue;\n }\n\n const field = parseField(context, line, lineIndex);\n if (field) {\n fields.push(field);\n }\n }\n\n return {\n kind: 'compositeType',\n name,\n fields,\n attributes,\n span: createLineRangeSpan(context, bounds.startLine, bounds.endLine),\n };\n}\n\nfunction parseEnumBlock(context: ParserContext, name: string, bounds: BlockBounds): PslEnum {\n const values: PslEnumValue[] = [];\n const attributes: PslAttribute[] = [];\n\n for (let lineIndex = bounds.startLine + 1; lineIndex < bounds.endLine; lineIndex += 1) {\n const raw = context.lines[lineIndex] ?? '';\n const line = stripInlineComment(raw).trim();\n if (line.length === 0) {\n continue;\n }\n\n if (line.startsWith('@@')) {\n const attribute = parseEnumAttribute(context, line, lineIndex);\n if (attribute) {\n attributes.push(attribute);\n }\n continue;\n }\n\n // An enum member line is the bare member identifier, optionally followed\n // by a `@map(\"storage-label\")` attribute. The map attribute lets the\n // printer round-trip enum values whose original storage label is not a\n // valid PSL identifier (e.g. PostgreSQL enum labels with hyphens).\n const valueMatch = line.match(/^([A-Za-z_]\\w*)(?:\\s+@map\\(\\s*\"((?:[^\"\\\\]|\\\\.)*)\"\\s*\\))?$/);\n if (!valueMatch) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ENUM_MEMBER',\n message: `Invalid enum value declaration \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n continue;\n }\n\n const mapName = valueMatch[2] !== undefined ? unescapePslString(valueMatch[2]) : undefined;\n\n values.push({\n kind: 'enumValue',\n name: valueMatch[1] ?? '',\n ...(mapName !== undefined ? { mapName } : {}),\n span: createTrimmedLineSpan(context, lineIndex),\n });\n }\n\n return {\n kind: 'enum',\n name,\n values,\n attributes,\n span: createLineRangeSpan(context, bounds.startLine, bounds.endLine),\n };\n}\n\n/**\n * Decode PSL escape sequences (`\\\\`, `\\\"`, `\\'`, `\\n`, `\\r`) inside a\n * quoted-literal body. The argument is the body of the literal with the\n * surrounding quotes already stripped by the caller. Mirrors the inverse\n * helper in `@prisma-next/psl-printer`'s `escapePslString` so a string\n * round-trips parser → printer → parser unchanged.\n */\nfunction unescapePslString(value: string): string {\n let result = '';\n for (let i = 0; i < value.length; i++) {\n const ch = value.charCodeAt(i);\n if (ch !== 0x5c /* '\\\\' */ || i + 1 >= value.length) {\n result += value[i];\n continue;\n }\n const next = value[i + 1];\n if (next === '\\\\' || next === '\"' || next === \"'\") {\n result += next;\n } else if (next === 'n') {\n result += '\\n';\n } else if (next === 'r') {\n result += '\\r';\n } else {\n result += '\\\\';\n result += next;\n }\n i++;\n }\n return result;\n}\n\nfunction parseTypesBlock(context: ParserContext, bounds: BlockBounds): PslTypesBlock {\n const declarations: PslNamedTypeDeclaration[] = [];\n\n for (let lineIndex = bounds.startLine + 1; lineIndex < bounds.endLine; lineIndex += 1) {\n const raw = context.lines[lineIndex] ?? '';\n const lineWithoutComment = stripInlineComment(raw);\n const line = lineWithoutComment.trim();\n if (line.length === 0) {\n continue;\n }\n\n const declarationMatch = line.match(/^([A-Za-z_]\\w*)\\s*=\\s*(.+)$/);\n if (!declarationMatch) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_TYPES_MEMBER',\n message: `Invalid types declaration \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n continue;\n }\n\n const declarationName = declarationMatch[1] ?? '';\n const trimmedStartColumn = firstNonWhitespaceColumn(raw);\n const declarationValue = (declarationMatch[2] ?? '').trim();\n const valueOffset = line.indexOf(declarationValue);\n const declarationValueColumn = trimmedStartColumn + Math.max(valueOffset, 0);\n\n const typeAndAttributeSplit = splitTypeAndAttributes(declarationValue);\n const typeSource = typeAndAttributeSplit.typeSource.trim();\n const attributeSource = typeAndAttributeSplit.attributeSource.trimStart();\n const leadingAttributeWhitespace =\n typeAndAttributeSplit.attributeSource.length - attributeSource.length;\n\n const typeConstructor = parseTypeConstructorCall(context, {\n declarationValue: typeSource,\n lineIndex,\n startColumn: declarationValueColumn,\n invalidCode: 'PSL_INVALID_TYPES_MEMBER',\n invalidMessage: (value) => `Invalid types declaration \"${value}\"`,\n });\n if (typeConstructor === 'malformed') {\n continue;\n }\n\n const attributeParse = extractAttributeTokensWithSpans(\n context,\n lineIndex,\n attributeSource,\n declarationValueColumn + typeAndAttributeSplit.attributeOffset + leadingAttributeWhitespace,\n );\n if (!attributeParse.ok) {\n continue;\n }\n const attributes = attributeParse.tokens\n .map((token) =>\n parseAttributeToken(context, {\n token: token.text,\n target: 'namedType',\n lineIndex,\n span: token.span,\n }),\n )\n .filter((attribute): attribute is PslAttribute => Boolean(attribute));\n\n if (typeConstructor) {\n declarations.push({\n kind: 'namedType',\n name: declarationName,\n typeConstructor,\n attributes,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n continue;\n }\n\n const baseTypeMatch = typeSource.match(/^([A-Za-z_]\\w*)$/);\n if (!baseTypeMatch) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_TYPES_MEMBER',\n message: `Invalid types declaration \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n continue;\n }\n\n const baseType = baseTypeMatch[1] ?? '';\n\n declarations.push({\n kind: 'namedType',\n name: declarationName,\n baseType,\n attributes,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n }\n\n return {\n kind: 'types',\n declarations,\n span: createLineRangeSpan(context, bounds.startLine, bounds.endLine),\n };\n}\n\nfunction parseTypeConstructorCall(\n context: ParserContext,\n input: {\n readonly declarationValue: string;\n readonly lineIndex: number;\n readonly startColumn: number;\n readonly invalidCode: PslDiagnosticCode;\n readonly invalidMessage: (value: string) => string;\n },\n): PslTypeConstructorCall | 'malformed' | undefined {\n const value = input.declarationValue.trim();\n const constructorMatch = value.match(\n /^([A-Za-z_][A-Za-z0-9_-]*(?:\\.[A-Za-z_][A-Za-z0-9_-]*)*)\\s*\\(/,\n );\n if (!constructorMatch) {\n return undefined;\n }\n\n // constructorMatch already required `(`; openParen is guaranteed ≥ 0.\n const openParen = value.indexOf('(');\n const closeParen = value.lastIndexOf(')');\n\n if (closeParen !== value.length - 1) {\n pushDiagnostic(context, {\n code: input.invalidCode,\n message: input.invalidMessage(value),\n span: createInlineSpan(\n context,\n input.lineIndex,\n input.startColumn,\n input.startColumn + value.length,\n ),\n });\n return 'malformed';\n }\n\n const constructorPath = constructorMatch[1] ?? '';\n\n const argsRaw = value.slice(openParen + 1, closeParen);\n const args = parseArgumentList(context, {\n argsRaw,\n argsOffset: input.startColumn + openParen + 1,\n lineIndex: input.lineIndex,\n token: value,\n span: createInlineSpan(\n context,\n input.lineIndex,\n input.startColumn,\n input.startColumn + value.length,\n ),\n invalidCode: input.invalidCode,\n invalidEmptyArgumentMessage: `Invalid empty argument in type constructor \"${value}\"`,\n invalidNamedArgumentMessage: (part) =>\n `Invalid named argument syntax \"${part}\" in type constructor \"${value}\"`,\n });\n if (!args) {\n return 'malformed';\n }\n\n return {\n kind: 'typeConstructor',\n path: constructorPath.split('.'),\n args,\n span: createInlineSpan(\n context,\n input.lineIndex,\n input.startColumn,\n input.startColumn + value.length,\n ),\n };\n}\n\nfunction parseModelAttribute(\n context: ParserContext,\n line: string,\n lineIndex: number,\n): PslModelAttribute | undefined {\n const rawLine = context.lines[lineIndex] ?? '';\n const tokenParse = extractAttributeTokensWithSpans(\n context,\n lineIndex,\n line,\n firstNonWhitespaceColumn(rawLine),\n );\n if (!tokenParse.ok || tokenParse.tokens.length !== 1) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Invalid model attribute syntax \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n return undefined;\n }\n const token = tokenParse.tokens[0];\n if (!token) {\n return undefined;\n }\n return parseAttributeToken(context, {\n token: token.text,\n target: 'model',\n lineIndex,\n span: token.span,\n });\n}\n\nfunction parseEnumAttribute(\n context: ParserContext,\n line: string,\n lineIndex: number,\n): PslAttribute | undefined {\n const rawLine = context.lines[lineIndex] ?? '';\n const tokenParse = extractAttributeTokensWithSpans(\n context,\n lineIndex,\n line,\n firstNonWhitespaceColumn(rawLine),\n );\n if (!tokenParse.ok || tokenParse.tokens.length !== 1) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ENUM_MEMBER',\n message: `Invalid enum value declaration \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n return undefined;\n }\n const token = tokenParse.tokens[0];\n if (!token) {\n return undefined;\n }\n const parsed = parseAttributeToken(context, {\n token: token.text,\n target: 'enum',\n lineIndex,\n span: token.span,\n });\n if (!parsed) {\n return undefined;\n }\n if (parsed.name !== 'map') {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ENUM_MEMBER',\n message: `Invalid enum value declaration \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n return undefined;\n }\n return parsed;\n}\n\nfunction parseField(context: ParserContext, line: string, lineIndex: number): PslField | undefined {\n const fieldMatch = line.match(/^([A-Za-z_]\\w*)(\\s+)(.+)$/);\n if (!fieldMatch) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_MODEL_MEMBER',\n message: `Invalid model member declaration \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n return undefined;\n }\n\n const fieldName = fieldMatch[1] ?? '';\n const separator = fieldMatch[2] ?? '';\n const remainder = fieldMatch[3] ?? '';\n const typeAndAttributeSplit = splitTypeAndAttributes(remainder);\n const rawTypeSource = typeAndAttributeSplit.typeSource.trim();\n const attributePart = typeAndAttributeSplit.attributeSource;\n const optional = rawTypeSource.endsWith('?');\n const typeSourceWithoutOptional = optional ? rawTypeSource.slice(0, -1).trimEnd() : rawTypeSource;\n const list = typeSourceWithoutOptional.endsWith('[]');\n const baseTypeSource = list\n ? typeSourceWithoutOptional.slice(0, -2).trimEnd()\n : typeSourceWithoutOptional;\n const rawLine = context.lines[lineIndex] ?? '';\n const trimmedStartColumn = firstNonWhitespaceColumn(rawLine);\n const typeStartColumn = trimmedStartColumn + fieldName.length + separator.length;\n\n const typeConstructor = parseTypeConstructorCall(context, {\n declarationValue: baseTypeSource,\n lineIndex,\n startColumn: typeStartColumn,\n invalidCode: 'PSL_INVALID_MODEL_MEMBER',\n invalidMessage: (value) => `Invalid field type constructor \"${value}\"`,\n });\n if (typeConstructor === 'malformed') {\n return undefined;\n }\n\n const simpleTypeMatch = baseTypeSource.match(/^([A-Za-z_]\\w*)$/);\n const typeName = typeConstructor?.path.join('.') ?? simpleTypeMatch?.[1];\n if (!typeName) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_MODEL_MEMBER',\n message: `Invalid model member declaration \"${line}\"`,\n span: createTrimmedLineSpan(context, lineIndex),\n });\n return undefined;\n }\n\n const attributes: PslFieldAttribute[] = [];\n const attributeSource = attributePart.trimStart();\n const leadingAttributeWhitespace = attributePart.length - attributeSource.length;\n const tokenParse = extractAttributeTokensWithSpans(\n context,\n lineIndex,\n attributeSource,\n trimmedStartColumn +\n fieldName.length +\n separator.length +\n typeAndAttributeSplit.attributeOffset +\n leadingAttributeWhitespace,\n );\n if (!tokenParse.ok) {\n return {\n kind: 'field',\n name: fieldName,\n typeName,\n ...ifDefined('typeConstructor', typeConstructor),\n optional,\n list,\n attributes,\n span: createTrimmedLineSpan(context, lineIndex),\n };\n }\n\n for (const token of tokenParse.tokens) {\n const parsed = parseAttributeToken(context, {\n token: token.text,\n target: 'field',\n lineIndex,\n span: token.span,\n });\n if (parsed) {\n attributes.push(parsed);\n }\n }\n\n return {\n kind: 'field',\n name: fieldName,\n typeName,\n ...ifDefined('typeConstructor', typeConstructor),\n optional,\n list,\n attributes,\n span: createTrimmedLineSpan(context, lineIndex),\n };\n}\n\nfunction isQuoteEscaped(value: string, quoteIndex: number): boolean {\n let backslashCount = 0;\n\n for (let index = quoteIndex - 1; index >= 0 && value[index] === '\\\\'; index -= 1) {\n backslashCount += 1;\n }\n\n return backslashCount % 2 === 1;\n}\n\nfunction splitTypeAndAttributes(value: string): {\n readonly typeSource: string;\n readonly attributeSource: string;\n readonly attributeOffset: number;\n} {\n let depthParen = 0;\n let depthBracket = 0;\n let depthBrace = 0;\n let quote: '\"' | \"'\" | null = null;\n\n for (let index = 0; index < value.length; index += 1) {\n const character = value[index] ?? '';\n if (quote) {\n if (character === quote && !isQuoteEscaped(value, index)) {\n quote = null;\n }\n continue;\n }\n\n if (character === '\"' || character === \"'\") {\n quote = character;\n continue;\n }\n if (character === '(') {\n depthParen += 1;\n continue;\n }\n if (character === ')') {\n depthParen = Math.max(0, depthParen - 1);\n continue;\n }\n if (character === '[') {\n depthBracket += 1;\n continue;\n }\n if (character === ']') {\n depthBracket = Math.max(0, depthBracket - 1);\n continue;\n }\n if (character === '{') {\n depthBrace += 1;\n continue;\n }\n if (character === '}') {\n depthBrace = Math.max(0, depthBrace - 1);\n continue;\n }\n\n if (character === '@' && depthParen === 0 && depthBracket === 0 && depthBrace === 0) {\n return {\n typeSource: value.slice(0, index).trimEnd(),\n attributeSource: value.slice(index),\n attributeOffset: index,\n };\n }\n }\n\n return {\n typeSource: value.trimEnd(),\n attributeSource: '',\n attributeOffset: value.length,\n };\n}\n\nfunction parseAttributeToken(\n context: ParserContext,\n input: {\n readonly token: string;\n readonly target: PslAttributeTarget;\n readonly lineIndex: number;\n readonly span: PslSpan;\n },\n): PslAttribute | undefined {\n const expectsBlockPrefix = input.target === 'model' || input.target === 'enum';\n const targetLabel = input.target === 'enum' ? 'Enum' : 'Model';\n if (expectsBlockPrefix && !input.token.startsWith('@@')) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `${targetLabel} attribute \"${input.token}\" must use @@ prefix`,\n span: input.span,\n });\n return undefined;\n }\n if (!expectsBlockPrefix && !input.token.startsWith('@')) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Attribute \"${input.token}\" must use @ prefix`,\n span: input.span,\n });\n return undefined;\n }\n if (!expectsBlockPrefix && input.token.startsWith('@@')) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Attribute \"${input.token}\" is not valid in ${input.target} context`,\n span: input.span,\n });\n return undefined;\n }\n\n const rawBody = expectsBlockPrefix ? input.token.slice(2) : input.token.slice(1);\n const openParen = rawBody.indexOf('(');\n const closeParen = rawBody.lastIndexOf(')');\n const hasArgs = openParen >= 0 || closeParen >= 0;\n if ((openParen >= 0 && closeParen === -1) || (openParen === -1 && closeParen >= 0)) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Invalid attribute syntax \"${input.token}\"`,\n span: input.span,\n });\n return undefined;\n }\n\n const name = (openParen >= 0 ? rawBody.slice(0, openParen) : rawBody).trim();\n if (!/^[A-Za-z_][A-Za-z0-9_-]*(\\.[A-Za-z_][A-Za-z0-9_-]*)*$/.test(name)) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Invalid attribute name \"${name || input.token}\"`,\n span: input.span,\n });\n return undefined;\n }\n\n let args: readonly PslAttributeArgument[] = [];\n if (hasArgs && openParen >= 0 && closeParen >= openParen) {\n if (closeParen !== rawBody.length - 1) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Invalid trailing syntax in attribute \"${input.token}\"`,\n span: input.span,\n });\n return undefined;\n }\n const argsRaw = rawBody.slice(openParen + 1, closeParen);\n const parsedArgs = parseArgumentList(context, {\n argsRaw,\n argsOffset: input.span.start.column - 1 + (expectsBlockPrefix ? 2 : 1) + openParen + 1,\n lineIndex: input.lineIndex,\n token: input.token,\n span: input.span,\n invalidCode: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n invalidEmptyArgumentMessage: `Invalid empty argument in attribute \"${input.token}\"`,\n invalidNamedArgumentMessage: (part) => `Invalid named argument syntax \"${part}\"`,\n });\n if (!parsedArgs) {\n return undefined;\n }\n args = parsedArgs;\n }\n\n return {\n kind: 'attribute',\n target: input.target,\n name,\n args,\n span: input.span,\n };\n}\n\nfunction parseArgumentList(\n context: ParserContext,\n input: {\n readonly argsRaw: string;\n readonly argsOffset: number;\n readonly lineIndex: number;\n readonly token: string;\n readonly span: PslSpan;\n readonly invalidCode: PslDiagnosticCode;\n readonly invalidEmptyArgumentMessage: string;\n readonly invalidNamedArgumentMessage: (part: string) => string;\n },\n): readonly PslAttributeArgument[] | undefined {\n const trimmed = input.argsRaw.trim();\n if (trimmed.length === 0) {\n return [];\n }\n\n const parts = splitTopLevelSegments(input.argsRaw, ',');\n const args: PslAttributeArgument[] = [];\n\n for (const part of parts) {\n const original = part.value;\n const trimmedPart = original.trim();\n if (trimmedPart.length === 0) {\n pushDiagnostic(context, {\n code: input.invalidCode,\n message: input.invalidEmptyArgumentMessage,\n span: input.span,\n });\n return undefined;\n }\n\n const leadingWhitespace = original.length - original.trimStart().length;\n const partStart = input.argsOffset + part.start + leadingWhitespace;\n const partEnd = partStart + trimmedPart.length;\n const partSpan = createInlineSpan(context, input.lineIndex, partStart, partEnd);\n\n const namedSplit = splitTopLevelSegments(trimmedPart, ':');\n if (namedSplit.length > 1) {\n const first = namedSplit[0];\n if (!first) {\n pushDiagnostic(context, {\n code: input.invalidCode,\n message: input.invalidNamedArgumentMessage(trimmedPart),\n span: partSpan,\n });\n return undefined;\n }\n const name = first.value.trim();\n const rawValue = trimmedPart.slice(first.end + 1).trim();\n if (!name || rawValue.length === 0) {\n pushDiagnostic(context, {\n code: input.invalidCode,\n message: input.invalidNamedArgumentMessage(trimmedPart),\n span: partSpan,\n });\n return undefined;\n }\n args.push({\n kind: 'named',\n name,\n value: normalizeAttributeArgumentValue(rawValue),\n span: partSpan,\n });\n continue;\n }\n\n args.push({\n kind: 'positional',\n value: normalizeAttributeArgumentValue(trimmedPart),\n span: partSpan,\n });\n }\n\n return args;\n}\n\nfunction normalizeAttributeArgumentValue(value: string): string {\n return value.trim();\n}\n\nfunction findBlockBounds(context: ParserContext, startLine: number): BlockBounds {\n let depth = 0;\n\n for (let lineIndex = startLine; lineIndex < context.lines.length; lineIndex += 1) {\n const line = stripInlineComment(context.lines[lineIndex] ?? '');\n let quote: '\"' | \"'\" | null = null;\n for (let index = 0; index < line.length; index += 1) {\n const character = line[index] ?? '';\n if (quote) {\n if (character === quote && !isQuoteEscaped(line, index)) {\n quote = null;\n }\n continue;\n }\n\n if (character === '\"' || character === \"'\") {\n quote = character;\n continue;\n }\n\n if (character === '{') {\n depth += 1;\n }\n if (character === '}') {\n depth -= 1;\n if (depth === 0) {\n return { startLine, endLine: lineIndex, closed: true };\n }\n }\n }\n }\n\n pushDiagnostic(context, {\n code: 'PSL_UNTERMINATED_BLOCK',\n message: 'Unterminated block declaration',\n span: createTrimmedLineSpan(context, startLine),\n });\n return {\n startLine,\n endLine: context.lines.length - 1,\n closed: false,\n };\n}\n\ninterface TopLevelSegment {\n readonly value: string;\n readonly start: number;\n readonly end: number;\n}\n\nfunction splitTopLevelSegments(value: string, separator: ',' | ':'): TopLevelSegment[] {\n const parts: TopLevelSegment[] = [];\n let depthParen = 0;\n let depthBracket = 0;\n let depthBrace = 0;\n let quote: '\"' | \"'\" | null = null;\n let start = 0;\n\n for (let index = 0; index < value.length; index += 1) {\n const character = value[index] ?? '';\n if (quote) {\n if (character === quote && !isQuoteEscaped(value, index)) {\n quote = null;\n }\n continue;\n }\n\n if (character === '\"' || character === \"'\") {\n quote = character;\n continue;\n }\n\n if (character === '(') {\n depthParen += 1;\n continue;\n }\n if (character === ')') {\n depthParen = Math.max(0, depthParen - 1);\n continue;\n }\n if (character === '[') {\n depthBracket += 1;\n continue;\n }\n if (character === ']') {\n depthBracket = Math.max(0, depthBracket - 1);\n continue;\n }\n if (character === '{') {\n depthBrace += 1;\n continue;\n }\n if (character === '}') {\n depthBrace = Math.max(0, depthBrace - 1);\n continue;\n }\n\n if (character === separator && depthParen === 0 && depthBracket === 0 && depthBrace === 0) {\n parts.push({\n value: value.slice(start, index),\n start,\n end: index,\n });\n start = index + 1;\n }\n }\n\n parts.push({\n value: value.slice(start),\n start,\n end: value.length,\n });\n return parts;\n}\n\nfunction extractAttributeTokensWithSpans(\n context: ParserContext,\n lineIndex: number,\n value: string,\n startColumn: number,\n): { readonly ok: boolean; readonly tokens: readonly { text: string; span: PslSpan }[] } {\n const tokens: { text: string; span: PslSpan }[] = [];\n let index = 0;\n while (index < value.length) {\n while (index < value.length && /\\s/.test(value[index] ?? '')) {\n index += 1;\n }\n if (index >= value.length) {\n break;\n }\n\n if (value[index] !== '@') {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Invalid attribute syntax \"${value.trim()}\"`,\n span: createInlineSpan(context, lineIndex, startColumn + index, startColumn + value.length),\n });\n return { ok: false, tokens };\n }\n\n const start = index;\n index += 1;\n if (value[index] === '@') {\n index += 1;\n }\n\n const nameStart = index;\n while (index < value.length && /[A-Za-z0-9_.-]/.test(value[index] ?? '')) {\n index += 1;\n }\n\n if (index === nameStart) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Invalid attribute syntax \"${value.slice(start).trim()}\"`,\n span: createInlineSpan(context, lineIndex, startColumn + start, startColumn + value.length),\n });\n return { ok: false, tokens };\n }\n\n if (value[index] === '(') {\n let depth = 0;\n let quote: '\"' | \"'\" | null = null;\n while (index < value.length) {\n const char = value[index] ?? '';\n if (quote) {\n if (char === quote && !isQuoteEscaped(value, index)) {\n quote = null;\n }\n index += 1;\n continue;\n }\n\n if (char === '\"' || char === \"'\") {\n quote = char;\n index += 1;\n continue;\n }\n\n if (char === '(') {\n depth += 1;\n } else if (char === ')') {\n depth -= 1;\n if (depth === 0) {\n index += 1;\n break;\n }\n }\n index += 1;\n }\n if (depth !== 0) {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Unterminated attribute argument list in \"${value.slice(start).trim()}\"`,\n span: createInlineSpan(\n context,\n lineIndex,\n startColumn + start,\n startColumn + value.length,\n ),\n });\n return { ok: false, tokens };\n }\n }\n\n const tokenText = value.slice(start, index).trim();\n tokens.push({\n text: tokenText,\n span: createInlineSpan(context, lineIndex, startColumn + start, startColumn + index),\n });\n\n while (index < value.length && /\\s/.test(value[index] ?? '')) {\n index += 1;\n }\n\n if (index < value.length && value[index] !== '@') {\n break;\n }\n }\n\n if (index < value.length && value[index] !== '@') {\n pushDiagnostic(context, {\n code: 'PSL_INVALID_ATTRIBUTE_SYNTAX',\n message: `Invalid attribute syntax \"${value.trim()}\"`,\n span: createInlineSpan(context, lineIndex, startColumn + index, startColumn + value.length),\n });\n return { ok: false, tokens };\n }\n\n return { ok: true, tokens };\n}\n\nfunction stripInlineComment(line: string): string {\n let quote: '\"' | \"'\" | null = null;\n for (let index = 0; index < line.length - 1; index += 1) {\n const current = line[index] ?? '';\n const next = line[index + 1] ?? '';\n\n if (quote) {\n if (current === quote && !isQuoteEscaped(line, index)) {\n quote = null;\n }\n continue;\n }\n\n if (current === '\"' || current === \"'\") {\n quote = current;\n continue;\n }\n\n if (current === '/' && next === '/') {\n return line.slice(0, index);\n }\n }\n\n return line;\n}\n\nfunction computeLineOffsets(schema: string): number[] {\n const offsets = [0];\n for (let index = 0; index < schema.length; index += 1) {\n if (schema[index] === '\\n') {\n offsets.push(index + 1);\n }\n }\n return offsets;\n}\n\nfunction firstNonWhitespaceColumn(line: string): number {\n const first = line.search(/\\S/);\n return first === -1 ? 0 : first;\n}\n\nfunction createInlineSpan(\n context: ParserContext,\n lineIndex: number,\n startColumn: number,\n endColumn: number,\n): PslSpan {\n return {\n start: createPosition(context, lineIndex, startColumn),\n end: createPosition(context, lineIndex, endColumn),\n };\n}\n\nfunction createTrimmedLineSpan(context: ParserContext, lineIndex: number): PslSpan {\n const line = context.lines[lineIndex] ?? '';\n const startColumn = firstNonWhitespaceColumn(line);\n return {\n start: createPosition(context, lineIndex, startColumn),\n end: createPosition(context, lineIndex, line.length),\n };\n}\n\nfunction createLineRangeSpan(context: ParserContext, startLine: number, endLine: number): PslSpan {\n const startLineText = context.lines[startLine] ?? '';\n const endLineText = context.lines[endLine] ?? '';\n const startColumn = firstNonWhitespaceColumn(startLineText);\n return {\n start: createPosition(context, startLine, startColumn),\n end: createPosition(context, endLine, endLineText.length),\n };\n}\n\nfunction createPosition(\n context: ParserContext,\n lineIndex: number,\n columnIndex: number,\n): PslPosition {\n const clampedLineIndex = Math.max(0, Math.min(lineIndex, context.lineOffsets.length - 1));\n const lineText = context.lines[clampedLineIndex] ?? '';\n const clampedColumnIndex = Math.max(0, Math.min(columnIndex, lineText.length));\n return {\n offset: (context.lineOffsets[clampedLineIndex] ?? 0) + clampedColumnIndex,\n line: clampedLineIndex + 1,\n column: clampedColumnIndex + 1,\n };\n}\n\nfunction pushDiagnostic(\n context: ParserContext,\n diagnostic: Omit<PslDiagnostic, 'sourceId'> & { readonly code: PslDiagnosticCode },\n): void {\n context.diagnostics.push({\n ...diagnostic,\n sourceId: context.sourceId,\n });\n}\n"],"mappings":"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"}