@prisma-next/psl-parser 0.14.0 → 0.15.0-dev.10
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/README.md +28 -10
- package/dist/declarations-DR6To8_k.mjs +1060 -0
- package/dist/declarations-DR6To8_k.mjs.map +1 -0
- package/dist/format.d.mts +19 -0
- package/dist/format.d.mts.map +1 -0
- package/dist/format.mjs +470 -0
- package/dist/format.mjs.map +1 -0
- package/dist/index.d.mts +144 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +849 -3
- package/dist/index.mjs.map +1 -1
- package/dist/interpret.d.mts +39 -0
- package/dist/interpret.d.mts.map +1 -0
- package/dist/interpret.mjs +25 -0
- package/dist/interpret.mjs.map +1 -0
- package/dist/parse-BazJr7Ye.d.mts +426 -0
- package/dist/parse-BazJr7Ye.d.mts.map +1 -0
- package/dist/parse-CdeXr0T3.mjs +626 -0
- package/dist/parse-CdeXr0T3.mjs.map +1 -0
- package/dist/symbol-table-C-AH04Ug.d.mts +127 -0
- package/dist/symbol-table-C-AH04Ug.d.mts.map +1 -0
- package/dist/syntax.d.mts +21 -347
- package/dist/syntax.d.mts.map +1 -1
- package/dist/syntax.mjs +26 -1401
- package/dist/syntax.mjs.map +1 -1
- package/package.json +11 -8
- package/src/attribute-spec/combinators/bool.ts +19 -0
- package/src/attribute-spec/combinators/diagnostic.ts +15 -0
- package/src/attribute-spec/combinators/entity-ref.ts +24 -0
- package/src/attribute-spec/combinators/field-ref.ts +36 -0
- package/src/attribute-spec/combinators/func-call.ts +65 -0
- package/src/attribute-spec/combinators/identifier.ts +16 -0
- package/src/attribute-spec/combinators/int.ts +35 -0
- package/src/attribute-spec/combinators/list.ts +43 -0
- package/src/attribute-spec/combinators/num.ts +26 -0
- package/src/attribute-spec/combinators/one-of.ts +29 -0
- package/src/attribute-spec/combinators/record.ts +43 -0
- package/src/attribute-spec/combinators/str.ts +19 -0
- package/src/attribute-spec/field-attribute.ts +27 -0
- package/src/attribute-spec/interpret.ts +177 -0
- package/src/attribute-spec/model-attribute.ts +27 -0
- package/src/attribute-spec/optional.ts +8 -0
- package/src/attribute-spec/types.ts +72 -0
- package/src/block-reconstruction.ts +140 -0
- package/src/exports/format.ts +3 -0
- package/src/exports/index.ts +61 -3
- package/src/exports/interpret.ts +2 -0
- package/src/exports/syntax.ts +25 -5
- package/src/extension-block.ts +107 -0
- package/src/format/emit.ts +603 -0
- package/src/format/error.ts +13 -0
- package/src/format/format.ts +13 -0
- package/src/format/options.ts +28 -0
- package/src/interpret.ts +67 -0
- package/src/parse.ts +32 -5
- package/src/resolve.ts +123 -0
- package/src/source-file.ts +25 -0
- package/src/symbol-table.ts +446 -0
- package/src/syntax/ast/attributes.ts +5 -6
- package/src/syntax/ast/declarations.ts +51 -26
- package/src/syntax/ast/expressions.ts +12 -13
- package/src/syntax/ast/identifier.ts +2 -3
- package/src/syntax/ast/qualified-name.ts +28 -19
- package/src/syntax/ast/type-annotation.ts +4 -5
- package/src/syntax/ast-helpers.ts +27 -3
- package/src/syntax/navigation.ts +55 -0
- package/src/syntax/red.ts +317 -42
- package/dist/parser-CaplKvRs.mjs +0 -1145
- package/dist/parser-CaplKvRs.mjs.map +0 -1
- package/dist/parser-Dfi3Wfdq.d.mts +0 -7
- package/dist/parser-Dfi3Wfdq.d.mts.map +0 -1
- package/dist/parser.d.mts +0 -2
- package/dist/parser.mjs +0 -2
- package/src/exports/parser.ts +0 -1
- package/src/parser.ts +0 -1642
package/dist/syntax.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syntax.mjs","names":["#text","#lineStarts","#lineIndexAt","#lineStartAt","#lineEndAt","#penultimateSegment","#lastSegment","#separatorCount","#stack","#tokenizer","#sourceFile","#builder","#diagnostics","#offset","#depth","#advance"],"sources":["../src/source-file.ts","../src/syntax/red.ts","../src/syntax/ast-helpers.ts","../src/syntax/ast/identifier.ts","../src/syntax/ast/qualified-name.ts","../src/syntax/ast/expressions.ts","../src/syntax/ast/attributes.ts","../src/syntax/ast/type-annotation.ts","../src/syntax/ast/declarations.ts","../src/syntax/green.ts","../src/syntax/green-builder.ts","../src/parse.ts"],"sourcesContent":["const LINE_FEED = 10;\n\nexport interface Position {\n readonly line: number;\n readonly character: number;\n}\n\nexport interface Range {\n readonly start: Position;\n readonly end: Position;\n}\n\nexport class SourceFile {\n readonly #text: string;\n readonly #lineStarts: readonly number[];\n\n constructor(text: string) {\n this.#text = text;\n const lineStarts: number[] = [0];\n for (let offset = 0; offset < text.length; offset++) {\n if (text.charCodeAt(offset) === LINE_FEED) {\n lineStarts.push(offset + 1);\n }\n }\n this.#lineStarts = lineStarts;\n }\n\n get text(): string {\n return this.#text;\n }\n\n get length(): number {\n return this.#text.length;\n }\n\n get lineCount(): number {\n return this.#lineStarts.length;\n }\n\n lineStartOffsets(): readonly number[] {\n return this.#lineStarts;\n }\n\n positionAt(offset: number): Position {\n const clamped = clamp(offset, 0, this.#text.length);\n const line = this.#lineIndexAt(clamped);\n return { line, character: clamped - this.#lineStartAt(line) };\n }\n\n offsetAt(position: Position): number {\n const line = clamp(position.line, 0, this.#lineStarts.length - 1);\n const lineStart = this.#lineStartAt(line);\n const lineEnd = this.#lineEndAt(line);\n return clamp(lineStart + position.character, lineStart, lineEnd);\n }\n\n #lineStartAt(line: number): number {\n return this.#lineStarts[line] ?? 0;\n }\n\n #lineEndAt(line: number): number {\n return line + 1 < this.#lineStarts.length ? this.#lineStartAt(line + 1) - 1 : this.#text.length;\n }\n\n #lineIndexAt(offset: number): number {\n const lineStarts = this.#lineStarts;\n let low = 0;\n let high = lineStarts.length - 1;\n while (low < high) {\n const mid = (low + high + 1) >>> 1;\n if ((lineStarts[mid] ?? 0) <= offset) {\n low = mid;\n } else {\n high = mid - 1;\n }\n }\n return low;\n }\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n if (value < min) {\n return min;\n }\n if (value > max) {\n return max;\n }\n return value;\n}\n","import type { Token } from '../tokenizer';\nimport type { GreenElement, GreenNode } from './green';\nimport type { SyntaxKind } from './syntax-kind';\n\n/**\n * A token in the red tree. Unlike the green-layer {@link Token} (kind + text\n * only), a red token also carries its absolute `offset` within the source,\n * computed lazily as the tree is walked.\n */\nexport interface SyntaxToken extends Token {\n readonly offset: number;\n}\n\nexport type SyntaxElement = SyntaxNode | SyntaxToken;\n\nexport class SyntaxNode {\n readonly green: GreenNode;\n readonly offset: number;\n readonly parent: SyntaxNode | undefined;\n\n constructor(green: GreenNode, offset: number, parent: SyntaxNode | undefined) {\n this.green = green;\n this.offset = offset;\n this.parent = parent;\n }\n\n get kind(): SyntaxKind {\n return this.green.kind;\n }\n\n get textLength(): number {\n return this.green.textLength;\n }\n\n get firstChild(): SyntaxElement | undefined {\n return childAt(this, 0);\n }\n\n get lastChild(): SyntaxElement | undefined {\n const len = this.green.children.length;\n if (len === 0) return undefined;\n return childAt(this, len - 1);\n }\n\n get nextSibling(): SyntaxElement | undefined {\n if (!this.parent) return undefined;\n const siblings = this.parent.green.children;\n let offset = this.parent.offset;\n let found = false;\n for (const child of siblings) {\n if (found) {\n return wrapElement(child, offset, this.parent);\n }\n const childLen = elementTextLength(child);\n if (child.type === 'node' && offset === this.offset && child === this.green) {\n found = true;\n }\n offset += childLen;\n }\n return undefined;\n }\n\n get prevSibling(): SyntaxElement | undefined {\n if (!this.parent) return undefined;\n const siblings = this.parent.green.children;\n let offset = this.parent.offset;\n let prev: { green: GreenElement; offset: number } | undefined;\n for (const child of siblings) {\n if (child.type === 'node' && offset === this.offset && child === this.green) {\n if (!prev) return undefined;\n return wrapElement(prev.green, prev.offset, this.parent);\n }\n prev = { green: child, offset };\n offset += elementTextLength(child);\n }\n return undefined;\n }\n\n *children(): Iterable<SyntaxElement> {\n let offset = this.offset;\n for (const child of this.green.children) {\n yield wrapElement(child, offset, this);\n offset += elementTextLength(child);\n }\n }\n\n *childNodes(): Iterable<SyntaxNode> {\n for (const child of this.children()) {\n if (child instanceof SyntaxNode) yield child;\n }\n }\n\n *ancestors(): Iterable<SyntaxNode> {\n let current: SyntaxNode | undefined = this.parent;\n while (current) {\n yield current;\n current = current.parent;\n }\n }\n\n *descendants(): Iterable<SyntaxElement> {\n const stack: SyntaxElement[] = [this];\n for (let el = stack.pop(); el !== undefined; el = stack.pop()) {\n yield el;\n if (el instanceof SyntaxNode) {\n const children = Array.from(el.children());\n for (let i = children.length - 1; i >= 0; i--) {\n const child = children[i];\n if (child !== undefined) {\n stack.push(child);\n }\n }\n }\n }\n }\n\n *tokens(): Iterable<SyntaxToken> {\n for (const el of this.descendants()) {\n if (!(el instanceof SyntaxNode)) {\n yield el;\n }\n }\n }\n}\n\nfunction elementTextLength(el: GreenElement): number {\n return el.type === 'token' ? el.text.length : el.textLength;\n}\n\nfunction wrapElement(green: GreenElement, offset: number, parent: SyntaxNode): SyntaxElement {\n if (green.type === 'token') {\n const token: SyntaxToken = { kind: green.kind, text: green.text, offset };\n return token;\n }\n return new SyntaxNode(green, offset, parent);\n}\n\nfunction childAt(node: SyntaxNode, index: number): SyntaxElement | undefined {\n const children = node.green.children;\n const target = children[index];\n if (target === undefined) return undefined;\n let offset = node.offset;\n for (let i = 0; i < index; i++) {\n const child = children[i];\n if (child !== undefined) {\n offset += elementTextLength(child);\n }\n }\n return wrapElement(target, offset, node);\n}\n\nexport function createSyntaxTree(green: GreenNode): SyntaxNode {\n return new SyntaxNode(green, 0, undefined);\n}\n","import type { Token, TokenKind } from '../tokenizer';\nimport { SyntaxNode } from './red';\n\nexport interface AstNode {\n readonly syntax: SyntaxNode;\n}\n\nexport function findChildToken(node: SyntaxNode, kind: TokenKind): Token | undefined {\n for (const child of node.children()) {\n if (!(child instanceof SyntaxNode) && child.kind === kind) {\n return child;\n }\n }\n return undefined;\n}\n\nexport function findFirstChild<T>(\n node: SyntaxNode,\n cast: (node: SyntaxNode) => T | undefined,\n): T | undefined {\n for (const child of node.childNodes()) {\n const result = cast(child);\n if (result !== undefined) return result;\n }\n return undefined;\n}\n\nexport function* filterChildren<T>(\n node: SyntaxNode,\n cast: (node: SyntaxNode) => T | undefined,\n): Iterable<T> {\n for (const child of node.childNodes()) {\n const result = cast(child);\n if (result !== undefined) yield result;\n }\n}\n\n/**\n * Raw source text of a CST node, verbatim (quotes and brackets preserved). For\n * the decoded value of a string literal, decode it instead.\n */\nexport function printSyntax(node: SyntaxNode): string {\n let text = '';\n for (const token of node.tokens()) {\n text += token.text;\n }\n return text;\n}\n","import type { Token } from '../../tokenizer';\nimport type { AstNode } from '../ast-helpers';\nimport { findChildToken } from '../ast-helpers';\nimport type { SyntaxNode } from '../red';\n\nexport class IdentifierAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n token(): Token | undefined {\n return findChildToken(this.syntax, 'Ident');\n }\n\n name(): string | undefined {\n return this.token()?.text;\n }\n\n static cast(node: SyntaxNode): IdentifierAst | undefined {\n return node.kind === 'Identifier' ? new IdentifierAst(node) : undefined;\n }\n}\n","import type { Token } from '../../tokenizer';\nimport type { AstNode } from '../ast-helpers';\nimport { filterChildren, findChildToken, findFirstChild } from '../ast-helpers';\nimport { SyntaxNode } from '../red';\nimport { IdentifierAst } from './identifier';\n\n/** A namespace-qualified name, e.g. `pgvector.Vector` or `supabase:auth.User`. */\nexport class QualifiedNameAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n #lastSegment(): IdentifierAst | undefined {\n let last: IdentifierAst | undefined;\n for (const segment of filterChildren(this.syntax, IdentifierAst.cast)) {\n last = segment;\n }\n return last;\n }\n\n #penultimateSegment(): IdentifierAst | undefined {\n let last: IdentifierAst | undefined;\n let penultimate: IdentifierAst | undefined;\n for (const segment of filterChildren(this.syntax, IdentifierAst.cast)) {\n penultimate = last;\n last = segment;\n }\n return penultimate;\n }\n\n #separatorCount(kind: 'Dot' | 'Colon'): number {\n let count = 0;\n for (const child of this.syntax.children()) {\n if (!(child instanceof SyntaxNode) && child.kind === kind) count++;\n }\n return count;\n }\n\n colon(): Token | undefined {\n return findChildToken(this.syntax, 'Colon');\n }\n\n dot(): Token | undefined {\n return findChildToken(this.syntax, 'Dot');\n }\n\n space(): IdentifierAst | undefined {\n if (!this.colon()) return undefined;\n return findFirstChild(this.syntax, IdentifierAst.cast);\n }\n\n namespace(): IdentifierAst | undefined {\n if (!this.dot()) return undefined;\n return this.#penultimateSegment();\n }\n\n identifier(): IdentifierAst | undefined {\n return this.#lastSegment();\n }\n\n /**\n * Every identifier segment, in source order. A bare `Vector` yields\n * `['Vector']`; a qualified `pgvector.Vector` yields `['pgvector', 'Vector']`.\n */\n path(): readonly string[] {\n const segments: string[] = [];\n for (const segment of filterChildren(this.syntax, IdentifierAst.cast)) {\n const text = segment.token()?.text;\n if (text !== undefined) segments.push(text);\n }\n return segments;\n }\n\n /**\n * Flags a malformed name with more qualifier segments than allowed (a second\n * `:`-space or a second `.`-namespace).\n */\n isOverQualified(): boolean {\n return this.#separatorCount('Dot') > 1 || this.#separatorCount('Colon') > 1;\n }\n\n static cast(node: SyntaxNode): QualifiedNameAst | undefined {\n return node.kind === 'QualifiedName' ? new QualifiedNameAst(node) : undefined;\n }\n}\n","import type { Token } from '../../tokenizer';\nimport type { AstNode } from '../ast-helpers';\nimport { filterChildren, findChildToken, findFirstChild } from '../ast-helpers';\nimport { SyntaxNode } from '../red';\nimport { IdentifierAst } from './identifier';\nimport { QualifiedNameAst } from './qualified-name';\n\nexport class FunctionCallAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n /** The qualified-name callee, or `undefined` when identifier segments sit directly under the node. */\n name(): QualifiedNameAst | undefined {\n return findFirstChild(this.syntax, QualifiedNameAst.cast);\n }\n\n /**\n * The dotted call path, in source order. A bare `Vector(…)` yields\n * `['Vector']`; a namespace-qualified `pgvector.Vector(…)` yields\n * `['pgvector', 'Vector']`. Empty when the call carries no identifier.\n */\n path(): readonly string[] {\n const qualified = this.name();\n const segments: string[] = [];\n for (const segment of filterChildren(qualified?.syntax ?? this.syntax, IdentifierAst.cast)) {\n const text = segment.token()?.text;\n if (text !== undefined) segments.push(text);\n }\n return segments;\n }\n\n lparen(): Token | undefined {\n return findChildToken(this.syntax, 'LParen');\n }\n\n rparen(): Token | undefined {\n return findChildToken(this.syntax, 'RParen');\n }\n\n *args(): Iterable<AttributeArgAst> {\n yield* filterChildren(this.syntax, AttributeArgAst.cast);\n }\n\n static cast(node: SyntaxNode): FunctionCallAst | undefined {\n return node.kind === 'FunctionCall' ? new FunctionCallAst(node) : undefined;\n }\n}\n\nexport class ArrayLiteralAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n lbracket(): Token | undefined {\n return findChildToken(this.syntax, 'LBracket');\n }\n\n rbracket(): Token | undefined {\n return findChildToken(this.syntax, 'RBracket');\n }\n\n *elements(): Iterable<ExpressionAst> {\n yield* filterChildren(this.syntax, castExpression);\n }\n\n static cast(node: SyntaxNode): ArrayLiteralAst | undefined {\n return node.kind === 'ArrayLiteral' ? new ArrayLiteralAst(node) : undefined;\n }\n}\n\nconst HEX = /^[0-9a-fA-F]+$/;\n\nfunction decodeFixedHex(raw: string, start: number, width: number): string | undefined {\n if (start + width > raw.length) return undefined;\n const hex = raw.slice(start, start + width);\n if (!HEX.test(hex)) return undefined;\n return String.fromCharCode(Number.parseInt(hex, 16));\n}\n\nfunction decodeStringLiteral(raw: string): string {\n let out = '';\n let i = 0;\n while (i < raw.length) {\n const ch = raw.charAt(i);\n if (ch !== '\\\\' || i + 1 >= raw.length) {\n out += ch;\n i++;\n continue;\n }\n const next = raw.charAt(i + 1);\n switch (next) {\n case 'n':\n out += '\\n';\n i += 2;\n continue;\n case 'r':\n out += '\\r';\n i += 2;\n continue;\n case 't':\n out += '\\t';\n i += 2;\n continue;\n case '\"':\n out += '\"';\n i += 2;\n continue;\n case \"'\":\n out += \"'\";\n i += 2;\n continue;\n case '\\\\':\n out += '\\\\';\n i += 2;\n continue;\n case 'x': {\n const decoded = decodeFixedHex(raw, i + 2, 2);\n if (decoded === undefined) {\n out += '\\\\x';\n i += 2;\n continue;\n }\n out += decoded;\n i += 4;\n continue;\n }\n case 'u': {\n const decoded = decodeFixedHex(raw, i + 2, 4);\n if (decoded === undefined) {\n out += '\\\\u';\n i += 2;\n continue;\n }\n out += decoded;\n i += 6;\n continue;\n }\n default:\n out += `\\\\${next}`;\n i += 2;\n continue;\n }\n }\n return out;\n}\n\nexport class StringLiteralExprAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n token(): Token | undefined {\n return findChildToken(this.syntax, 'StringLiteral');\n }\n\n value(): string | undefined {\n const tok = this.token();\n if (!tok) return undefined;\n return decodeStringLiteral(tok.text.slice(1, -1));\n }\n\n static cast(node: SyntaxNode): StringLiteralExprAst | undefined {\n return node.kind === 'StringLiteralExpr' ? new StringLiteralExprAst(node) : undefined;\n }\n}\n\nexport class NumberLiteralExprAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n token(): Token | undefined {\n return findChildToken(this.syntax, 'NumberLiteral');\n }\n\n value(): number | undefined {\n const tok = this.token();\n if (!tok) return undefined;\n return Number(tok.text);\n }\n\n static cast(node: SyntaxNode): NumberLiteralExprAst | undefined {\n return node.kind === 'NumberLiteralExpr' ? new NumberLiteralExprAst(node) : undefined;\n }\n}\n\nexport class BooleanLiteralExprAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n token(): Token | undefined {\n return findChildToken(this.syntax, 'Ident');\n }\n\n value(): boolean | undefined {\n const tok = this.token();\n if (!tok) return undefined;\n if (tok.text === 'true') return true;\n if (tok.text === 'false') return false;\n return undefined;\n }\n\n static cast(node: SyntaxNode): BooleanLiteralExprAst | undefined {\n return node.kind === 'BooleanLiteralExpr' ? new BooleanLiteralExprAst(node) : undefined;\n }\n}\n\nexport class ObjectLiteralExprAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n lbrace(): Token | undefined {\n return findChildToken(this.syntax, 'LBrace');\n }\n\n rbrace(): Token | undefined {\n return findChildToken(this.syntax, 'RBrace');\n }\n\n *fields(): Iterable<ObjectFieldAst> {\n yield* filterChildren(this.syntax, ObjectFieldAst.cast);\n }\n\n static cast(node: SyntaxNode): ObjectLiteralExprAst | undefined {\n return node.kind === 'ObjectLiteralExpr' ? new ObjectLiteralExprAst(node) : undefined;\n }\n}\n\nexport class ObjectFieldAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n key(): IdentifierAst | undefined {\n for (const child of this.syntax.children()) {\n if (!(child instanceof SyntaxNode)) {\n if (child.kind === 'Colon') break;\n continue;\n }\n return IdentifierAst.cast(child);\n }\n return undefined;\n }\n\n /**\n * The field's logical key name, unquoted. An identifier key (`length:`) yields\n * its text; a string-literal key (`\"length\":`) yields the decoded string.\n * `undefined` when the field carries no key node.\n */\n keyName(): string | undefined {\n for (const child of this.syntax.children()) {\n if (!(child instanceof SyntaxNode)) {\n if (child.kind === 'Colon') break;\n continue;\n }\n const identifier = IdentifierAst.cast(child);\n if (identifier) return identifier.token()?.text;\n const stringKey = StringLiteralExprAst.cast(child);\n if (stringKey) return stringKey.value();\n return undefined;\n }\n return undefined;\n }\n\n colon(): Token | undefined {\n return findChildToken(this.syntax, 'Colon');\n }\n\n value(): ExpressionAst | undefined {\n if (this.colon()) {\n let pastColon = false;\n for (const child of this.syntax.children()) {\n if (!(child instanceof SyntaxNode)) {\n if (child.kind === 'Colon') pastColon = true;\n continue;\n }\n if (pastColon) {\n const expr = castExpression(child);\n if (expr) return expr;\n }\n }\n return undefined;\n }\n return findFirstChild(this.syntax, castExpression);\n }\n\n static cast(node: SyntaxNode): ObjectFieldAst | undefined {\n return node.kind === 'ObjectField' ? new ObjectFieldAst(node) : undefined;\n }\n}\n\nexport type ExpressionAst =\n | FunctionCallAst\n | ArrayLiteralAst\n | StringLiteralExprAst\n | NumberLiteralExprAst\n | BooleanLiteralExprAst\n | ObjectLiteralExprAst\n | IdentifierAst;\n\nexport function castExpression(node: SyntaxNode): ExpressionAst | undefined {\n return (\n FunctionCallAst.cast(node) ??\n ArrayLiteralAst.cast(node) ??\n StringLiteralExprAst.cast(node) ??\n NumberLiteralExprAst.cast(node) ??\n BooleanLiteralExprAst.cast(node) ??\n ObjectLiteralExprAst.cast(node) ??\n IdentifierAst.cast(node)\n );\n}\n\nexport class AttributeArgAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n name(): IdentifierAst | undefined {\n if (!this.colon()) return undefined;\n return findFirstChild(this.syntax, IdentifierAst.cast);\n }\n\n colon(): Token | undefined {\n return findChildToken(this.syntax, 'Colon');\n }\n\n value(): ExpressionAst | undefined {\n if (this.colon()) {\n let pastColon = false;\n for (const child of this.syntax.children()) {\n if (!(child instanceof SyntaxNode)) {\n if (child.kind === 'Colon') pastColon = true;\n continue;\n }\n if (pastColon) {\n const expr = castExpression(child);\n if (expr) return expr;\n }\n }\n return undefined;\n }\n return findFirstChild(this.syntax, castExpression);\n }\n\n static cast(node: SyntaxNode): AttributeArgAst | undefined {\n return node.kind === 'AttributeArg' ? new AttributeArgAst(node) : undefined;\n }\n}\n","import type { Token } from '../../tokenizer';\nimport type { AstNode } from '../ast-helpers';\nimport { filterChildren, findChildToken, findFirstChild } from '../ast-helpers';\nimport type { SyntaxNode } from '../red';\nimport { AttributeArgAst } from './expressions';\nimport { QualifiedNameAst } from './qualified-name';\n\nexport class AttributeArgListAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n lparen(): Token | undefined {\n return findChildToken(this.syntax, 'LParen');\n }\n\n rparen(): Token | undefined {\n return findChildToken(this.syntax, 'RParen');\n }\n\n *args(): Iterable<AttributeArgAst> {\n yield* filterChildren(this.syntax, AttributeArgAst.cast);\n }\n\n static cast(node: SyntaxNode): AttributeArgListAst | undefined {\n return node.kind === 'AttributeArgList' ? new AttributeArgListAst(node) : undefined;\n }\n}\n\nexport class FieldAttributeAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n at(): Token | undefined {\n return findChildToken(this.syntax, 'At');\n }\n\n name(): QualifiedNameAst | undefined {\n return findFirstChild(this.syntax, QualifiedNameAst.cast);\n }\n\n argList(): AttributeArgListAst | undefined {\n return findFirstChild(this.syntax, AttributeArgListAst.cast);\n }\n\n static cast(node: SyntaxNode): FieldAttributeAst | undefined {\n return node.kind === 'FieldAttribute' ? new FieldAttributeAst(node) : undefined;\n }\n}\n\nexport class ModelAttributeAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n doubleAt(): Token | undefined {\n return findChildToken(this.syntax, 'DoubleAt');\n }\n\n name(): QualifiedNameAst | undefined {\n return findFirstChild(this.syntax, QualifiedNameAst.cast);\n }\n\n argList(): AttributeArgListAst | undefined {\n return findFirstChild(this.syntax, AttributeArgListAst.cast);\n }\n\n static cast(node: SyntaxNode): ModelAttributeAst | undefined {\n return node.kind === 'ModelAttribute' ? new ModelAttributeAst(node) : undefined;\n }\n}\n","import type { Token } from '../../tokenizer';\nimport type { AstNode } from '../ast-helpers';\nimport { findChildToken, findFirstChild } from '../ast-helpers';\nimport type { SyntaxNode } from '../red';\nimport { AttributeArgListAst } from './attributes';\nimport { QualifiedNameAst } from './qualified-name';\n\nexport class TypeAnnotationAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n /** The annotation's reference, doubling as the constructor callee when an {@link argList} follows. */\n name(): QualifiedNameAst | undefined {\n return findFirstChild(this.syntax, QualifiedNameAst.cast);\n }\n\n /** Present when the annotation is a constructor (`Vector(1536)`) rather than a plain reference. */\n argList(): AttributeArgListAst | undefined {\n return findFirstChild(this.syntax, AttributeArgListAst.cast);\n }\n\n isConstructor(): boolean {\n return this.argList() !== undefined;\n }\n\n lbracket(): Token | undefined {\n return findChildToken(this.syntax, 'LBracket');\n }\n\n rbracket(): Token | undefined {\n return findChildToken(this.syntax, 'RBracket');\n }\n\n questionMark(): Token | undefined {\n return findChildToken(this.syntax, 'Question');\n }\n\n isList(): boolean {\n return this.lbracket() !== undefined;\n }\n\n isOptional(): boolean {\n return this.questionMark() !== undefined;\n }\n\n static cast(node: SyntaxNode): TypeAnnotationAst | undefined {\n return node.kind === 'TypeAnnotation' ? new TypeAnnotationAst(node) : undefined;\n }\n}\n","import type { Token } from '../../tokenizer';\nimport type { AstNode } from '../ast-helpers';\nimport { filterChildren, findChildToken, findFirstChild } from '../ast-helpers';\nimport { SyntaxNode } from '../red';\nimport { FieldAttributeAst, ModelAttributeAst } from './attributes';\nimport type { ExpressionAst } from './expressions';\nimport { castExpression } from './expressions';\nimport { IdentifierAst } from './identifier';\nimport { TypeAnnotationAst } from './type-annotation';\n\n/**\n * What may appear inside a `namespace` block: models, composite types, and\n * extension (block) declarations. `types {}` blocks and nested `namespace`\n * blocks are document-only, so they are not namespace members.\n */\nexport type NamespaceMemberAst =\n | ModelDeclarationAst\n | CompositeTypeDeclarationAst\n | GenericBlockDeclarationAst;\n\nfunction castNamespaceMember(node: SyntaxNode): NamespaceMemberAst | undefined {\n return (\n ModelDeclarationAst.cast(node) ??\n CompositeTypeDeclarationAst.cast(node) ??\n GenericBlockDeclarationAst.cast(node)\n );\n}\n\nexport class DocumentAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n *declarations(): Iterable<NamespaceMemberAst | TypesBlockAst | NamespaceDeclarationAst> {\n yield* filterChildren(\n this.syntax,\n (node) =>\n castNamespaceMember(node) ?? TypesBlockAst.cast(node) ?? NamespaceDeclarationAst.cast(node),\n );\n }\n\n static cast(node: SyntaxNode): DocumentAst | undefined {\n return node.kind === 'Document' ? new DocumentAst(node) : undefined;\n }\n}\n\nexport class ModelDeclarationAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n keyword(): Token | undefined {\n return findChildToken(this.syntax, 'Ident');\n }\n\n name(): IdentifierAst | undefined {\n return findFirstChild(this.syntax, IdentifierAst.cast);\n }\n\n lbrace(): Token | undefined {\n return findChildToken(this.syntax, 'LBrace');\n }\n\n rbrace(): Token | undefined {\n return findChildToken(this.syntax, 'RBrace');\n }\n\n *fields(): Iterable<FieldDeclarationAst> {\n yield* filterChildren(this.syntax, FieldDeclarationAst.cast);\n }\n\n *attributes(): Iterable<ModelAttributeAst> {\n yield* filterChildren(this.syntax, ModelAttributeAst.cast);\n }\n\n static cast(node: SyntaxNode): ModelDeclarationAst | undefined {\n return node.kind === 'ModelDeclaration' ? new ModelDeclarationAst(node) : undefined;\n }\n}\n\nexport class CompositeTypeDeclarationAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n keyword(): Token | undefined {\n return findChildToken(this.syntax, 'Ident');\n }\n\n name(): IdentifierAst | undefined {\n return findFirstChild(this.syntax, IdentifierAst.cast);\n }\n\n lbrace(): Token | undefined {\n return findChildToken(this.syntax, 'LBrace');\n }\n\n rbrace(): Token | undefined {\n return findChildToken(this.syntax, 'RBrace');\n }\n\n *fields(): Iterable<FieldDeclarationAst> {\n yield* filterChildren(this.syntax, FieldDeclarationAst.cast);\n }\n\n *attributes(): Iterable<ModelAttributeAst> {\n yield* filterChildren(this.syntax, ModelAttributeAst.cast);\n }\n\n static cast(node: SyntaxNode): CompositeTypeDeclarationAst | undefined {\n return node.kind === 'CompositeTypeDeclaration'\n ? new CompositeTypeDeclarationAst(node)\n : undefined;\n }\n}\n\nexport class NamespaceDeclarationAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n keyword(): Token | undefined {\n return findChildToken(this.syntax, 'Ident');\n }\n\n name(): IdentifierAst | undefined {\n return findFirstChild(this.syntax, IdentifierAst.cast);\n }\n\n lbrace(): Token | undefined {\n return findChildToken(this.syntax, 'LBrace');\n }\n\n rbrace(): Token | undefined {\n return findChildToken(this.syntax, 'RBrace');\n }\n\n *declarations(): Iterable<NamespaceMemberAst> {\n yield* filterChildren(this.syntax, castNamespaceMember);\n }\n\n static cast(node: SyntaxNode): NamespaceDeclarationAst | undefined {\n return node.kind === 'Namespace' ? new NamespaceDeclarationAst(node) : undefined;\n }\n}\n\nexport class TypesBlockAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n keyword(): Token | undefined {\n return findChildToken(this.syntax, 'Ident');\n }\n\n lbrace(): Token | undefined {\n return findChildToken(this.syntax, 'LBrace');\n }\n\n rbrace(): Token | undefined {\n return findChildToken(this.syntax, 'RBrace');\n }\n\n *declarations(): Iterable<NamedTypeDeclarationAst> {\n yield* filterChildren(this.syntax, NamedTypeDeclarationAst.cast);\n }\n\n static cast(node: SyntaxNode): TypesBlockAst | undefined {\n return node.kind === 'TypesBlock' ? new TypesBlockAst(node) : undefined;\n }\n}\n\nexport class GenericBlockDeclarationAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n keyword(): Token | undefined {\n return findChildToken(this.syntax, 'Ident');\n }\n\n name(): IdentifierAst | undefined {\n return findFirstChild(this.syntax, IdentifierAst.cast);\n }\n\n lbrace(): Token | undefined {\n return findChildToken(this.syntax, 'LBrace');\n }\n\n rbrace(): Token | undefined {\n return findChildToken(this.syntax, 'RBrace');\n }\n\n *entries(): Iterable<KeyValuePairAst> {\n yield* filterChildren(this.syntax, KeyValuePairAst.cast);\n }\n\n *attributes(): Iterable<ModelAttributeAst> {\n yield* filterChildren(this.syntax, ModelAttributeAst.cast);\n }\n\n static cast(node: SyntaxNode): GenericBlockDeclarationAst | undefined {\n return node.kind === 'GenericBlockDeclaration'\n ? new GenericBlockDeclarationAst(node)\n : undefined;\n }\n}\n\nexport class KeyValuePairAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n key(): IdentifierAst | undefined {\n return findFirstChild(this.syntax, IdentifierAst.cast);\n }\n\n equals(): Token | undefined {\n return findChildToken(this.syntax, 'Equals');\n }\n\n value(): ExpressionAst | undefined {\n let pastEquals = false;\n for (const child of this.syntax.children()) {\n if (!(child instanceof SyntaxNode)) {\n if (child.kind === 'Equals') pastEquals = true;\n continue;\n }\n if (pastEquals) {\n const expr = castExpression(child);\n if (expr) return expr;\n }\n }\n return undefined;\n }\n\n static cast(node: SyntaxNode): KeyValuePairAst | undefined {\n return node.kind === 'KeyValuePair' ? new KeyValuePairAst(node) : undefined;\n }\n}\n\nexport class FieldDeclarationAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n name(): IdentifierAst | undefined {\n return findFirstChild(this.syntax, IdentifierAst.cast);\n }\n\n typeAnnotation(): TypeAnnotationAst | undefined {\n return findFirstChild(this.syntax, TypeAnnotationAst.cast);\n }\n\n *attributes(): Iterable<FieldAttributeAst> {\n yield* filterChildren(this.syntax, FieldAttributeAst.cast);\n }\n\n static cast(node: SyntaxNode): FieldDeclarationAst | undefined {\n return node.kind === 'FieldDeclaration' ? new FieldDeclarationAst(node) : undefined;\n }\n}\n\nexport class NamedTypeDeclarationAst implements AstNode {\n readonly syntax: SyntaxNode;\n\n constructor(syntax: SyntaxNode) {\n this.syntax = syntax;\n }\n\n name(): IdentifierAst | undefined {\n return findFirstChild(this.syntax, IdentifierAst.cast);\n }\n\n equals(): Token | undefined {\n return findChildToken(this.syntax, 'Equals');\n }\n\n typeAnnotation(): TypeAnnotationAst | undefined {\n return findFirstChild(this.syntax, TypeAnnotationAst.cast);\n }\n\n *attributes(): Iterable<FieldAttributeAst> {\n yield* filterChildren(this.syntax, FieldAttributeAst.cast);\n }\n\n static cast(node: SyntaxNode): NamedTypeDeclarationAst | undefined {\n return node.kind === 'NamedTypeDeclaration' ? new NamedTypeDeclarationAst(node) : undefined;\n }\n}\n","import type { TokenKind } from '../tokenizer';\nimport type { SyntaxKind } from './syntax-kind';\n\nexport interface GreenToken {\n readonly type: 'token';\n readonly kind: TokenKind;\n readonly text: string;\n}\n\nexport interface GreenNode {\n readonly type: 'node';\n readonly kind: SyntaxKind;\n readonly children: ReadonlyArray<GreenElement>;\n readonly textLength: number;\n}\n\nexport type GreenElement = GreenNode | GreenToken;\n\nexport function greenToken(kind: TokenKind, text: string): GreenToken {\n return { type: 'token', kind, text };\n}\n\nexport function greenNode(kind: SyntaxKind, children: ReadonlyArray<GreenElement>): GreenNode {\n let textLength = 0;\n for (const child of children) {\n textLength += child.type === 'token' ? child.text.length : child.textLength;\n }\n return { type: 'node', kind, children, textLength };\n}\n","import type { TokenKind } from '../tokenizer';\nimport type { GreenElement, GreenNode } from './green';\nimport { greenNode, greenToken } from './green';\nimport type { SyntaxKind } from './syntax-kind';\n\nexport class GreenNodeBuilder {\n readonly #stack: Array<{ kind: SyntaxKind; children: GreenElement[] }> = [];\n\n startNode(kind: SyntaxKind): void {\n this.#stack.push({ kind, children: [] });\n }\n\n token(kind: TokenKind, text: string): void {\n const current = this.#stack.at(-1);\n if (!current) {\n throw new Error('GreenNodeBuilder: token() called with no open node');\n }\n current.children.push(greenToken(kind, text));\n }\n\n finishNode(): GreenNode {\n const completed = this.#stack.pop();\n if (!completed) {\n throw new Error('GreenNodeBuilder: finishNode() called with no open node');\n }\n const node = greenNode(completed.kind, completed.children);\n const parent = this.#stack.at(-1);\n if (parent) {\n parent.children.push(node);\n }\n return node;\n }\n}\n","import type { PslDiagnosticCode } from '@prisma-next/framework-components/psl-ast';\nimport { UNSPECIFIED_PSL_NAMESPACE_ID } from '@prisma-next/framework-components/psl-ast';\nimport { type Range, SourceFile } from './source-file';\nimport { DocumentAst } from './syntax/ast/declarations';\nimport type { GreenNode } from './syntax/green';\nimport { GreenNodeBuilder } from './syntax/green-builder';\nimport { createSyntaxTree } from './syntax/red';\nimport type { SyntaxKind } from './syntax/syntax-kind';\nimport { isTerminatedStringLiteral, type Token, Tokenizer, type TokenKind } from './tokenizer';\n\nexport interface ParseDiagnostic {\n readonly code: PslDiagnosticCode;\n readonly message: string;\n readonly range: Range;\n}\n\nexport interface ParseResult {\n readonly document: DocumentAst;\n readonly diagnostics: readonly ParseDiagnostic[];\n readonly sourceFile: SourceFile;\n}\n\nconst TRIVIA_KINDS: ReadonlySet<TokenKind> = new Set<TokenKind>([\n 'Whitespace',\n 'Newline',\n 'Comment',\n]);\n\n/**\n * The source span of a token, captured eagerly so it stays valid after the\n * cursor advances past the token it points at.\n */\nexport interface DiagnosticMark {\n readonly offset: number;\n readonly length: number;\n}\n\n/**\n * The fault-tolerant parser substrate the grammars drive. Trivia is flushed\n * into the enclosing open node, so every child node spans exactly its first\n * through last significant token.\n */\nexport class Cursor {\n readonly #tokenizer: Tokenizer;\n readonly #sourceFile: SourceFile;\n readonly #builder = new GreenNodeBuilder();\n readonly #diagnostics: ParseDiagnostic[] = [];\n #offset = 0;\n #depth = 0;\n\n constructor(source: string) {\n this.#tokenizer = new Tokenizer(source);\n this.#sourceFile = new SourceFile(source);\n }\n\n get diagnostics(): readonly ParseDiagnostic[] {\n return this.#diagnostics;\n }\n\n get sourceFile(): SourceFile {\n return this.#sourceFile;\n }\n\n peekKind(ahead = 0): TokenKind {\n return this.peekToken(ahead).kind;\n }\n\n peekToken(ahead = 0): Token {\n let rawIndex = 0;\n let remaining = ahead;\n for (;;) {\n const token = this.#tokenizer.peek(rawIndex);\n if (token.kind === 'Eof') return token;\n if (TRIVIA_KINDS.has(token.kind)) {\n rawIndex++;\n continue;\n }\n if (remaining === 0) return token;\n remaining--;\n rawIndex++;\n }\n }\n\n /** Span of the significant token `lookahead` positions ahead (`mark(0)` = the next). */\n mark(lookahead = 0): DiagnosticMark {\n let rawIndex = 0;\n let offset = this.#offset;\n let remaining = lookahead;\n for (;;) {\n const token = this.#tokenizer.peek(rawIndex);\n if (token.kind === 'Eof') {\n return { offset, length: token.text.length };\n }\n if (!TRIVIA_KINDS.has(token.kind) && remaining === 0) {\n return { offset, length: token.text.length };\n }\n if (!TRIVIA_KINDS.has(token.kind)) {\n remaining--;\n }\n offset += token.text.length;\n rawIndex++;\n }\n }\n\n /**\n * Zero-width mark just past the last consumed significant token — anchors an\n * \"expected here\" diagnostic, e.g. the `{` missing after a declaration's name.\n */\n markAfterLastToken(): DiagnosticMark {\n return { offset: this.#offset, length: 0 };\n }\n\n startNode(kind: SyntaxKind): void {\n if (this.#depth > 0) {\n this.flushTrivia();\n }\n this.#builder.startNode(kind);\n this.#depth++;\n }\n\n finishNode(): GreenNode {\n this.#depth--;\n return this.#builder.finishNode();\n }\n\n bump(): Token {\n this.flushTrivia();\n const token = this.#tokenizer.peek();\n if (token.kind === 'Eof') return token;\n this.#builder.token(token.kind, token.text);\n this.#advance();\n return token;\n }\n\n recoverToSyncPoint(): void {\n for (;;) {\n const token = this.#tokenizer.peek();\n if (token.kind === 'Eof' || token.kind === 'Newline' || token.kind === 'RBrace') {\n return;\n }\n this.#builder.token(token.kind, token.text);\n this.#advance();\n }\n }\n\n flushTrivia(): void {\n for (;;) {\n const token = this.#tokenizer.peek();\n if (!TRIVIA_KINDS.has(token.kind)) return;\n this.#builder.token(token.kind, token.text);\n this.#advance();\n }\n }\n\n diagnostic(code: PslDiagnosticCode, message: string, mark: DiagnosticMark): void {\n const start = mark.offset;\n const end = start + mark.length;\n this.#diagnostics.push({\n code,\n message,\n range: {\n start: this.#sourceFile.positionAt(start),\n end: this.#sourceFile.positionAt(end),\n },\n });\n }\n\n #advance(): void {\n this.#offset += this.#tokenizer.next().text.length;\n }\n}\n\nfunction parseIdentifier(cursor: Cursor): void {\n cursor.startNode('Identifier');\n cursor.bump();\n cursor.finishNode();\n}\n\n/**\n * Returns `undefined` when the next significant token does not start a\n * recognised expression, leaving recovery to the caller.\n */\nexport function parseExpression(cursor: Cursor): GreenNode | undefined {\n return (\n parseStringLiteralExpr(cursor) ??\n parseNumberLiteralExpr(cursor) ??\n parseArrayLiteral(cursor) ??\n parseObjectLiteralExpr(cursor) ??\n parseFunctionCall(cursor) ??\n parseBooleanLiteralExpr(cursor) ??\n parseIdentifierExpr(cursor)\n );\n}\n\nexport function parseStringLiteralExpr(cursor: Cursor): GreenNode | undefined {\n if (cursor.peekKind() !== 'StringLiteral') return undefined;\n const stringMark = cursor.mark();\n const text = cursor.peekToken().text;\n cursor.startNode('StringLiteralExpr');\n cursor.bump();\n if (!isTerminatedStringLiteral(text)) {\n cursor.diagnostic('PSL_UNTERMINATED_STRING', 'Unterminated string literal', stringMark);\n }\n return cursor.finishNode();\n}\n\nexport function parseNumberLiteralExpr(cursor: Cursor): GreenNode | undefined {\n if (cursor.peekKind() !== 'NumberLiteral') return undefined;\n cursor.startNode('NumberLiteralExpr');\n cursor.bump();\n return cursor.finishNode();\n}\n\n/**\n * Parses a namespace-qualified name `[space ':']? Ident ('.' Ident)*`. The\n * caller guarantees a leading `Ident`.\n *\n * Parsing the whole chain up front lets a position decide\n * constructor-vs-reference by peeking exactly one token for `(`, with no scan of\n * the dotted chain's length.\n */\nexport function parseQualifiedName(cursor: Cursor): void {\n cursor.startNode('QualifiedName');\n parseIdentifier(cursor); // first segment: the space, namespace, or bare name\n parseQualifiedSegments(cursor, 'Colon');\n parseQualifiedSegments(cursor, 'Dot');\n cursor.finishNode();\n}\n\n/**\n * A well-formed name carries at most one colon space and one dot namespace, so\n * each separator past the first of its kind reports `PSL_INVALID_QUALIFIED_NAME`.\n * The separator is consumed regardless, keeping the lossless round-trip intact.\n */\nfunction parseQualifiedSegments(cursor: Cursor, separator: 'Colon' | 'Dot'): void {\n let seen = 0;\n while (cursor.peekKind() === separator) {\n seen++;\n const separatorMark = cursor.mark();\n cursor.bump();\n if (seen > 1) {\n cursor.diagnostic(\n 'PSL_INVALID_QUALIFIED_NAME',\n 'Qualified name has too many segments',\n separatorMark,\n );\n }\n if (cursor.peekKind() === 'Ident') {\n parseIdentifier(cursor);\n } else {\n cursor.diagnostic(\n 'PSL_INVALID_QUALIFIED_NAME',\n 'Qualified name is missing a name after the separator',\n cursor.mark(),\n );\n }\n }\n}\n\n// Ordering among the `Ident`-leading alternatives is load-bearing: the\n// `LParen`/`Dot` lookahead of `parseCall` must win before the boolean check, so\n// `true(` stays a function call named `true` rather than a boolean literal.\nexport function parseBooleanLiteralExpr(cursor: Cursor): GreenNode | undefined {\n if (cursor.peekKind() !== 'Ident') return undefined;\n const text = cursor.peekToken().text;\n if (text !== 'true' && text !== 'false') return undefined;\n cursor.startNode('BooleanLiteralExpr');\n cursor.bump();\n return cursor.finishNode();\n}\n\nexport function parseIdentifierExpr(cursor: Cursor): GreenNode | undefined {\n if (cursor.peekKind() !== 'Ident') return undefined;\n cursor.startNode('Identifier');\n cursor.bump();\n return cursor.finishNode();\n}\n\nexport function parseArrayLiteral(cursor: Cursor): GreenNode | undefined {\n if (cursor.peekKind() !== 'LBracket') return undefined;\n cursor.startNode('ArrayLiteral');\n cursor.bump();\n while (cursor.peekKind() !== 'RBracket' && cursor.peekKind() !== 'Eof') {\n const element = parseExpression(cursor);\n if (!element) break;\n if (cursor.peekKind() === 'Comma') {\n cursor.bump();\n } else {\n break;\n }\n }\n if (cursor.peekKind() === 'RBracket') {\n cursor.bump();\n }\n return cursor.finishNode();\n}\n\nexport function parseObjectLiteralExpr(cursor: Cursor): GreenNode | undefined {\n if (cursor.peekKind() !== 'LBrace') return undefined;\n const braceMark = cursor.mark();\n cursor.startNode('ObjectLiteralExpr');\n cursor.bump();\n while (cursor.peekKind() !== 'RBrace' && cursor.peekKind() !== 'Eof') {\n parseObjectField(cursor);\n if (cursor.peekKind() === 'Comma') {\n cursor.bump();\n } else if (cursor.peekKind() === 'Ident') {\n // A following identifier key with no comma re-enters the loop; the next\n // parseObjectField consumes ≥1 token, so progress is guaranteed.\n cursor.diagnostic(\n 'PSL_INVALID_OBJECT_LITERAL',\n 'Expected \",\" between object-literal fields',\n cursor.markAfterLastToken(),\n );\n } else {\n break;\n }\n }\n if (cursor.peekKind() === 'RBrace') {\n cursor.bump();\n } else {\n cursor.diagnostic('PSL_INVALID_OBJECT_LITERAL', 'Unterminated object literal', braceMark);\n }\n return cursor.finishNode();\n}\n\nexport function parseObjectField(cursor: Cursor): GreenNode {\n cursor.startNode('ObjectField');\n const keyMark = cursor.mark();\n const keyText = cursor.peekToken().text;\n if (cursor.peekKind() === 'Ident') {\n parseIdentifier(cursor);\n } else if (cursor.peekKind() === 'StringLiteral') {\n // A string-literal key (e.g. `{ \"length\": 35 }`) is accepted; its logical\n // name is the unquoted string.\n parseStringLiteralExpr(cursor);\n }\n if (cursor.peekKind() === 'Colon') {\n cursor.bump(); // Colon\n const value = parseExpression(cursor);\n if (!value) {\n cursor.diagnostic('PSL_INVALID_OBJECT_LITERAL', 'Expected a value after \":\"', cursor.mark());\n }\n } else {\n cursor.diagnostic('PSL_INVALID_OBJECT_LITERAL', `Expected \":\" after \"${keyText}\"`, keyMark);\n const followsWithKey = cursor.peekKind() === 'Ident' && cursor.peekKind(1) === 'Colon';\n if (!followsWithKey) {\n parseExpression(cursor); // best-effort: consume a value if one follows\n }\n }\n return cursor.finishNode();\n}\n\n/**\n * Whether the next tokens open a call: a bare `Ident(` or a namespace-qualified\n * `Ident.Ident(`. The lookahead is deliberately bounded so a bare dotted\n * reference like `a.b` is not mistaken for a call, rather than scanning an\n * unbounded dotted chain ahead to find the paren.\n */\nfunction isCallAhead(cursor: Cursor): boolean {\n if (cursor.peekKind() !== 'Ident') return false;\n if (cursor.peekKind(1) === 'LParen') return true;\n return (\n cursor.peekKind(1) === 'Dot' &&\n cursor.peekKind(2) === 'Ident' &&\n cursor.peekKind(3) === 'LParen'\n );\n}\n\n/**\n * Parses a function/constructor call — bare `autoincrement()` or qualified\n * `temporal.updatedAt()`. Returns `undefined` unless {@link isCallAhead}\n * confirms a trailing `(`, so the `parseExpression` chain falls through to the\n * boolean and bare-identifier forms.\n */\nexport function parseFunctionCall(cursor: Cursor): GreenNode | undefined {\n if (!isCallAhead(cursor)) return undefined;\n cursor.startNode('FunctionCall');\n parseQualifiedName(cursor);\n if (cursor.peekKind() === 'LParen') {\n parseParenArgs(cursor);\n }\n return cursor.finishNode();\n}\n\n/** Parses a parenthesised, comma-separated `AttributeArg` list into the currently open node. */\nfunction parseParenArgs(cursor: Cursor): void {\n cursor.bump();\n while (cursor.peekKind() !== 'RParen' && cursor.peekKind() !== 'Eof') {\n parseAttributeArg(cursor);\n if (cursor.peekKind() === 'Comma') {\n cursor.bump();\n } else {\n break;\n }\n }\n if (cursor.peekKind() === 'RParen') {\n cursor.bump();\n }\n}\n\nexport function parseAttributeArg(cursor: Cursor): GreenNode {\n cursor.startNode('AttributeArg');\n if (cursor.peekKind() === 'Ident' && cursor.peekKind(1) === 'Colon') {\n parseIdentifier(cursor);\n cursor.bump();\n }\n parseArgValue(cursor);\n return cursor.finishNode();\n}\n\nfunction parseArgValue(cursor: Cursor): void {\n parseExpression(cursor);\n}\n\nexport function parseAttributeArgList(cursor: Cursor): GreenNode {\n cursor.startNode('AttributeArgList');\n parseParenArgs(cursor);\n return cursor.finishNode();\n}\n\nexport function parseAttribute(cursor: Cursor): GreenNode {\n const isBlockAttribute = cursor.peekKind() === 'DoubleAt';\n const attributeMark = cursor.mark();\n cursor.startNode(isBlockAttribute ? 'ModelAttribute' : 'FieldAttribute');\n cursor.bump();\n if (cursor.peekKind() === 'Ident') {\n parseQualifiedName(cursor);\n } else {\n cursor.diagnostic('PSL_INVALID_ATTRIBUTE_SYNTAX', 'Attribute name expected', attributeMark);\n }\n if (cursor.peekKind() === 'LParen') {\n parseAttributeArgList(cursor);\n }\n return cursor.finishNode();\n}\n\n/** A type annotation: `QualifiedName (argList)? ([])? (?)?`, e.g. `pgvector.Vector(1536)[]?`. */\nexport function parseTypeAnnotation(cursor: Cursor): GreenNode {\n cursor.startNode('TypeAnnotation');\n if (cursor.peekKind() === 'Ident') {\n parseQualifiedName(cursor);\n if (cursor.peekKind() === 'LParen') {\n parseAttributeArgList(cursor);\n }\n }\n if (cursor.peekKind() === 'LBracket') {\n cursor.bump();\n if (cursor.peekKind() === 'RBracket') {\n cursor.bump();\n }\n }\n if (cursor.peekKind() === 'Question') {\n cursor.bump();\n }\n return cursor.finishNode();\n}\n\ntype MemberParser = (cursor: Cursor) => void;\n\n/**\n * Parses a full PSL document. Never throws — malformed input yields diagnostics\n * and a recovered tree, not an exception.\n */\nexport function parse(source: string): ParseResult {\n const cursor = new Cursor(source);\n const green = parseDocument(cursor);\n const root = createSyntaxTree(green);\n const document = DocumentAst.cast(root) ?? new DocumentAst(root);\n return { document, diagnostics: cursor.diagnostics, sourceFile: cursor.sourceFile };\n}\n\nfunction parseDocument(cursor: Cursor): GreenNode {\n cursor.startNode('Document');\n while (cursor.peekKind() !== 'Eof') {\n parseDeclaration(cursor, false);\n }\n cursor.flushTrivia(); // attach trailing trivia so the round-trip stays lossless\n return cursor.finishNode();\n}\n\nconst RESERVED_BLOCK_KEYWORDS: ReadonlySet<string> = new Set([\n 'model',\n 'namespace',\n 'type',\n 'types',\n]);\n\nfunction keywordIs(cursor: Cursor, keyword: string): boolean {\n return cursor.peekKind() === 'Ident' && cursor.peekToken().text === keyword;\n}\n\n/**\n * Each alternative is a no-op on non-match, consuming nothing, so the\n * forward-only cursor is never left half-consumed by a rejected alternative.\n * Recovery runs via the `if (!node)` tail rather than as a `??` arm, because it\n * appends raw tokens to the open parent instead of returning a child node.\n */\nfunction parseDeclaration(cursor: Cursor, insideNamespace: boolean): void {\n const name = cursor.peekKind(1) === 'Ident' ? cursor.peekToken(1).text : '';\n if (insideNamespace && keywordIs(cursor, 'namespace')) {\n cursor.diagnostic(\n 'PSL_INVALID_NAMESPACE_BLOCK',\n `Recursive \"namespace ${name}\" block is not allowed; namespace blocks may not nest`,\n cursor.mark(),\n );\n } else if (insideNamespace && keywordIs(cursor, 'types')) {\n cursor.diagnostic(\n 'PSL_INVALID_NAMESPACE_BLOCK',\n '`types` blocks must be declared at the document top level, not inside a namespace block',\n cursor.mark(),\n );\n } else if (keywordIs(cursor, 'namespace') && name === UNSPECIFIED_PSL_NAMESPACE_ID) {\n cursor.diagnostic(\n 'PSL_INVALID_NAMESPACE_BLOCK',\n `Namespace name \"${UNSPECIFIED_PSL_NAMESPACE_ID}\" is reserved for the parser-synthesised bucket for top-level declarations`,\n cursor.mark(1),\n );\n }\n\n const node =\n parseModel(cursor) ??\n parseNamespace(cursor) ??\n parseCompositeType(cursor) ??\n parseTypesBlock(cursor) ??\n parseGenericBlock(cursor);\n if (!node) {\n parseUnsupportedTopLevel(cursor);\n }\n}\n\n/**\n * Reports only the first missing piece — a missing name suppresses the\n * missing-brace diagnostic. `nameRequired` is false only for the `types` block.\n */\nfunction parseBlock(\n cursor: Cursor,\n kind: SyntaxKind,\n nameRequired: boolean,\n parseMember: MemberParser,\n): GreenNode {\n const keyword = cursor.peekToken().text;\n const keywordMark = cursor.mark();\n cursor.startNode(kind);\n cursor.bump();\n const hasName = nameRequired && cursor.peekKind() === 'Ident';\n if (hasName) {\n parseIdentifier(cursor);\n }\n if (nameRequired && !hasName) {\n cursor.diagnostic('PSL_INVALID_DECLARATION', `Expected a name after \"${keyword}\"`, keywordMark);\n } else if (cursor.peekKind() !== 'LBrace') {\n cursor.diagnostic(\n 'PSL_INVALID_DECLARATION',\n `Expected \"{\" to open the \"${keyword}\" block`,\n cursor.markAfterLastToken(),\n );\n }\n if (cursor.peekKind() === 'LBrace') {\n parseBlockBody(cursor, parseMember);\n } else {\n cursor.recoverToSyncPoint();\n }\n return cursor.finishNode();\n}\n\nexport function parseModel(cursor: Cursor): GreenNode | undefined {\n if (!keywordIs(cursor, 'model')) return undefined;\n return parseBlock(cursor, 'ModelDeclaration', true, parseModelMember);\n}\n\n/**\n * Excluding the reserved keywords keeps a malformed reserved block (e.g. `model\n * {` with no name) routed to its dedicated parser. The generic keyword set is\n * open, so a bare identifier with no brace (e.g. `oops`) is read as an unfinished\n * custom declaration rather than unsupported content.\n */\nexport function parseGenericBlock(cursor: Cursor): GreenNode | undefined {\n if (cursor.peekKind() !== 'Ident') return undefined;\n const keyword = cursor.peekToken().text;\n if (RESERVED_BLOCK_KEYWORDS.has(keyword)) return undefined;\n const hasName = cursor.peekKind(1) === 'Ident' && cursor.peekKind(2) === 'LBrace';\n cursor.startNode('GenericBlockDeclaration');\n cursor.bump();\n if (hasName) {\n parseIdentifier(cursor);\n }\n if (cursor.peekKind() === 'LBrace') {\n parseBlockBody(cursor, parseKeyValueMember);\n } else {\n cursor.diagnostic(\n 'PSL_INVALID_DECLARATION',\n `Expected \"{\" to open the \"${keyword}\" block`,\n cursor.markAfterLastToken(),\n );\n cursor.recoverToSyncPoint();\n }\n return cursor.finishNode();\n}\n\nexport function parseNamespace(cursor: Cursor): GreenNode | undefined {\n if (!keywordIs(cursor, 'namespace')) return undefined;\n return parseBlock(cursor, 'Namespace', true, (inner) => parseDeclaration(inner, true));\n}\n\nexport function parseCompositeType(cursor: Cursor): GreenNode | undefined {\n if (!keywordIs(cursor, 'type')) return undefined;\n return parseBlock(cursor, 'CompositeTypeDeclaration', true, parseModelMember);\n}\n\n/** `types` (plural) is the no-name types block; the singular `type` is the composite type above. */\nexport function parseTypesBlock(cursor: Cursor): GreenNode | undefined {\n if (!keywordIs(cursor, 'types')) return undefined;\n return parseBlock(cursor, 'TypesBlock', false, parseNamedTypeMember);\n}\n\n/** Every `parseMember` consumes at least one significant token, so the loop always terminates. */\nfunction parseBlockBody(cursor: Cursor, parseMember: MemberParser): void {\n const braceMark = cursor.mark();\n cursor.bump();\n for (;;) {\n const kind = cursor.peekKind();\n if (kind === 'RBrace' || kind === 'Eof') break;\n parseMember(cursor);\n }\n if (cursor.peekKind() === 'RBrace') {\n cursor.bump();\n } else {\n cursor.diagnostic('PSL_UNTERMINATED_BLOCK', 'Unterminated block declaration', braceMark);\n }\n}\n\nfunction parseUnsupportedTopLevel(cursor: Cursor): void {\n const offending = cursor.peekToken().text;\n const message =\n cursor.peekKind(1) === 'LBrace'\n ? `Unsupported top-level block \"${offending}\"`\n : `Unsupported top-level declaration \"${offending}\"`;\n cursor.diagnostic('PSL_UNSUPPORTED_TOP_LEVEL_BLOCK', message, cursor.mark());\n cursor.bump();\n cursor.recoverToSyncPoint();\n}\n\n/**\n * Matches a leading `@@` block attribute, a no-op otherwise. Single-`@`\n * attributes belong to fields and are parsed inside `parseField`.\n */\nexport function parseBlockAttribute(cursor: Cursor): GreenNode | undefined {\n if (cursor.peekKind() !== 'DoubleAt') return undefined;\n return parseAttribute(cursor);\n}\n\nfunction parseModelMember(cursor: Cursor): void {\n const node = parseBlockAttribute(cursor) ?? parseField(cursor);\n if (!node) {\n invalidMember(\n cursor,\n 'PSL_INVALID_MODEL_MEMBER',\n `Invalid model member declaration \"${cursor.peekToken().text}\"`,\n );\n }\n}\n\nfunction parseNamedTypeMember(cursor: Cursor): void {\n const node = parseNamedType(cursor);\n if (!node) {\n invalidMember(\n cursor,\n 'PSL_INVALID_TYPES_MEMBER',\n `Invalid types declaration \"${cursor.peekToken().text}\"`,\n );\n }\n}\n\n/**\n * A generic-block member is either a `@@`-block attribute or a `key = value`\n * entry. The block-attribute alternative is purely syntactic — it does not judge\n * whether the attribute is valid for the block's kind.\n */\nfunction parseKeyValueMember(cursor: Cursor): void {\n const node = parseBlockAttribute(cursor) ?? parseKeyValue(cursor);\n if (!node) {\n invalidMember(cursor, 'PSL_INVALID_EXTENSION_BLOCK_MEMBER', 'Invalid block entry');\n }\n}\n\nfunction invalidMember(cursor: Cursor, code: PslDiagnosticCode, message: string): void {\n cursor.diagnostic(code, message, cursor.mark());\n cursor.bump(); // consume the offending token so the member loop makes progress\n cursor.recoverToSyncPoint();\n}\n\nexport function parseField(cursor: Cursor): GreenNode | undefined {\n if (cursor.peekKind() !== 'Ident') return undefined;\n cursor.startNode('FieldDeclaration');\n parseIdentifier(cursor);\n parseTypeAnnotation(cursor);\n while (cursor.peekKind() === 'At') {\n parseAttribute(cursor);\n }\n return cursor.finishNode();\n}\n\nexport function parseNamedType(cursor: Cursor): GreenNode | undefined {\n if (cursor.peekKind() !== 'Ident') return undefined;\n cursor.startNode('NamedTypeDeclaration');\n const nameMark = cursor.mark();\n const nameText = cursor.peekToken().text;\n parseIdentifier(cursor);\n if (cursor.peekKind() === 'Equals') {\n cursor.bump();\n } else {\n cursor.diagnostic('PSL_INVALID_TYPES_MEMBER', `Expected \"=\" after \"${nameText}\"`, nameMark);\n }\n parseTypeAnnotation(cursor);\n while (cursor.peekKind() === 'At') {\n parseAttribute(cursor);\n }\n return cursor.finishNode();\n}\n\n/**\n * A generic-block entry is either `key = value` or a bare `key` (committing a\n * `KeyValuePair` carrying only the key). A `key =` with no following expression\n * is flagged.\n */\nexport function parseKeyValue(cursor: Cursor): GreenNode | undefined {\n if (cursor.peekKind() !== 'Ident') return undefined;\n cursor.startNode('KeyValuePair');\n parseIdentifier(cursor);\n if (cursor.peekKind() === 'Equals') {\n cursor.bump();\n if (!parseExpression(cursor)) {\n cursor.diagnostic(\n 'PSL_INVALID_EXTENSION_BLOCK_MEMBER',\n 'Expected a value after \"=\"',\n cursor.mark(),\n );\n }\n }\n return cursor.finishNode();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"syntax.mjs","names":[],"sources":["../src/syntax/navigation.ts"],"sourcesContent":["import type { TokenKind } from '../tokenizer';\nimport { type SyntaxElement, SyntaxToken } from './red';\n\n/** Direction of a sibling/token walk. */\nexport type Direction = 'next' | 'prev';\n\nconst TRIVIA_KINDS: ReadonlySet<TokenKind> = new Set<TokenKind>([\n 'Whitespace',\n 'Newline',\n 'Comment',\n]);\n\n/** Whether a token kind is trivia (whitespace, newline, or comment). */\nexport function isTriviaKind(kind: TokenKind): boolean {\n return TRIVIA_KINDS.has(kind);\n}\n\n/** Whether a token is trivia. */\nexport function isTrivia(token: SyntaxToken): boolean {\n return isTriviaKind(token.kind);\n}\n\n/**\n * The first non-trivia token at or beyond `token` in `direction`. Returns\n * `token` itself when it is already significant.\n */\nexport function skipTriviaToken(token: SyntaxToken, direction: Direction): SyntaxToken | undefined {\n let current: SyntaxToken | undefined = token;\n while (current !== undefined && isTrivia(current)) {\n current = direction === 'next' ? current.nextToken : current.prevToken;\n }\n return current;\n}\n\n/**\n * The nearest sibling of `element` (within the same parent) in `direction` that\n * is not a trivia token. Nodes are always significant.\n */\nexport function nonTriviaSibling(\n element: SyntaxElement,\n direction: Direction,\n): SyntaxElement | undefined {\n let sibling = step(element, direction);\n while (sibling !== undefined) {\n if (!(sibling instanceof SyntaxToken) || !isTrivia(sibling)) {\n return sibling;\n }\n sibling = step(sibling, direction);\n }\n return undefined;\n}\n\nfunction step(element: SyntaxElement, direction: Direction): SyntaxElement | undefined {\n return direction === 'next' ? element.nextSiblingOrToken : element.prevSiblingOrToken;\n}\n"],"mappings":";;;AAMA,MAAM,+BAAuC,IAAI,IAAe;CAC9D;CACA;CACA;AACF,CAAC;;AAGD,SAAgB,aAAa,MAA0B;CACrD,OAAO,aAAa,IAAI,IAAI;AAC9B;;AAGA,SAAgB,SAAS,OAA6B;CACpD,OAAO,aAAa,MAAM,IAAI;AAChC;;;;;AAMA,SAAgB,gBAAgB,OAAoB,WAA+C;CACjG,IAAI,UAAmC;CACvC,OAAO,YAAY,KAAA,KAAa,SAAS,OAAO,GAC9C,UAAU,cAAc,SAAS,QAAQ,YAAY,QAAQ;CAE/D,OAAO;AACT;;;;;AAMA,SAAgB,iBACd,SACA,WAC2B;CAC3B,IAAI,UAAU,KAAK,SAAS,SAAS;CACrC,OAAO,YAAY,KAAA,GAAW;EAC5B,IAAI,EAAE,mBAAmB,gBAAgB,CAAC,SAAS,OAAO,GACxD,OAAO;EAET,UAAU,KAAK,SAAS,SAAS;CACnC;AAEF;AAEA,SAAS,KAAK,SAAwB,WAAiD;CACrF,OAAO,cAAc,SAAS,QAAQ,qBAAqB,QAAQ;AACrE"}
|
package/package.json
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prisma-next/psl-parser",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0-dev.10",
|
|
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/
|
|
10
|
-
"@prisma-next/
|
|
9
|
+
"@prisma-next/config": "0.15.0-dev.10",
|
|
10
|
+
"@prisma-next/contract": "0.15.0-dev.10",
|
|
11
|
+
"@prisma-next/framework-components": "0.15.0-dev.10",
|
|
12
|
+
"@prisma-next/utils": "0.15.0-dev.10"
|
|
11
13
|
},
|
|
12
14
|
"devDependencies": {
|
|
13
|
-
"@prisma-next/tsconfig": "0.
|
|
14
|
-
"@prisma-next/tsdown": "0.
|
|
15
|
-
"tsdown": "0.22.
|
|
15
|
+
"@prisma-next/tsconfig": "0.15.0-dev.10",
|
|
16
|
+
"@prisma-next/tsdown": "0.15.0-dev.10",
|
|
17
|
+
"tsdown": "0.22.3",
|
|
16
18
|
"typescript": "5.9.3",
|
|
17
|
-
"vitest": "4.1.
|
|
19
|
+
"vitest": "4.1.10"
|
|
18
20
|
},
|
|
19
21
|
"peerDependencies": {
|
|
20
22
|
"typescript": ">=5.9"
|
|
@@ -31,7 +33,8 @@
|
|
|
31
33
|
"types": "./dist/index.d.mts",
|
|
32
34
|
"exports": {
|
|
33
35
|
".": "./dist/index.mjs",
|
|
34
|
-
"./
|
|
36
|
+
"./format": "./dist/format.mjs",
|
|
37
|
+
"./interpret": "./dist/interpret.mjs",
|
|
35
38
|
"./syntax": "./dist/syntax.mjs",
|
|
36
39
|
"./tokenizer": "./dist/tokenizer.mjs",
|
|
37
40
|
"./package.json": "./package.json"
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
3
|
+
import { BooleanLiteralExprAst } from '../../syntax/ast/expressions';
|
|
4
|
+
import type { ArgType } from '../types';
|
|
5
|
+
import { leafDiagnostic } from './diagnostic';
|
|
6
|
+
|
|
7
|
+
export function bool(): ArgType<boolean> {
|
|
8
|
+
return {
|
|
9
|
+
kind: 'bool',
|
|
10
|
+
label: 'boolean',
|
|
11
|
+
parse: (arg, ctx): Result<boolean, readonly PslDiagnostic[]> => {
|
|
12
|
+
if (arg instanceof BooleanLiteralExprAst) {
|
|
13
|
+
const value = arg.value();
|
|
14
|
+
if (value !== undefined) return ok(value);
|
|
15
|
+
}
|
|
16
|
+
return notOk([leafDiagnostic(ctx, arg, 'Expected a boolean literal')]);
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PslDiagnostic, PslDiagnosticCode } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { nodePslSpan } from '../../resolve';
|
|
3
|
+
import type { AstNode } from '../../syntax/ast-helpers';
|
|
4
|
+
import type { InterpretCtx } from '../types';
|
|
5
|
+
|
|
6
|
+
export const ATTRIBUTE_DIAGNOSTIC_CODE: PslDiagnosticCode = 'PSL_INVALID_ATTRIBUTE_SYNTAX';
|
|
7
|
+
|
|
8
|
+
export function leafDiagnostic(ctx: InterpretCtx, node: AstNode, message: string): PslDiagnostic {
|
|
9
|
+
return {
|
|
10
|
+
code: ATTRIBUTE_DIAGNOSTIC_CODE,
|
|
11
|
+
message,
|
|
12
|
+
sourceId: ctx.sourceId,
|
|
13
|
+
span: nodePslSpan(node.syntax, ctx.sourceFile),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
3
|
+
import { IdentifierAst } from '../../syntax/ast/identifier';
|
|
4
|
+
import type { ArgType } from '../types';
|
|
5
|
+
import { leafDiagnostic } from './diagnostic';
|
|
6
|
+
|
|
7
|
+
// A bare model-name reference. Existence of a model with this name is resolved
|
|
8
|
+
// downstream (e.g. `resolvePolymorphism`), not here.
|
|
9
|
+
export function entityRef(): ArgType<string> {
|
|
10
|
+
return {
|
|
11
|
+
kind: 'entityRef',
|
|
12
|
+
label: 'model name',
|
|
13
|
+
parse: (arg, ctx): Result<string, readonly PslDiagnostic[]> => {
|
|
14
|
+
if (!(arg instanceof IdentifierAst)) {
|
|
15
|
+
return notOk([leafDiagnostic(ctx, arg, 'Expected a model name')]);
|
|
16
|
+
}
|
|
17
|
+
const name = arg.name();
|
|
18
|
+
if (name === undefined) {
|
|
19
|
+
return notOk([leafDiagnostic(ctx, arg, 'Expected a model name')]);
|
|
20
|
+
}
|
|
21
|
+
return ok(name);
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
3
|
+
import { IdentifierAst } from '../../syntax/ast/identifier';
|
|
4
|
+
import type { ArgType } from '../types';
|
|
5
|
+
import { leafDiagnostic } from './diagnostic';
|
|
6
|
+
|
|
7
|
+
export type FieldRefScope = 'self' | 'referenced';
|
|
8
|
+
|
|
9
|
+
export interface FieldRefArgType extends ArgType<string> {
|
|
10
|
+
readonly scope: FieldRefScope;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function fieldRef(scope: FieldRefScope): FieldRefArgType {
|
|
14
|
+
return {
|
|
15
|
+
kind: 'fieldRef',
|
|
16
|
+
label: 'field name',
|
|
17
|
+
scope,
|
|
18
|
+
parse: (arg, ctx): Result<string, readonly PslDiagnostic[]> => {
|
|
19
|
+
if (!(arg instanceof IdentifierAst)) {
|
|
20
|
+
return notOk([leafDiagnostic(ctx, arg, 'Expected a field name')]);
|
|
21
|
+
}
|
|
22
|
+
const name = arg.name();
|
|
23
|
+
if (name === undefined) {
|
|
24
|
+
return notOk([leafDiagnostic(ctx, arg, 'Expected a field name')]);
|
|
25
|
+
}
|
|
26
|
+
const model = scope === 'self' ? ctx.selfModel : ctx.resolveReferencedModel();
|
|
27
|
+
// A referenced model in another space can't be resolved here (resolveReferencedModel returns undefined); skip the existence check — it runs where that model is known.
|
|
28
|
+
if (model !== undefined && !Object.hasOwn(model.fields, name)) {
|
|
29
|
+
return notOk([
|
|
30
|
+
leafDiagnostic(ctx, arg, `Field "${name}" does not exist on model "${model.name}"`),
|
|
31
|
+
]);
|
|
32
|
+
}
|
|
33
|
+
return ok(name);
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { PslDiagnostic, PslSpan } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
3
|
+
import { nodePslSpan } from '../../resolve';
|
|
4
|
+
import type { ExpressionAst } from '../../syntax/ast/expressions';
|
|
5
|
+
import { FunctionCallAst } from '../../syntax/ast/expressions';
|
|
6
|
+
import { interpretArgs } from '../interpret';
|
|
7
|
+
import type { ArgType, InterpretCtx, Param, PositionalParam } from '../types';
|
|
8
|
+
import { leafDiagnostic } from './diagnostic';
|
|
9
|
+
|
|
10
|
+
// The argument signature of a pinned function call — the same positional/named shape an attribute
|
|
11
|
+
// spec uses. Omitted groups default to empty, so a nullary call needs neither key.
|
|
12
|
+
export interface FuncCallSig {
|
|
13
|
+
readonly positional?: readonly PositionalParam<unknown>[];
|
|
14
|
+
readonly named?: Readonly<Record<string, Param<unknown>>>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface TypedFuncCall {
|
|
18
|
+
readonly fn: string;
|
|
19
|
+
readonly span: PslSpan;
|
|
20
|
+
readonly args: Readonly<Record<string, unknown>>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// A name-pinned function-call argument — `funcCall('now', {})` matches `now()`, parsing the call's
|
|
24
|
+
// arguments through `sig`.
|
|
25
|
+
export function funcCall(name: string, sig: FuncCallSig): ArgType<TypedFuncCall> {
|
|
26
|
+
return {
|
|
27
|
+
kind: 'funcCall',
|
|
28
|
+
label: 'function call',
|
|
29
|
+
parse: (arg, ctx): Result<TypedFuncCall, readonly PslDiagnostic[]> => {
|
|
30
|
+
const guard = matchCallee(arg, name, ctx);
|
|
31
|
+
if (!guard.ok) return guard;
|
|
32
|
+
const span = nodePslSpan(guard.value.syntax, ctx.sourceFile);
|
|
33
|
+
const bound = interpretArgs(
|
|
34
|
+
guard.value.args(),
|
|
35
|
+
{ name, positional: sig.positional ?? [], named: sig.named ?? {} },
|
|
36
|
+
ctx,
|
|
37
|
+
span,
|
|
38
|
+
);
|
|
39
|
+
if (!bound.ok) return notOk<readonly PslDiagnostic[]>(bound.failure);
|
|
40
|
+
return ok({ fn: name, span, args: bound.value });
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function matchCallee(
|
|
46
|
+
arg: ExpressionAst,
|
|
47
|
+
name: string,
|
|
48
|
+
ctx: InterpretCtx,
|
|
49
|
+
): Result<FunctionCallAst, readonly PslDiagnostic[]> {
|
|
50
|
+
if (!(arg instanceof FunctionCallAst)) {
|
|
51
|
+
return notOk([leafDiagnostic(ctx, arg, 'Expected a function call')]);
|
|
52
|
+
}
|
|
53
|
+
const qname = arg.name();
|
|
54
|
+
if (qname === undefined || qname.dot() !== undefined || qname.colon() !== undefined) {
|
|
55
|
+
return notOk([leafDiagnostic(ctx, arg, 'Expected a function call')]);
|
|
56
|
+
}
|
|
57
|
+
const calleeName = qname.identifier()?.token()?.text;
|
|
58
|
+
if (calleeName === undefined) {
|
|
59
|
+
return notOk([leafDiagnostic(ctx, arg, 'Expected a function call')]);
|
|
60
|
+
}
|
|
61
|
+
if (calleeName !== name) {
|
|
62
|
+
return notOk([leafDiagnostic(ctx, arg, `Expected ${name}()`)]);
|
|
63
|
+
}
|
|
64
|
+
return ok(arg);
|
|
65
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
3
|
+
import { IdentifierAst } from '../../syntax/ast/identifier';
|
|
4
|
+
import type { ArgType } from '../types';
|
|
5
|
+
import { leafDiagnostic } from './diagnostic';
|
|
6
|
+
|
|
7
|
+
export function identifier<const N extends string>(name: N): ArgType<N> {
|
|
8
|
+
return {
|
|
9
|
+
kind: 'identifier',
|
|
10
|
+
label: name,
|
|
11
|
+
parse: (arg, ctx): Result<N, readonly PslDiagnostic[]> => {
|
|
12
|
+
if (arg instanceof IdentifierAst && arg.name() === name) return ok(name);
|
|
13
|
+
return notOk([leafDiagnostic(ctx, arg, `Expected ${name}`)]);
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
3
|
+
import { NumberLiteralExprAst } from '../../syntax/ast/expressions';
|
|
4
|
+
import type { ArgType } from '../types';
|
|
5
|
+
import { leafDiagnostic } from './diagnostic';
|
|
6
|
+
|
|
7
|
+
// An integer literal reduced to its numeric value. Passing `min`/`max` additionally rejects
|
|
8
|
+
// out-of-range integers with a distinct range message, leaving the integer-only check intact.
|
|
9
|
+
export function int(opts?: { min?: number; max?: number }): ArgType<number> {
|
|
10
|
+
const min = opts?.min;
|
|
11
|
+
const max = opts?.max;
|
|
12
|
+
return {
|
|
13
|
+
kind: 'int',
|
|
14
|
+
label: 'integer',
|
|
15
|
+
parse: (arg, ctx): Result<number, readonly PslDiagnostic[]> => {
|
|
16
|
+
if (arg instanceof NumberLiteralExprAst) {
|
|
17
|
+
const value = arg.value();
|
|
18
|
+
if (value !== undefined && Number.isInteger(value)) {
|
|
19
|
+
if ((min === undefined || value >= min) && (max === undefined || value <= max)) {
|
|
20
|
+
return ok(value);
|
|
21
|
+
}
|
|
22
|
+
return notOk([leafDiagnostic(ctx, arg, rangeMessage(min, max))]);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return notOk([leafDiagnostic(ctx, arg, 'Expected an integer literal')]);
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function rangeMessage(min: number | undefined, max: number | undefined): string {
|
|
31
|
+
if (min !== undefined && max !== undefined)
|
|
32
|
+
return `Expected an integer between ${min} and ${max}`;
|
|
33
|
+
if (min !== undefined) return `Expected an integer greater than or equal to ${min}`;
|
|
34
|
+
return `Expected an integer less than or equal to ${max}`;
|
|
35
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
3
|
+
import { ArrayLiteralAst, type ExpressionAst } from '../../syntax/ast/expressions';
|
|
4
|
+
import type { ArgType } from '../types';
|
|
5
|
+
import { leafDiagnostic } from './diagnostic';
|
|
6
|
+
|
|
7
|
+
export interface ListOptions {
|
|
8
|
+
readonly nonEmpty?: boolean;
|
|
9
|
+
readonly unique?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function list<T>(of: ArgType<T>, opts?: ListOptions): ArgType<T[]> {
|
|
13
|
+
return {
|
|
14
|
+
kind: 'list',
|
|
15
|
+
label: `${of.label}[]`,
|
|
16
|
+
parse: (arg, ctx): Result<T[], readonly PslDiagnostic[]> => {
|
|
17
|
+
if (!(arg instanceof ArrayLiteralAst)) {
|
|
18
|
+
return notOk([leafDiagnostic(ctx, arg, `Expected a list of ${of.label}`)]);
|
|
19
|
+
}
|
|
20
|
+
const diagnostics: PslDiagnostic[] = [];
|
|
21
|
+
const parsed: { node: ExpressionAst; value: T }[] = [];
|
|
22
|
+
let count = 0;
|
|
23
|
+
for (const element of arg.elements()) {
|
|
24
|
+
count += 1;
|
|
25
|
+
const result = of.parse(element, ctx);
|
|
26
|
+
if (result.ok) parsed.push({ node: element, value: result.value });
|
|
27
|
+
else diagnostics.push(...result.failure);
|
|
28
|
+
}
|
|
29
|
+
if (opts?.nonEmpty === true && count === 0) {
|
|
30
|
+
diagnostics.push(leafDiagnostic(ctx, arg, 'Expected a non-empty list'));
|
|
31
|
+
}
|
|
32
|
+
if (opts?.unique === true) {
|
|
33
|
+
const seen = new Set<T>();
|
|
34
|
+
for (const { node, value } of parsed) {
|
|
35
|
+
if (seen.has(value)) diagnostics.push(leafDiagnostic(ctx, node, 'Duplicate list entry'));
|
|
36
|
+
else seen.add(value);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (diagnostics.length > 0) return notOk(diagnostics);
|
|
40
|
+
return ok(parsed.map((entry) => entry.value));
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
3
|
+
import { NumberLiteralExprAst } from '../../syntax/ast/expressions';
|
|
4
|
+
import type { ArgType } from '../types';
|
|
5
|
+
import { leafDiagnostic } from './diagnostic';
|
|
6
|
+
|
|
7
|
+
// A general number literal — any number, including floats — reduced to its numeric value.
|
|
8
|
+
// Passing `value` pins the combinator to that single literal (`num(4)` matches only `4`),
|
|
9
|
+
// mirroring how `identifier(name)` pins a bare identifier. Use `int()` when only integer
|
|
10
|
+
// literals are allowed.
|
|
11
|
+
export function num(): ArgType<number>;
|
|
12
|
+
export function num(value: number): ArgType<number>;
|
|
13
|
+
export function num(value?: number): ArgType<number> {
|
|
14
|
+
return {
|
|
15
|
+
kind: 'num',
|
|
16
|
+
label: value === undefined ? 'number' : String(value),
|
|
17
|
+
parse: (arg, ctx): Result<number, readonly PslDiagnostic[]> => {
|
|
18
|
+
if (arg instanceof NumberLiteralExprAst) {
|
|
19
|
+
const parsed = arg.value();
|
|
20
|
+
if (parsed !== undefined && (value === undefined || parsed === value)) return ok(parsed);
|
|
21
|
+
}
|
|
22
|
+
const message = value === undefined ? 'Expected a number literal' : `Expected ${value}`;
|
|
23
|
+
return notOk([leafDiagnostic(ctx, arg, message)]);
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { blindCast } from '@prisma-next/utils/casts';
|
|
3
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
4
|
+
import type { ArgType, OutOf } from '../types';
|
|
5
|
+
import { leafDiagnostic } from './diagnostic';
|
|
6
|
+
|
|
7
|
+
export function oneOf<Alts extends readonly [ArgType<unknown>, ...ArgType<unknown>[]]>(
|
|
8
|
+
...alts: Alts
|
|
9
|
+
): ArgType<OutOf<Alts[number]>> {
|
|
10
|
+
const label = alts.map((alt) => alt.label).join(' | ');
|
|
11
|
+
return {
|
|
12
|
+
kind: 'oneOf',
|
|
13
|
+
label,
|
|
14
|
+
parse: (arg, ctx): Result<OutOf<Alts[number]>, readonly PslDiagnostic[]> => {
|
|
15
|
+
for (const alt of alts) {
|
|
16
|
+
const result = alt.parse(arg, ctx);
|
|
17
|
+
if (result.ok) {
|
|
18
|
+
return ok(
|
|
19
|
+
blindCast<
|
|
20
|
+
OutOf<Alts[number]>,
|
|
21
|
+
'The matched value comes from an alternative whose output type is a member of the union, but iterating the tuple widens each element to ArgType<unknown>, erasing that relationship.'
|
|
22
|
+
>(result.value),
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return notOk([leafDiagnostic(ctx, arg, `Expected one of: ${label}`)]);
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { PslDiagnostic } from '@prisma-next/framework-components/psl-ast';
|
|
2
|
+
import { notOk, ok, type Result } from '@prisma-next/utils/result';
|
|
3
|
+
import { ObjectLiteralExprAst } from '../../syntax/ast/expressions';
|
|
4
|
+
import type { ArgType } from '../types';
|
|
5
|
+
import { leafDiagnostic } from './diagnostic';
|
|
6
|
+
|
|
7
|
+
export function record<T>(of: ArgType<T>): ArgType<Record<string, T>> {
|
|
8
|
+
return {
|
|
9
|
+
kind: 'record',
|
|
10
|
+
label: `{ [key]: ${of.label} }`,
|
|
11
|
+
parse: (arg, ctx): Result<Record<string, T>, readonly PslDiagnostic[]> => {
|
|
12
|
+
if (!(arg instanceof ObjectLiteralExprAst)) {
|
|
13
|
+
return notOk([leafDiagnostic(ctx, arg, 'Expected an object literal')]);
|
|
14
|
+
}
|
|
15
|
+
const diagnostics: PslDiagnostic[] = [];
|
|
16
|
+
const result: Record<string, T> = {};
|
|
17
|
+
for (const field of arg.fields()) {
|
|
18
|
+
const key = field.keyName();
|
|
19
|
+
if (key === undefined) {
|
|
20
|
+
diagnostics.push(leafDiagnostic(ctx, field, 'Expected a key'));
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
const value = field.value();
|
|
24
|
+
if (value === undefined) {
|
|
25
|
+
diagnostics.push(leafDiagnostic(ctx, field, `Expected a value for key "${key}"`));
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const parsed = of.parse(value, ctx);
|
|
29
|
+
if (!parsed.ok) {
|
|
30
|
+
diagnostics.push(...parsed.failure);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (Object.hasOwn(result, key)) {
|
|
34
|
+
diagnostics.push(leafDiagnostic(ctx, field, `Duplicate key "${key}"`));
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
result[key] = parsed.value;
|
|
38
|
+
}
|
|
39
|
+
if (diagnostics.length > 0) return notOk(diagnostics);
|
|
40
|
+
return ok(result);
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|