@lokascript/framework 2.8.0 → 2.9.1
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/CHANGELOG.md +393 -0
- package/dist/api/create-dsl.d.ts +93 -1
- package/dist/api/create-dsl.d.ts.map +1 -1
- package/dist/api/domain-registry.d.ts +5 -3
- package/dist/api/domain-registry.d.ts.map +1 -1
- package/dist/api/index.js +232 -18
- package/dist/api/index.js.map +1 -1
- package/dist/core/index.js +26 -6
- package/dist/core/index.js.map +1 -1
- package/dist/core/tokenization/base-tokenizer.d.ts +15 -3
- package/dist/core/tokenization/base-tokenizer.d.ts.map +1 -1
- package/dist/core/tokenization/char-classifiers.d.ts +2 -2
- package/dist/core/tokenization/index.js +26 -6
- package/dist/core/tokenization/index.js.map +1 -1
- package/dist/core/tokenization/token-utils.d.ts +15 -0
- package/dist/core/tokenization/token-utils.d.ts.map +1 -1
- package/dist/generation/index.js +73 -47
- package/dist/generation/index.js.map +1 -1
- package/dist/generation/pattern-generator.d.ts +8 -1
- package/dist/generation/pattern-generator.d.ts.map +1 -1
- package/dist/generation/renderer.d.ts +53 -1
- package/dist/generation/renderer.d.ts.map +1 -1
- package/dist/index.cjs +302 -115
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +298 -115
- package/dist/index.js.map +1 -1
- package/dist/interfaces/value-extractor.d.ts +5 -0
- package/dist/interfaces/value-extractor.d.ts.map +1 -1
- package/dist/multilingual/index.js +25 -6
- package/dist/multilingual/index.js.map +1 -1
- package/package.json +4 -3
- package/src/api/create-dsl.test.ts +11 -0
- package/src/api/create-dsl.ts +278 -9
- package/src/api/domain-registry.ts +15 -10
- package/src/api/extensions.test.ts +322 -0
- package/src/core/tokenization/base-tokenizer.ts +23 -8
- package/src/core/tokenization/char-classifiers.ts +2 -2
- package/src/core/tokenization/css-selector-extractor.test.ts +67 -0
- package/src/core/tokenization/token-utils.ts +18 -0
- package/src/generation/domain-renderer.test.ts +172 -0
- package/src/generation/pattern-generator.test.ts +102 -0
- package/src/generation/pattern-generator.ts +27 -19
- package/src/generation/renderer.test.ts +243 -4
- package/src/generation/renderer.ts +188 -45
- package/src/index.ts +9 -1
- package/src/interfaces/value-extractor.ts +50 -0
|
@@ -100,6 +100,21 @@ export declare function isQuote(char: string): boolean;
|
|
|
100
100
|
* Check if a character is a digit.
|
|
101
101
|
*/
|
|
102
102
|
export declare function isDigit(char: string): boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Strip diacritical marks that are OPTIONAL in their script — currently Arabic
|
|
105
|
+
* harakat (U+064B–U+0652: fatha, kasra, damma, sukun, shadda…) and the
|
|
106
|
+
* superscript alif (U+0670).
|
|
107
|
+
*
|
|
108
|
+
* `بدّل` and `بَدِّل` are the same word; Arabic prose writes either. So any place
|
|
109
|
+
* that compares an Arabic surface form against a declared keyword has to compare
|
|
110
|
+
* stripped, or the same word fails to match itself.
|
|
111
|
+
*
|
|
112
|
+
* Deliberately Arabic-only. Latin diacritics are NOT optional — `obtén`, `récupère`
|
|
113
|
+
* and `vá` differ from their unaccented spellings in meaning or validity — and
|
|
114
|
+
* Hebrew niqqud (U+05B0–U+05BC) is out of range too, so this is inert for every
|
|
115
|
+
* other script.
|
|
116
|
+
*/
|
|
117
|
+
export declare function stripOptionalDiacritics(word: string): string;
|
|
103
118
|
/**
|
|
104
119
|
* Check if a character is an ASCII letter.
|
|
105
120
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-utils.d.ts","sourceRoot":"","sources":["../../../src/core/tokenization/token-utils.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"token-utils.d.ts","sourceRoot":"","sources":["../../../src/core/tokenization/token-utils.ts"],"names":[],"mappings":"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"}
|
package/dist/generation/index.js
CHANGED
|
@@ -39,10 +39,12 @@ function buildTokens(schema, profile, keyword, alternatives) {
|
|
|
39
39
|
addRoleWithMarker(tokens, role, profile);
|
|
40
40
|
}
|
|
41
41
|
} else if (profile.wordOrder === "SOV") {
|
|
42
|
+
const preVerb = [];
|
|
43
|
+
const postVerb = [];
|
|
42
44
|
for (const role of sortedRoles) {
|
|
43
|
-
addRoleWithMarker(
|
|
45
|
+
addRoleWithMarker(role.sovSlot === "postVerb" ? postVerb : preVerb, role, profile);
|
|
44
46
|
}
|
|
45
|
-
tokens.push(keywordToken);
|
|
47
|
+
tokens.push(...preVerb, keywordToken, ...postVerb);
|
|
46
48
|
} else if (profile.wordOrder === "VSO") {
|
|
47
49
|
tokens.push(keywordToken);
|
|
48
50
|
for (const role of sortedRoles) {
|
|
@@ -125,29 +127,28 @@ function buildExtractionRules(schema, profile) {
|
|
|
125
127
|
return rules;
|
|
126
128
|
}
|
|
127
129
|
function buildFormatString(schema, profile, keyword) {
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
130
|
+
const isSOV = profile.wordOrder === "SOV";
|
|
131
|
+
const preVerb = [];
|
|
132
|
+
const postVerb = [];
|
|
132
133
|
const sortedRoles = sortRolesByWordOrder(schema.roles, profile.wordOrder);
|
|
133
134
|
for (const role of sortedRoles) {
|
|
134
135
|
const marker = getMarkerForRole(role, profile);
|
|
135
136
|
const roleName = `{${role.role}}`;
|
|
137
|
+
const bucket = isSOV && role.sovSlot === "postVerb" ? postVerb : preVerb;
|
|
136
138
|
if (marker) {
|
|
137
139
|
const markerInfo = profile.roleMarkers?.[role.role];
|
|
138
140
|
if (markerInfo?.position === "after") {
|
|
139
|
-
|
|
141
|
+
bucket.push(`${roleName} ${marker}`);
|
|
140
142
|
} else {
|
|
141
|
-
|
|
143
|
+
bucket.push(`${marker} ${roleName}`);
|
|
142
144
|
}
|
|
143
145
|
} else {
|
|
144
|
-
|
|
146
|
+
bucket.push(roleName);
|
|
145
147
|
}
|
|
146
148
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
return parts.join(" ");
|
|
149
|
+
return (isSOV ? [...preVerb, keyword, ...postVerb] : [keyword, ...preVerb, ...postVerb]).join(
|
|
150
|
+
" "
|
|
151
|
+
);
|
|
151
152
|
}
|
|
152
153
|
function generatePatternVariants(schema, profile, config = defaultConfig) {
|
|
153
154
|
const patterns = [];
|
|
@@ -226,44 +227,67 @@ function detectWordOrders(profiles) {
|
|
|
226
227
|
return { sovLanguages, vsoLanguages };
|
|
227
228
|
}
|
|
228
229
|
function createSchemaRenderer(schemas, profiles) {
|
|
230
|
+
const tables = buildRenderTables(schemas, profiles);
|
|
231
|
+
return {
|
|
232
|
+
render(node, language) {
|
|
233
|
+
return renderFromSchema(node, language, tables) ?? node.action;
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function createDomainRenderer(config) {
|
|
238
|
+
const { schemas, profiles, overrides } = config;
|
|
239
|
+
let tables;
|
|
240
|
+
return (node, language) => {
|
|
241
|
+
const override = overrides?.[node.action];
|
|
242
|
+
if (override) return override(node, language);
|
|
243
|
+
tables ?? (tables = buildRenderTables(schemas, profiles));
|
|
244
|
+
return renderFromSchema(node, language, tables);
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
function buildRenderTables(schemas, profiles) {
|
|
229
248
|
const { keywords, markers } = buildTablesFromProfiles(schemas, profiles);
|
|
230
249
|
const { sovLanguages } = detectWordOrders(profiles);
|
|
250
|
+
const markerPositions = {};
|
|
251
|
+
for (const profile of profiles) {
|
|
252
|
+
for (const [role, markerDef] of Object.entries(profile.roleMarkers ?? {})) {
|
|
253
|
+
if (!markerDef.position) continue;
|
|
254
|
+
markerPositions[role] ?? (markerPositions[role] = {});
|
|
255
|
+
markerPositions[role][profile.code] = markerDef.position;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
231
258
|
const schemaMap = /* @__PURE__ */ new Map();
|
|
232
259
|
for (const s of schemas) schemaMap.set(s.action, s);
|
|
233
|
-
return {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
role
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
const parts = [];
|
|
251
|
-
if (isSOV) {
|
|
252
|
-
for (const rp of roleParts) {
|
|
253
|
-
if (rp.value) parts.push(rp.value);
|
|
254
|
-
if (rp.marker) parts.push(rp.marker);
|
|
255
|
-
}
|
|
256
|
-
parts.push(keyword);
|
|
257
|
-
} else {
|
|
258
|
-
parts.push(keyword);
|
|
259
|
-
for (const rp of roleParts) {
|
|
260
|
-
if (rp.marker) parts.push(rp.marker);
|
|
261
|
-
if (rp.value) parts.push(rp.value);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
return buildPhrase(...parts);
|
|
260
|
+
return { keywords, markers, markerPositions, sovLanguages, schemaMap };
|
|
261
|
+
}
|
|
262
|
+
function renderFromSchema(node, language, tables) {
|
|
263
|
+
const schema = tables.schemaMap.get(node.action);
|
|
264
|
+
if (!schema) return null;
|
|
265
|
+
const keyword = lookupKeyword(tables.keywords, node.action, language);
|
|
266
|
+
const isSOV = tables.sovLanguages.has(language);
|
|
267
|
+
const ordered = sortRolesByWordOrder([...schema.roles], isSOV ? "SOV" : "SVO");
|
|
268
|
+
const preVerb = [];
|
|
269
|
+
const postVerb = [];
|
|
270
|
+
for (const role of ordered) {
|
|
271
|
+
let value = extractRoleValue(node, role.role);
|
|
272
|
+
if (!value && role.default !== void 0) {
|
|
273
|
+
value = String(extractValue(role.default));
|
|
265
274
|
}
|
|
266
|
-
|
|
275
|
+
if (!value) continue;
|
|
276
|
+
if (role.quoteMultiword && /\s/.test(value) && !/^(["']).*\1$/.test(value)) {
|
|
277
|
+
value = `"${value}"`;
|
|
278
|
+
}
|
|
279
|
+
const markerText = role.renderOverride?.[language] ?? role.markerOverride?.[language] ?? role.renderOverride?.["*"] ?? tables.markers[role.role]?.[language];
|
|
280
|
+
const markerPosition = role.markerPositionOverride?.[language] ?? role.markerPosition ?? tables.markerPositions[role.role]?.[language] ?? (isSOV ? "after" : "before");
|
|
281
|
+
const bucket = isSOV && role.sovSlot === "postVerb" ? postVerb : preVerb;
|
|
282
|
+
if (markerText && markerPosition === "before") {
|
|
283
|
+
bucket.push(markerText, value);
|
|
284
|
+
} else if (markerText) {
|
|
285
|
+
bucket.push(value, markerText);
|
|
286
|
+
} else {
|
|
287
|
+
bucket.push(value);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return isSOV ? buildPhrase(...preVerb, keyword, ...postVerb) : buildPhrase(keyword, ...preVerb, ...postVerb);
|
|
267
291
|
}
|
|
268
292
|
|
|
269
293
|
// src/generation/diagnostics.ts
|
|
@@ -272,6 +296,7 @@ export {
|
|
|
272
296
|
buildPhrase,
|
|
273
297
|
buildTablesFromProfiles,
|
|
274
298
|
createDiagnosticCollector,
|
|
299
|
+
createDomainRenderer,
|
|
275
300
|
createSchemaRenderer,
|
|
276
301
|
detectWordOrders,
|
|
277
302
|
filterBySeverity,
|
|
@@ -279,6 +304,7 @@ export {
|
|
|
279
304
|
generatePattern,
|
|
280
305
|
generatePatternVariants,
|
|
281
306
|
lookupKeyword,
|
|
282
|
-
lookupMarker
|
|
307
|
+
lookupMarker,
|
|
308
|
+
sortRolesByWordOrder
|
|
283
309
|
};
|
|
284
310
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/generation/pattern-generator.ts","../../src/core/types.ts","../../src/generation/renderer.ts","../../src/generation/diagnostics.ts"],"sourcesContent":["/**\n * Pattern Generator\n *\n * Generates LanguagePattern objects from CommandSchema + LanguageProfile.\n * This solves the pattern explosion problem by deriving patterns from\n * high-level schema definitions rather than hand-writing each one.\n */\n\nimport type { LanguagePattern, PatternToken, ExtractionRule } from '../core/types';\nimport type { CommandSchema, RoleSpec } from '../schema';\n\n/**\n * Minimal language profile interface for pattern generation.\n */\nexport interface PatternGenLanguageProfile {\n readonly code: string;\n readonly wordOrder: 'SVO' | 'SOV' | 'VSO' | 'VOS' | 'OSV' | 'OVS' | 'free';\n readonly keywords: Record<string, { primary: string; alternatives?: string[] }>;\n readonly roleMarkers?: Record<\n string,\n { primary: string; alternatives?: string[]; position?: 'before' | 'after' }\n >;\n}\n\n/**\n * Configuration for pattern generation.\n */\nexport interface GeneratorConfig {\n /** Base priority for generated patterns (default: 100) */\n readonly basePriority?: number;\n /** Include optional role variants (default: true) */\n readonly includeOptionalVariants?: boolean;\n}\n\nconst defaultConfig: GeneratorConfig = {\n basePriority: 100,\n includeOptionalVariants: true,\n};\n\n/**\n * Generate a language pattern from a command schema and language profile.\n *\n * @param schema - Command schema defining the command structure\n * @param profile - Language profile with word order and keywords\n * @param config - Optional configuration\n * @returns Generated language pattern\n */\nexport function generatePattern(\n schema: CommandSchema,\n profile: PatternGenLanguageProfile,\n config: GeneratorConfig = defaultConfig\n): LanguagePattern {\n const id = `${schema.action}-${profile.code}-generated`;\n const priority = config.basePriority ?? 100;\n\n // Get keyword translation\n const keyword = profile.keywords[schema.action];\n if (!keyword) {\n throw new Error(`No keyword translation for '${schema.action}' in ${profile.code}`);\n }\n\n // Build tokens based on word order\n const tokens = buildTokens(schema, profile, keyword.primary, keyword.alternatives);\n\n // Build extraction rules\n const extraction = buildExtractionRules(schema, profile);\n\n // Build format string for documentation\n const format = buildFormatString(schema, profile, keyword.primary);\n\n return {\n id,\n language: profile.code,\n command: schema.action,\n priority,\n template: {\n format,\n tokens,\n },\n extraction,\n };\n}\n\n/**\n * Build pattern tokens based on word order and role markers.\n */\nfunction buildTokens(\n schema: CommandSchema,\n profile: PatternGenLanguageProfile,\n keyword: string,\n alternatives?: string[]\n): PatternToken[] {\n const tokens: PatternToken[] = [];\n const keywordToken: PatternToken = {\n type: 'literal',\n value: keyword,\n ...(alternatives?.length && { alternatives }),\n };\n\n // Sort roles by word order\n const sortedRoles = sortRolesByWordOrder(schema.roles, profile.wordOrder);\n\n // For SVO: [action, patient, destination, source, ...]\n if (profile.wordOrder === 'SVO') {\n // Add keyword first\n tokens.push(keywordToken);\n\n // Add roles with markers\n for (const role of sortedRoles) {\n addRoleWithMarker(tokens, role, profile);\n }\n }\n // For SOV: [patient, destination, source, ..., action]\n else if (profile.wordOrder === 'SOV') {\n // Add roles with markers first\n for (const role of sortedRoles) {\n addRoleWithMarker(tokens, role, profile);\n }\n\n // Add keyword last\n tokens.push(keywordToken);\n }\n // For VSO: [action, destination, patient, source, ...]\n else if (profile.wordOrder === 'VSO') {\n // Add keyword first\n tokens.push(keywordToken);\n\n // Add roles with markers\n for (const role of sortedRoles) {\n addRoleWithMarker(tokens, role, profile);\n }\n }\n // Other word orders can be added as needed\n else {\n // Fallback to SVO-style ordering\n tokens.push(keywordToken);\n for (const role of sortedRoles) {\n addRoleWithMarker(tokens, role, profile);\n }\n }\n\n return tokens;\n}\n\n/**\n * Add a role token with its grammatical marker if needed.\n * For optional roles, wraps the role + marker in a group.\n */\nfunction addRoleWithMarker(\n tokens: PatternToken[],\n roleSpec: RoleSpec,\n profile: PatternGenLanguageProfile\n): void {\n const marker = getMarkerForRole(roleSpec, profile);\n const isOptional = !roleSpec.required;\n\n // Build the role token\n const roleToken: PatternToken = {\n type: 'role',\n role: roleSpec.role,\n optional: isOptional,\n expectedTypes: roleSpec.expectedTypes,\n ...(roleSpec.greedy && { greedy: true }),\n };\n\n if (marker) {\n const markerInfo = profile.roleMarkers?.[roleSpec.role];\n // Priority: schema markerPosition → profile roleMarkers position → word-order default\n const defaultPosition = profile.wordOrder === 'SOV' ? 'after' : 'before';\n const position = roleSpec.markerPosition ?? markerInfo?.position ?? defaultPosition;\n\n if (isOptional) {\n // Optional role: wrap marker + role in optional group\n if (position === 'before') {\n tokens.push({\n type: 'group',\n optional: true,\n tokens: [{ type: 'literal', value: marker }, roleToken],\n });\n } else {\n tokens.push({\n type: 'group',\n optional: true,\n tokens: [roleToken, { type: 'literal', value: marker }],\n });\n }\n } else {\n // Required role: add marker + role separately\n if (position === 'before') {\n tokens.push({ type: 'literal', value: marker });\n tokens.push(roleToken);\n } else {\n tokens.push(roleToken);\n tokens.push({ type: 'literal', value: marker });\n }\n }\n } else {\n // No marker - just add the role\n tokens.push(roleToken);\n }\n}\n\n/**\n * Get the grammatical marker for a role from the profile.\n */\nfunction getMarkerForRole(\n roleSpec: RoleSpec,\n profile: PatternGenLanguageProfile\n): string | undefined {\n // Check for role-specific override first\n if (roleSpec.markerOverride?.[profile.code]) {\n return roleSpec.markerOverride[profile.code];\n }\n\n // Use profile's default marker for this role\n return profile.roleMarkers?.[roleSpec.role]?.primary;\n}\n\n/**\n * Sort roles by word order for pattern building.\n */\nfunction sortRolesByWordOrder(roles: RoleSpec[], wordOrder: string): RoleSpec[] {\n const sorted = [...roles];\n\n if (wordOrder === 'SVO') {\n // Sort by svoPosition (higher = earlier)\n sorted.sort((a, b) => (b.svoPosition ?? 0) - (a.svoPosition ?? 0));\n } else if (wordOrder === 'SOV') {\n // Sort by sovPosition (higher = earlier)\n sorted.sort((a, b) => (b.sovPosition ?? 0) - (a.sovPosition ?? 0));\n }\n // VSO and others use SVO-style ordering\n\n return sorted;\n}\n\n/**\n * Build extraction rules for capturing role values during parsing.\n */\nfunction buildExtractionRules(\n schema: CommandSchema,\n profile: PatternGenLanguageProfile\n): Record<string, ExtractionRule> {\n const rules: Record<string, ExtractionRule> = {};\n\n for (const roleSpec of schema.roles) {\n // Build the rule object correctly with readonly properties\n const marker = getMarkerForRole(roleSpec, profile);\n\n const rule: ExtractionRule = {\n ...(roleSpec.default !== undefined && { default: roleSpec.default }),\n ...(marker && { marker }),\n };\n\n rules[roleSpec.role] = rule;\n }\n\n return rules;\n}\n\n/**\n * Build a human-readable format string for the pattern.\n */\nfunction buildFormatString(\n schema: CommandSchema,\n profile: PatternGenLanguageProfile,\n keyword: string\n): string {\n const parts: string[] = [];\n\n if (profile.wordOrder === 'SVO' || profile.wordOrder === 'VSO') {\n parts.push(keyword);\n }\n\n // Order roles the same way buildTokens does (descending position). Iterating\n // declaration order here would disagree with the token order whenever a\n // schema's roles are declared in a different order than their positions imply.\n const sortedRoles = sortRolesByWordOrder(schema.roles, profile.wordOrder);\n for (const role of sortedRoles) {\n const marker = getMarkerForRole(role, profile);\n const roleName = `{${role.role}}`;\n\n if (marker) {\n const markerInfo = profile.roleMarkers?.[role.role];\n if (markerInfo?.position === 'after') {\n parts.push(`${roleName} ${marker}`);\n } else {\n parts.push(`${marker} ${roleName}`);\n }\n } else {\n parts.push(roleName);\n }\n }\n\n if (profile.wordOrder === 'SOV') {\n parts.push(keyword);\n }\n\n return parts.join(' ');\n}\n\n/**\n * Generate multiple pattern variants (with and without optional roles).\n */\nexport function generatePatternVariants(\n schema: CommandSchema,\n profile: PatternGenLanguageProfile,\n config: GeneratorConfig = defaultConfig\n): LanguagePattern[] {\n const patterns: LanguagePattern[] = [];\n\n // Main pattern (all roles)\n patterns.push(generatePattern(schema, profile, config));\n\n // TODO: Generate variants with optional roles omitted\n // This can be added later when needed\n\n return patterns;\n}\n","/**\n * Core Types — re-exported from @lokascript/intent + framework-specific extensions\n *\n * The universal semantic types (SemanticNode, SemanticValue, etc.) now live in\n * @lokascript/intent and are re-exported here for backward compatibility.\n *\n * Framework-specific types (tokenization, pattern matching) are defined below.\n */\n\n// =============================================================================\n// Re-export everything from @lokascript/intent\n// =============================================================================\n\nexport type {\n ActionType,\n SemanticRole,\n SemanticValue,\n ExpectedType,\n LiteralValue,\n SelectorValue,\n ReferenceValue,\n PropertyPathValue,\n ExpressionValue,\n FlagValue,\n Annotation,\n ProtocolDiagnostic,\n AsyncVariant,\n MatchArm,\n SemanticNode,\n SemanticMetadata,\n SourcePosition,\n CommandSemanticNode,\n EventHandlerSemanticNode,\n EventModifiers,\n ConditionalSemanticNode,\n CompoundSemanticNode,\n LoopVariant,\n LoopSemanticNode,\n LSEEnvelope,\n} from '@lokascript/intent';\n\nexport {\n createLiteral,\n createSelector,\n createReference,\n createPropertyPath,\n createExpression,\n createFlag,\n createCommandNode,\n createEventHandlerNode,\n createConditionalNode,\n createCompoundNode,\n createLoopNode,\n createTryNode,\n createAsyncNode,\n createMatchNode,\n extractValue,\n extractRoleValue,\n getRoleValue,\n} from '@lokascript/intent';\n\n// =============================================================================\n// Framework-specific types (multilingual DSL infrastructure)\n// =============================================================================\n\nimport type {\n ActionType,\n SemanticRole,\n SemanticValue,\n SelectorValue,\n ExpectedType,\n SourcePosition,\n} from '@lokascript/intent';\n\n/**\n * Token kind - categorizes what type of token this is.\n */\nexport type TokenKind =\n | 'keyword' // Command or modifier keyword\n | 'selector' // CSS selector or identifier (#id, .class, table-name)\n | 'literal' // String or number literal\n | 'particle' // Grammatical particle (を, に, من)\n | 'conjunction' // Grammatical conjunction\n | 'event-modifier' // Event modifier (.once, .debounce(300))\n | 'identifier' // Generic identifier\n | 'operator' // Operators (., +, -, etc.)\n | 'punctuation' // Punctuation (parentheses, etc.)\n | 'url'; // URL or path\n\n/**\n * A language token - the result of tokenization.\n */\nexport interface LanguageToken {\n readonly value: string;\n readonly kind: TokenKind;\n readonly position: SourcePosition;\n readonly normalized?: string;\n readonly stem?: string;\n readonly stemConfidence?: number;\n readonly metadata?: Record<string, unknown>;\n}\n\n/**\n * Token stream - provides sequential access to tokens with backtracking.\n */\nexport interface TokenStream {\n readonly tokens: readonly LanguageToken[];\n readonly language: string;\n peek(offset?: number): LanguageToken | null;\n advance(): LanguageToken;\n isAtEnd(): boolean;\n mark(): StreamMark;\n reset(mark: StreamMark): void;\n position(): number;\n}\n\nexport interface StreamMark {\n readonly position: number;\n}\n\n/**\n * Language tokenizer interface - converts text to tokens.\n */\nexport interface LanguageTokenizer {\n readonly language: string;\n readonly direction: 'ltr' | 'rtl';\n tokenize(input: string): TokenStream;\n classifyToken(token: string): TokenKind;\n}\n\n// =============================================================================\n// Pattern Matching Types\n// =============================================================================\n\nexport interface LanguagePattern {\n readonly id: string;\n readonly language: string;\n readonly command: ActionType;\n readonly priority: number;\n readonly template: PatternTemplate;\n readonly extraction: ExtractionRules;\n readonly constraints?: PatternConstraints;\n}\n\nexport interface PatternTemplate {\n readonly format: string;\n readonly tokens: PatternToken[];\n}\n\nexport type PatternToken = LiteralPatternToken | RolePatternToken | GroupPatternToken;\n\nexport interface LiteralPatternToken {\n readonly type: 'literal';\n readonly value: string;\n readonly alternatives?: string[];\n}\n\nexport interface RolePatternToken {\n readonly type: 'role';\n readonly role: SemanticRole;\n readonly optional?: boolean;\n readonly expectedTypes?: Array<ExpectedType>;\n readonly greedy?: boolean;\n}\n\nexport interface GroupPatternToken {\n readonly type: 'group';\n readonly tokens: PatternToken[];\n readonly optional?: boolean;\n}\n\nexport interface ExtractionRules {\n readonly [role: string]: ExtractionRule;\n}\n\nexport interface ExtractionRule {\n readonly position?: number;\n readonly marker?: string;\n readonly markerAlternatives?: string[];\n readonly transform?: (raw: string) => SemanticValue;\n readonly default?: SemanticValue;\n readonly value?: string;\n readonly fromRole?: string;\n}\n\nexport interface PatternConstraints {\n readonly requiredRoles?: SemanticRole[];\n readonly forbiddenRoles?: SemanticRole[];\n readonly validPatientTypes?: Array<SelectorValue['selectorKind']>;\n readonly conflictsWith?: string[];\n}\n\nexport interface PatternMatchResult {\n readonly pattern: LanguagePattern;\n readonly captured: ReadonlyMap<SemanticRole, SemanticValue>;\n readonly consumedTokens: number;\n readonly confidence: number;\n}\n\nexport interface PatternMatchError {\n readonly message: string;\n readonly position: SourcePosition;\n readonly expectedPatterns?: string[];\n readonly partialMatch?: Partial<PatternMatchResult>;\n}\n","/**\n * Natural Language Renderer\n *\n * Interface and utilities for rendering SemanticNode → human-readable text\n * in any supported language. This is the inverse of parsing: it converts\n * a language-neutral semantic representation back to natural-language syntax.\n *\n * Every domain that supports `translate()` needs a renderer.\n */\n\nimport type { SemanticNode } from '../core/types';\nimport { extractRoleValue } from '../core/types';\nimport type { CommandSchema, RoleSpec } from '../schema';\nimport type { PatternGenLanguageProfile } from './pattern-generator';\n\n// =============================================================================\n// Renderer Interface\n// =============================================================================\n\n/**\n * Renders a SemanticNode to human-readable text in a target language.\n */\nexport interface NaturalLanguageRenderer {\n render(node: SemanticNode, language: string): string;\n}\n\n// =============================================================================\n// Renderer Helpers\n// =============================================================================\n\n/**\n * Keyword table: action → language → translated keyword.\n *\n * @example\n * ```typescript\n * const KEYWORDS: KeywordTable = {\n * select: { en: 'select', ja: '選択', es: 'seleccionar' },\n * insert: { en: 'insert', ja: '挿入', es: 'insertar' },\n * };\n * ```\n */\nexport type KeywordTable = Record<string, Record<string, string>>;\n\n/**\n * Marker table: marker name → language → translated marker.\n *\n * @example\n * ```typescript\n * const MARKERS: MarkerTable = {\n * from: { en: 'from', ja: 'から', es: 'de' },\n * into: { en: 'into', ja: 'に', es: 'en' },\n * };\n * ```\n */\nexport type MarkerTable = Record<string, Record<string, string>>;\n\n/**\n * Configuration for building a renderer from schemas and profiles.\n */\nexport interface RendererConfig {\n /** Command keyword translations per language */\n readonly keywords: KeywordTable;\n\n /** Role marker translations per language (prepositions/particles) */\n readonly markers: MarkerTable;\n\n /** Languages that use SOV word order */\n readonly sovLanguages: ReadonlySet<string>;\n\n /** Languages that use VSO word order (optional, defaults to empty) */\n readonly vsoLanguages?: ReadonlySet<string>;\n}\n\n/**\n * Look up a command keyword in the target language.\n * Falls back to the key itself if no translation found.\n */\nexport function lookupKeyword(keywords: KeywordTable, action: string, language: string): string {\n return keywords[action]?.[language] ?? action;\n}\n\n/**\n * Look up a role marker in the target language.\n * Falls back to the key itself if no translation found.\n */\nexport function lookupMarker(markers: MarkerTable, marker: string, language: string): string {\n return markers[marker]?.[language] ?? marker;\n}\n\n/**\n * Build a phrase from parts, filtering empty strings and joining with space.\n *\n * @example\n * ```typescript\n * buildPhrase('select', '', 'name', 'from', 'users')\n * // → 'select name from users'\n * ```\n */\nexport function buildPhrase(...parts: string[]): string {\n return parts.filter(Boolean).join(' ');\n}\n\n/**\n * Build keyword and marker tables from schemas and language profiles.\n * Extracts translations from the profile's keyword definitions and\n * role marker overrides.\n *\n * @example\n * ```typescript\n * const { keywords, markers } = buildTablesFromProfiles(schemas, profiles);\n * ```\n */\nexport function buildTablesFromProfiles(\n schemas: readonly CommandSchema[],\n profiles: readonly PatternGenLanguageProfile[]\n): { keywords: KeywordTable; markers: MarkerTable } {\n const keywords: KeywordTable = {};\n const markers: MarkerTable = {};\n\n // Build keyword table from profiles\n for (const profile of profiles) {\n for (const [action, kw] of Object.entries(profile.keywords)) {\n if (!keywords[action]) keywords[action] = {};\n keywords[action][profile.code] = kw.primary;\n }\n }\n\n // Build marker table from schema markerOverrides\n for (const schema of schemas) {\n for (const role of schema.roles) {\n if (role.markerOverride) {\n // Use role name as marker key\n const markerKey = role.role;\n if (!markers[markerKey]) markers[markerKey] = {};\n for (const [lang, markerText] of Object.entries(role.markerOverride)) {\n markers[markerKey][lang] = markerText;\n }\n }\n }\n }\n\n // Also extract role markers from profiles\n for (const profile of profiles) {\n if (profile.roleMarkers) {\n for (const [markerKey, markerDef] of Object.entries(profile.roleMarkers)) {\n if (!markers[markerKey]) markers[markerKey] = {};\n markers[markerKey][profile.code] = markerDef.primary;\n }\n }\n }\n\n return { keywords, markers };\n}\n\n/**\n * Detect word order from language profiles.\n * Returns sets of SOV and VSO language codes.\n */\nexport function detectWordOrders(profiles: readonly PatternGenLanguageProfile[]): {\n sovLanguages: Set<string>;\n vsoLanguages: Set<string>;\n} {\n const sovLanguages = new Set<string>();\n const vsoLanguages = new Set<string>();\n\n for (const profile of profiles) {\n if (profile.wordOrder === 'SOV') sovLanguages.add(profile.code);\n if (profile.wordOrder === 'VSO') vsoLanguages.add(profile.code);\n }\n\n return { sovLanguages, vsoLanguages };\n}\n\n/**\n * Create a basic renderer from schemas and profiles.\n *\n * This generates a renderer that handles word-order reordering automatically.\n * For each command, it constructs the output by placing the keyword and\n * role values in the correct order for the target language.\n *\n * For complex domain-specific rendering, implement `NaturalLanguageRenderer`\n * directly instead.\n *\n * @example\n * ```typescript\n * const renderer = createSchemaRenderer(schemas, profiles);\n * renderer.render(node, 'ja'); // → \"users から name 選択\"\n * ```\n */\nexport function createSchemaRenderer(\n schemas: readonly CommandSchema[],\n profiles: readonly PatternGenLanguageProfile[]\n): NaturalLanguageRenderer {\n const { keywords, markers } = buildTablesFromProfiles(schemas, profiles);\n const { sovLanguages } = detectWordOrders(profiles);\n const schemaMap = new Map<string, CommandSchema>();\n for (const s of schemas) schemaMap.set(s.action, s);\n\n return {\n render(node: SemanticNode, language: string): string {\n const schema = schemaMap.get(node.action);\n if (!schema) return node.action;\n\n const keyword = lookupKeyword(keywords, node.action, language);\n const isSOV = sovLanguages.has(language);\n\n // Collect role parts in schema order\n const roleParts: Array<{ marker?: string; value: string; role: RoleSpec }> = [];\n for (const role of schema.roles) {\n const value = extractRoleValue(node, role.role);\n if (!value && !role.required) continue;\n\n const markerText =\n role.markerOverride?.[language] ?? markers[role.role]?.[language] ?? undefined;\n\n roleParts.push({\n ...(markerText != null && { marker: markerText }),\n value: value || '',\n role,\n });\n }\n\n const parts: string[] = [];\n\n if (isSOV) {\n // SOV: roles (with markers after values) then keyword\n for (const rp of roleParts) {\n if (rp.value) parts.push(rp.value);\n if (rp.marker) parts.push(rp.marker);\n }\n parts.push(keyword);\n } else {\n // SVO/VSO: keyword then roles (with markers before values)\n parts.push(keyword);\n for (const rp of roleParts) {\n if (rp.marker) parts.push(rp.marker);\n if (rp.value) parts.push(rp.value);\n }\n }\n\n return buildPhrase(...parts);\n },\n };\n}\n","/**\n * Structured Error Diagnostics\n *\n * Re-exported from @lokascript/intent.\n * This module is the framework's re-export point for the diagnostic types\n * that live in the universal intent package.\n */\n\nexport type {\n DiagnosticSeverity,\n Diagnostic,\n DiagnosticResult,\n DiagnosticSummary,\n DiagnosticCollector,\n DiagnosticOptions,\n} from '@lokascript/intent';\n\nexport { createDiagnosticCollector, fromError, filterBySeverity } from '@lokascript/intent';\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/generation/pattern-generator.ts","../../src/core/types.ts","../../src/generation/renderer.ts","../../src/generation/diagnostics.ts"],"sourcesContent":["/**\n * Pattern Generator\n *\n * Generates LanguagePattern objects from CommandSchema + LanguageProfile.\n * This solves the pattern explosion problem by deriving patterns from\n * high-level schema definitions rather than hand-writing each one.\n */\n\nimport type { LanguagePattern, PatternToken, ExtractionRule } from '../core/types';\nimport type { CommandSchema, RoleSpec } from '../schema';\n\n/**\n * Minimal language profile interface for pattern generation.\n */\nexport interface PatternGenLanguageProfile {\n readonly code: string;\n readonly wordOrder: 'SVO' | 'SOV' | 'VSO' | 'VOS' | 'OSV' | 'OVS' | 'free';\n readonly keywords: Record<string, { primary: string; alternatives?: string[] }>;\n readonly roleMarkers?: Record<\n string,\n { primary: string; alternatives?: string[]; position?: 'before' | 'after' }\n >;\n}\n\n/**\n * Configuration for pattern generation.\n */\nexport interface GeneratorConfig {\n /** Base priority for generated patterns (default: 100) */\n readonly basePriority?: number;\n /** Include optional role variants (default: true) */\n readonly includeOptionalVariants?: boolean;\n}\n\nconst defaultConfig: GeneratorConfig = {\n basePriority: 100,\n includeOptionalVariants: true,\n};\n\n/**\n * Generate a language pattern from a command schema and language profile.\n *\n * @param schema - Command schema defining the command structure\n * @param profile - Language profile with word order and keywords\n * @param config - Optional configuration\n * @returns Generated language pattern\n */\nexport function generatePattern(\n schema: CommandSchema,\n profile: PatternGenLanguageProfile,\n config: GeneratorConfig = defaultConfig\n): LanguagePattern {\n const id = `${schema.action}-${profile.code}-generated`;\n const priority = config.basePriority ?? 100;\n\n // Get keyword translation\n const keyword = profile.keywords[schema.action];\n if (!keyword) {\n throw new Error(`No keyword translation for '${schema.action}' in ${profile.code}`);\n }\n\n // Build tokens based on word order\n const tokens = buildTokens(schema, profile, keyword.primary, keyword.alternatives);\n\n // Build extraction rules\n const extraction = buildExtractionRules(schema, profile);\n\n // Build format string for documentation\n const format = buildFormatString(schema, profile, keyword.primary);\n\n return {\n id,\n language: profile.code,\n command: schema.action,\n priority,\n template: {\n format,\n tokens,\n },\n extraction,\n };\n}\n\n/**\n * Build pattern tokens based on word order and role markers.\n */\nfunction buildTokens(\n schema: CommandSchema,\n profile: PatternGenLanguageProfile,\n keyword: string,\n alternatives?: string[]\n): PatternToken[] {\n const tokens: PatternToken[] = [];\n const keywordToken: PatternToken = {\n type: 'literal',\n value: keyword,\n ...(alternatives?.length && { alternatives }),\n };\n\n // Sort roles by word order\n const sortedRoles = sortRolesByWordOrder(schema.roles, profile.wordOrder);\n\n // For SVO: [action, patient, destination, source, ...]\n if (profile.wordOrder === 'SVO') {\n // Add keyword first\n tokens.push(keywordToken);\n\n // Add roles with markers\n for (const role of sortedRoles) {\n addRoleWithMarker(tokens, role, profile);\n }\n }\n // For SOV: [patient, destination, source, ..., action, postVerb roles...]\n else if (profile.wordOrder === 'SOV') {\n // `sovSlot: 'postVerb'` moves a role AFTER the verb, which is what the\n // renderer does (`renderer.ts` buckets by the same field). Generation has\n // to mirror it: a role the renderer writes post-verb but the pattern\n // expects pre-verb produces a faithful surface its own parser drops the\n // argument from — voice's `戻る 2` re-parsing as a bare `back`.\n const preVerb: PatternToken[] = [];\n const postVerb: PatternToken[] = [];\n\n for (const role of sortedRoles) {\n addRoleWithMarker(role.sovSlot === 'postVerb' ? postVerb : preVerb, role, profile);\n }\n\n tokens.push(...preVerb, keywordToken, ...postVerb);\n }\n // For VSO: [action, destination, patient, source, ...]\n else if (profile.wordOrder === 'VSO') {\n // Add keyword first\n tokens.push(keywordToken);\n\n // Add roles with markers\n for (const role of sortedRoles) {\n addRoleWithMarker(tokens, role, profile);\n }\n }\n // Other word orders can be added as needed\n else {\n // Fallback to SVO-style ordering\n tokens.push(keywordToken);\n for (const role of sortedRoles) {\n addRoleWithMarker(tokens, role, profile);\n }\n }\n\n return tokens;\n}\n\n/**\n * Add a role token with its grammatical marker if needed.\n * For optional roles, wraps the role + marker in a group.\n */\nfunction addRoleWithMarker(\n tokens: PatternToken[],\n roleSpec: RoleSpec,\n profile: PatternGenLanguageProfile\n): void {\n const marker = getMarkerForRole(roleSpec, profile);\n const isOptional = !roleSpec.required;\n\n // Build the role token\n const roleToken: PatternToken = {\n type: 'role',\n role: roleSpec.role,\n optional: isOptional,\n expectedTypes: roleSpec.expectedTypes,\n ...(roleSpec.greedy && { greedy: true }),\n };\n\n if (marker) {\n const markerInfo = profile.roleMarkers?.[roleSpec.role];\n // Priority: schema markerPosition → profile roleMarkers position → word-order default\n const defaultPosition = profile.wordOrder === 'SOV' ? 'after' : 'before';\n const position = roleSpec.markerPosition ?? markerInfo?.position ?? defaultPosition;\n\n if (isOptional) {\n // Optional role: wrap marker + role in optional group\n if (position === 'before') {\n tokens.push({\n type: 'group',\n optional: true,\n tokens: [{ type: 'literal', value: marker }, roleToken],\n });\n } else {\n tokens.push({\n type: 'group',\n optional: true,\n tokens: [roleToken, { type: 'literal', value: marker }],\n });\n }\n } else {\n // Required role: add marker + role separately\n if (position === 'before') {\n tokens.push({ type: 'literal', value: marker });\n tokens.push(roleToken);\n } else {\n tokens.push(roleToken);\n tokens.push({ type: 'literal', value: marker });\n }\n }\n } else {\n // No marker - just add the role\n tokens.push(roleToken);\n }\n}\n\n/**\n * Get the grammatical marker for a role from the profile.\n */\nfunction getMarkerForRole(\n roleSpec: RoleSpec,\n profile: PatternGenLanguageProfile\n): string | undefined {\n // Check for role-specific override first\n if (roleSpec.markerOverride?.[profile.code]) {\n return roleSpec.markerOverride[profile.code];\n }\n\n // Use profile's default marker for this role\n return profile.roleMarkers?.[roleSpec.role]?.primary;\n}\n\n/**\n * Sort roles by word order for pattern building.\n *\n * Exported so the renderer sorts with exactly this comparator — a rendered\n * surface whose role order differs from the generated pattern would not re-parse.\n */\nexport function sortRolesByWordOrder(roles: RoleSpec[], wordOrder: string): RoleSpec[] {\n const sorted = [...roles];\n\n if (wordOrder === 'SVO') {\n // Sort by svoPosition (higher = earlier)\n sorted.sort((a, b) => (b.svoPosition ?? 0) - (a.svoPosition ?? 0));\n } else if (wordOrder === 'SOV') {\n // Sort by sovPosition (higher = earlier)\n sorted.sort((a, b) => (b.sovPosition ?? 0) - (a.sovPosition ?? 0));\n }\n // VSO and others use SVO-style ordering\n\n return sorted;\n}\n\n/**\n * Build extraction rules for capturing role values during parsing.\n */\nfunction buildExtractionRules(\n schema: CommandSchema,\n profile: PatternGenLanguageProfile\n): Record<string, ExtractionRule> {\n const rules: Record<string, ExtractionRule> = {};\n\n for (const roleSpec of schema.roles) {\n // Build the rule object correctly with readonly properties\n const marker = getMarkerForRole(roleSpec, profile);\n\n const rule: ExtractionRule = {\n ...(roleSpec.default !== undefined && { default: roleSpec.default }),\n ...(marker && { marker }),\n };\n\n rules[roleSpec.role] = rule;\n }\n\n return rules;\n}\n\n/**\n * Build a human-readable format string for the pattern.\n */\nfunction buildFormatString(\n schema: CommandSchema,\n profile: PatternGenLanguageProfile,\n keyword: string\n): string {\n const isSOV = profile.wordOrder === 'SOV';\n const preVerb: string[] = [];\n const postVerb: string[] = [];\n\n // Order roles the same way buildTokens does (descending position). Iterating\n // declaration order here would disagree with the token order whenever a\n // schema's roles are declared in a different order than their positions imply.\n const sortedRoles = sortRolesByWordOrder(schema.roles, profile.wordOrder);\n for (const role of sortedRoles) {\n const marker = getMarkerForRole(role, profile);\n const roleName = `{${role.role}}`;\n // Same pre/post-verb split buildTokens applies, so the documented format\n // string keeps describing the tokens it is generated alongside.\n const bucket = isSOV && role.sovSlot === 'postVerb' ? postVerb : preVerb;\n\n if (marker) {\n const markerInfo = profile.roleMarkers?.[role.role];\n if (markerInfo?.position === 'after') {\n bucket.push(`${roleName} ${marker}`);\n } else {\n bucket.push(`${marker} ${roleName}`);\n }\n } else {\n bucket.push(roleName);\n }\n }\n\n return (isSOV ? [...preVerb, keyword, ...postVerb] : [keyword, ...preVerb, ...postVerb]).join(\n ' '\n );\n}\n\n/**\n * Generate multiple pattern variants (with and without optional roles).\n */\nexport function generatePatternVariants(\n schema: CommandSchema,\n profile: PatternGenLanguageProfile,\n config: GeneratorConfig = defaultConfig\n): LanguagePattern[] {\n const patterns: LanguagePattern[] = [];\n\n // Main pattern (all roles)\n patterns.push(generatePattern(schema, profile, config));\n\n // TODO: Generate variants with optional roles omitted\n // This can be added later when needed\n\n return patterns;\n}\n","/**\n * Core Types — re-exported from @lokascript/intent + framework-specific extensions\n *\n * The universal semantic types (SemanticNode, SemanticValue, etc.) now live in\n * @lokascript/intent and are re-exported here for backward compatibility.\n *\n * Framework-specific types (tokenization, pattern matching) are defined below.\n */\n\n// =============================================================================\n// Re-export everything from @lokascript/intent\n// =============================================================================\n\nexport type {\n ActionType,\n SemanticRole,\n SemanticValue,\n ExpectedType,\n LiteralValue,\n SelectorValue,\n ReferenceValue,\n PropertyPathValue,\n ExpressionValue,\n FlagValue,\n Annotation,\n ProtocolDiagnostic,\n AsyncVariant,\n MatchArm,\n SemanticNode,\n SemanticMetadata,\n SourcePosition,\n CommandSemanticNode,\n EventHandlerSemanticNode,\n EventModifiers,\n ConditionalSemanticNode,\n CompoundSemanticNode,\n LoopVariant,\n LoopSemanticNode,\n LSEEnvelope,\n} from '@lokascript/intent';\n\nexport {\n createLiteral,\n createSelector,\n createReference,\n createPropertyPath,\n createExpression,\n createFlag,\n createCommandNode,\n createEventHandlerNode,\n createConditionalNode,\n createCompoundNode,\n createLoopNode,\n createTryNode,\n createAsyncNode,\n createMatchNode,\n extractValue,\n extractRoleValue,\n getRoleValue,\n} from '@lokascript/intent';\n\n// =============================================================================\n// Framework-specific types (multilingual DSL infrastructure)\n// =============================================================================\n\nimport type {\n ActionType,\n SemanticRole,\n SemanticValue,\n SelectorValue,\n ExpectedType,\n SourcePosition,\n} from '@lokascript/intent';\n\n/**\n * Token kind - categorizes what type of token this is.\n */\nexport type TokenKind =\n | 'keyword' // Command or modifier keyword\n | 'selector' // CSS selector or identifier (#id, .class, table-name)\n | 'literal' // String or number literal\n | 'particle' // Grammatical particle (を, に, من)\n | 'conjunction' // Grammatical conjunction\n | 'event-modifier' // Event modifier (.once, .debounce(300))\n | 'identifier' // Generic identifier\n | 'operator' // Operators (., +, -, etc.)\n | 'punctuation' // Punctuation (parentheses, etc.)\n | 'url'; // URL or path\n\n/**\n * A language token - the result of tokenization.\n */\nexport interface LanguageToken {\n readonly value: string;\n readonly kind: TokenKind;\n readonly position: SourcePosition;\n readonly normalized?: string;\n readonly stem?: string;\n readonly stemConfidence?: number;\n readonly metadata?: Record<string, unknown>;\n}\n\n/**\n * Token stream - provides sequential access to tokens with backtracking.\n */\nexport interface TokenStream {\n readonly tokens: readonly LanguageToken[];\n readonly language: string;\n peek(offset?: number): LanguageToken | null;\n advance(): LanguageToken;\n isAtEnd(): boolean;\n mark(): StreamMark;\n reset(mark: StreamMark): void;\n position(): number;\n}\n\nexport interface StreamMark {\n readonly position: number;\n}\n\n/**\n * Language tokenizer interface - converts text to tokens.\n */\nexport interface LanguageTokenizer {\n readonly language: string;\n readonly direction: 'ltr' | 'rtl';\n tokenize(input: string): TokenStream;\n classifyToken(token: string): TokenKind;\n}\n\n// =============================================================================\n// Pattern Matching Types\n// =============================================================================\n\nexport interface LanguagePattern {\n readonly id: string;\n readonly language: string;\n readonly command: ActionType;\n readonly priority: number;\n readonly template: PatternTemplate;\n readonly extraction: ExtractionRules;\n readonly constraints?: PatternConstraints;\n}\n\nexport interface PatternTemplate {\n readonly format: string;\n readonly tokens: PatternToken[];\n}\n\nexport type PatternToken = LiteralPatternToken | RolePatternToken | GroupPatternToken;\n\nexport interface LiteralPatternToken {\n readonly type: 'literal';\n readonly value: string;\n readonly alternatives?: string[];\n}\n\nexport interface RolePatternToken {\n readonly type: 'role';\n readonly role: SemanticRole;\n readonly optional?: boolean;\n readonly expectedTypes?: Array<ExpectedType>;\n readonly greedy?: boolean;\n}\n\nexport interface GroupPatternToken {\n readonly type: 'group';\n readonly tokens: PatternToken[];\n readonly optional?: boolean;\n}\n\nexport interface ExtractionRules {\n readonly [role: string]: ExtractionRule;\n}\n\nexport interface ExtractionRule {\n readonly position?: number;\n readonly marker?: string;\n readonly markerAlternatives?: string[];\n readonly transform?: (raw: string) => SemanticValue;\n readonly default?: SemanticValue;\n readonly value?: string;\n readonly fromRole?: string;\n}\n\nexport interface PatternConstraints {\n readonly requiredRoles?: SemanticRole[];\n readonly forbiddenRoles?: SemanticRole[];\n readonly validPatientTypes?: Array<SelectorValue['selectorKind']>;\n readonly conflictsWith?: string[];\n}\n\nexport interface PatternMatchResult {\n readonly pattern: LanguagePattern;\n readonly captured: ReadonlyMap<SemanticRole, SemanticValue>;\n readonly consumedTokens: number;\n readonly confidence: number;\n}\n\nexport interface PatternMatchError {\n readonly message: string;\n readonly position: SourcePosition;\n readonly expectedPatterns?: string[];\n readonly partialMatch?: Partial<PatternMatchResult>;\n}\n","/**\n * Natural Language Renderer\n *\n * Interface and utilities for rendering SemanticNode → human-readable text\n * in any supported language. This is the inverse of parsing: it converts\n * a language-neutral semantic representation back to natural-language syntax.\n *\n * Every domain that supports `translate()` needs a renderer.\n */\n\nimport type { SemanticNode } from '../core/types';\nimport { extractRoleValue, extractValue } from '../core/types';\nimport type { CommandSchema } from '../schema';\nimport { sortRolesByWordOrder, type PatternGenLanguageProfile } from './pattern-generator';\n\n// =============================================================================\n// Renderer Interface\n// =============================================================================\n\n/**\n * Renders a SemanticNode to human-readable text in a target language.\n */\nexport interface NaturalLanguageRenderer {\n render(node: SemanticNode, language: string): string;\n}\n\n// =============================================================================\n// Renderer Helpers\n// =============================================================================\n\n/**\n * Keyword table: action → language → translated keyword.\n *\n * @example\n * ```typescript\n * const KEYWORDS: KeywordTable = {\n * select: { en: 'select', ja: '選択', es: 'seleccionar' },\n * insert: { en: 'insert', ja: '挿入', es: 'insertar' },\n * };\n * ```\n */\nexport type KeywordTable = Record<string, Record<string, string>>;\n\n/**\n * Marker table: marker name → language → translated marker.\n *\n * @example\n * ```typescript\n * const MARKERS: MarkerTable = {\n * from: { en: 'from', ja: 'から', es: 'de' },\n * into: { en: 'into', ja: 'に', es: 'en' },\n * };\n * ```\n */\nexport type MarkerTable = Record<string, Record<string, string>>;\n\n/**\n * Configuration for building a renderer from schemas and profiles.\n */\nexport interface RendererConfig {\n /** Command keyword translations per language */\n readonly keywords: KeywordTable;\n\n /** Role marker translations per language (prepositions/particles) */\n readonly markers: MarkerTable;\n\n /** Languages that use SOV word order */\n readonly sovLanguages: ReadonlySet<string>;\n\n /** Languages that use VSO word order (optional, defaults to empty) */\n readonly vsoLanguages?: ReadonlySet<string>;\n}\n\n/**\n * Look up a command keyword in the target language.\n * Falls back to the key itself if no translation found.\n */\nexport function lookupKeyword(keywords: KeywordTable, action: string, language: string): string {\n return keywords[action]?.[language] ?? action;\n}\n\n/**\n * Look up a role marker in the target language.\n * Falls back to the key itself if no translation found.\n */\nexport function lookupMarker(markers: MarkerTable, marker: string, language: string): string {\n return markers[marker]?.[language] ?? marker;\n}\n\n/**\n * Build a phrase from parts, filtering empty strings and joining with space.\n *\n * @example\n * ```typescript\n * buildPhrase('select', '', 'name', 'from', 'users')\n * // → 'select name from users'\n * ```\n */\nexport function buildPhrase(...parts: string[]): string {\n return parts.filter(Boolean).join(' ');\n}\n\n/**\n * Build keyword and marker tables from schemas and language profiles.\n * Extracts translations from the profile's keyword definitions and\n * role marker overrides.\n *\n * @example\n * ```typescript\n * const { keywords, markers } = buildTablesFromProfiles(schemas, profiles);\n * ```\n */\nexport function buildTablesFromProfiles(\n schemas: readonly CommandSchema[],\n profiles: readonly PatternGenLanguageProfile[]\n): { keywords: KeywordTable; markers: MarkerTable } {\n const keywords: KeywordTable = {};\n const markers: MarkerTable = {};\n\n // Build keyword table from profiles\n for (const profile of profiles) {\n for (const [action, kw] of Object.entries(profile.keywords)) {\n if (!keywords[action]) keywords[action] = {};\n keywords[action][profile.code] = kw.primary;\n }\n }\n\n // Build marker table from schema markerOverrides\n for (const schema of schemas) {\n for (const role of schema.roles) {\n if (role.markerOverride) {\n // Use role name as marker key\n const markerKey = role.role;\n if (!markers[markerKey]) markers[markerKey] = {};\n for (const [lang, markerText] of Object.entries(role.markerOverride)) {\n markers[markerKey][lang] = markerText;\n }\n }\n }\n }\n\n // Also extract role markers from profiles\n for (const profile of profiles) {\n if (profile.roleMarkers) {\n for (const [markerKey, markerDef] of Object.entries(profile.roleMarkers)) {\n if (!markers[markerKey]) markers[markerKey] = {};\n markers[markerKey][profile.code] = markerDef.primary;\n }\n }\n }\n\n return { keywords, markers };\n}\n\n/**\n * Detect word order from language profiles.\n * Returns sets of SOV and VSO language codes.\n */\nexport function detectWordOrders(profiles: readonly PatternGenLanguageProfile[]): {\n sovLanguages: Set<string>;\n vsoLanguages: Set<string>;\n} {\n const sovLanguages = new Set<string>();\n const vsoLanguages = new Set<string>();\n\n for (const profile of profiles) {\n if (profile.wordOrder === 'SOV') sovLanguages.add(profile.code);\n if (profile.wordOrder === 'VSO') vsoLanguages.add(profile.code);\n }\n\n return { sovLanguages, vsoLanguages };\n}\n\n/**\n * Create a basic renderer from schemas and profiles.\n *\n * This generates a renderer that handles word-order reordering automatically.\n * For each command, it constructs the output by placing the keyword and\n * role values in the correct order for the target language.\n *\n * For complex domain-specific rendering, implement `NaturalLanguageRenderer`\n * directly instead.\n *\n * @example\n * ```typescript\n * const renderer = createSchemaRenderer(schemas, profiles);\n * renderer.render(node, 'ja'); // → \"users から name 選択\"\n * ```\n */\nexport function createSchemaRenderer(\n schemas: readonly CommandSchema[],\n profiles: readonly PatternGenLanguageProfile[]\n): NaturalLanguageRenderer {\n const tables = buildRenderTables(schemas, profiles);\n\n return {\n render(node: SemanticNode, language: string): string {\n // An action with no schema still has a name — render that rather than\n // nothing. `createDomainRenderer` returns null for this case instead.\n return renderFromSchema(node, language, tables) ?? node.action;\n },\n };\n}\n\n// =============================================================================\n// Domain renderer (hand-written cases + schema fallthrough)\n// =============================================================================\n\n/**\n * Renders a SemanticNode, or returns `null` when the action cannot be rendered.\n *\n * The nullable counterpart to {@link NaturalLanguageRenderer}: `null` means \"I\n * do not know this action\", which callers can act on. A domain that signals the\n * same condition with a sentinel string forces consumers into string matching.\n */\nexport type DomainRenderFn = (node: SemanticNode, language: string) => string | null;\n\n/**\n * Configuration for {@link createDomainRenderer}.\n */\nexport interface DomainRendererConfig {\n /** Schemas for this domain's commands, including any extensions. */\n readonly schemas: readonly CommandSchema[];\n\n /** Language profiles supplying keywords and role markers. */\n readonly profiles: readonly PatternGenLanguageProfile[];\n\n /**\n * Hand-written renderers per action. These take absolute precedence over the\n * schema-driven path, so a domain's existing output is preserved byte for byte.\n *\n * An override returning `null` means \"this action cannot be rendered\" and is\n * passed straight through — it does not fall through to the schema path,\n * since a hand-written renderer knows more about its action than the schema does.\n */\n readonly overrides?: Readonly<Record<string, DomainRenderFn>>;\n}\n\n/**\n * Create a renderer that composes a domain's hand-written per-action renderers\n * with the schema-driven fallback.\n *\n * Resolution order:\n * 1. `overrides[node.action]` — the domain's own rendering, unchanged\n * 2. schema-driven rendering — any action with a schema but no hand-written case\n * 3. `null` — no override and no schema\n *\n * Step 2 is what makes a domain extensible: a consumer that adds a command\n * schema (with per-language keywords in the profiles) gets correct word order,\n * markers and keywords for free, without the domain package having to know\n * about that command.\n *\n * @example\n * ```typescript\n * const render = createDomainRenderer({\n * schemas: allSchemas,\n * profiles: allProfiles,\n * overrides: { select: renderSelect, insert: renderInsert },\n * });\n * render(node, 'ja'); // hand-written for `select`, schema-driven otherwise\n * render(bogusNode, 'en'); // → null\n * ```\n */\nexport function createDomainRenderer(config: DomainRendererConfig): DomainRenderFn {\n const { schemas, profiles, overrides } = config;\n\n // Built on first render — a domain module can construct its renderer at import\n // time without paying for table construction it may never use.\n let tables: RenderTables | undefined;\n\n return (node: SemanticNode, language: string): string | null => {\n const override = overrides?.[node.action];\n if (override) return override(node, language);\n\n tables ??= buildRenderTables(schemas, profiles);\n return renderFromSchema(node, language, tables);\n };\n}\n\n// =============================================================================\n// Shared schema-driven rendering\n// =============================================================================\n\ninterface RenderTables {\n readonly keywords: KeywordTable;\n readonly markers: MarkerTable;\n /** Marker side per role per language, from each profile's roleMarkers. */\n readonly markerPositions: Record<string, Record<string, 'before' | 'after'>>;\n readonly sovLanguages: ReadonlySet<string>;\n readonly schemaMap: ReadonlyMap<string, CommandSchema>;\n}\n\nfunction buildRenderTables(\n schemas: readonly CommandSchema[],\n profiles: readonly PatternGenLanguageProfile[]\n): RenderTables {\n const { keywords, markers } = buildTablesFromProfiles(schemas, profiles);\n const { sovLanguages } = detectWordOrders(profiles);\n\n const markerPositions: Record<string, Record<string, 'before' | 'after'>> = {};\n for (const profile of profiles) {\n for (const [role, markerDef] of Object.entries(profile.roleMarkers ?? {})) {\n if (!markerDef.position) continue;\n markerPositions[role] ??= {};\n markerPositions[role][profile.code] = markerDef.position;\n }\n }\n\n const schemaMap = new Map<string, CommandSchema>();\n for (const s of schemas) schemaMap.set(s.action, s);\n return { keywords, markers, markerPositions, sovLanguages, schemaMap };\n}\n\n/**\n * The one schema-driven rendering algorithm, shared by `createSchemaRenderer`\n * and `createDomainRenderer` so the two can never drift.\n *\n * Returns `null` when the action has no schema.\n */\nfunction renderFromSchema(\n node: SemanticNode,\n language: string,\n tables: RenderTables\n): string | null {\n const schema = tables.schemaMap.get(node.action);\n if (!schema) return null;\n\n const keyword = lookupKeyword(tables.keywords, node.action, language);\n const isSOV = tables.sovLanguages.has(language);\n\n // Order roles by their declared positions, using the SAME comparator pattern\n // generation uses. Rendering in declaration order instead would produce a\n // surface the generated pattern cannot re-parse whenever the two disagree.\n const ordered = sortRolesByWordOrder([...schema.roles], isSOV ? 'SOV' : 'SVO');\n\n // Roles rendered before the verb, and (SOV only) after it.\n const preVerb: string[] = [];\n const postVerb: string[] = [];\n\n for (const role of ordered) {\n let value = extractRoleValue(node, role.role);\n if (!value && role.default !== undefined) {\n value = String(extractValue(role.default));\n }\n // A role with no value is skipped entirely — including its marker. Emitting\n // the marker of an absent role produces dangling text (\"analyze #content as\",\n // \"#content として 分析\"), which is never valid surface syntax. This applies to\n // required roles too: a required role with no value is a malformed node, and\n // a dangling marker is a worse rendering of it than simply leaving it out.\n if (!value) continue;\n\n if (role.quoteMultiword && /\\s/.test(value) && !/^([\"']).*\\1$/.test(value)) {\n value = `\"${value}\"`;\n }\n\n // Marker resolution, most specific first. `renderOverride` for this exact\n // language is the most specific statement; `''` means \"render this role\n // bare\" (a marker that exists only to help the parser). The `'*'` key is a\n // blanket statement about the PROFILE default, so it ranks below a\n // per-language markerOverride — which is how SQL's `get` renders bare in\n // SVO languages while keeping its SOV source particles.\n const markerText =\n role.renderOverride?.[language] ??\n role.markerOverride?.[language] ??\n role.renderOverride?.['*'] ??\n tables.markers[role.role]?.[language];\n\n const markerPosition =\n role.markerPositionOverride?.[language] ??\n role.markerPosition ??\n tables.markerPositions[role.role]?.[language] ??\n (isSOV ? 'after' : 'before');\n\n const bucket = isSOV && role.sovSlot === 'postVerb' ? postVerb : preVerb;\n if (markerText && markerPosition === 'before') {\n bucket.push(markerText, value);\n } else if (markerText) {\n bucket.push(value, markerText);\n } else {\n bucket.push(value);\n }\n }\n\n return isSOV\n ? buildPhrase(...preVerb, keyword, ...postVerb)\n : buildPhrase(keyword, ...preVerb, ...postVerb);\n}\n","/**\n * Structured Error Diagnostics\n *\n * Re-exported from @lokascript/intent.\n * This module is the framework's re-export point for the diagnostic types\n * that live in the universal intent package.\n */\n\nexport type {\n DiagnosticSeverity,\n Diagnostic,\n DiagnosticResult,\n DiagnosticSummary,\n DiagnosticCollector,\n DiagnosticOptions,\n} from '@lokascript/intent';\n\nexport { createDiagnosticCollector, fromError, filterBySeverity } from '@lokascript/intent';\n"],"mappings":"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","names":[]}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* high-level schema definitions rather than hand-writing each one.
|
|
7
7
|
*/
|
|
8
8
|
import type { LanguagePattern } from '../core/types';
|
|
9
|
-
import type { CommandSchema } from '../schema';
|
|
9
|
+
import type { CommandSchema, RoleSpec } from '../schema';
|
|
10
10
|
/**
|
|
11
11
|
* Minimal language profile interface for pattern generation.
|
|
12
12
|
*/
|
|
@@ -41,6 +41,13 @@ export interface GeneratorConfig {
|
|
|
41
41
|
* @returns Generated language pattern
|
|
42
42
|
*/
|
|
43
43
|
export declare function generatePattern(schema: CommandSchema, profile: PatternGenLanguageProfile, config?: GeneratorConfig): LanguagePattern;
|
|
44
|
+
/**
|
|
45
|
+
* Sort roles by word order for pattern building.
|
|
46
|
+
*
|
|
47
|
+
* Exported so the renderer sorts with exactly this comparator — a rendered
|
|
48
|
+
* surface whose role order differs from the generated pattern would not re-parse.
|
|
49
|
+
*/
|
|
50
|
+
export declare function sortRolesByWordOrder(roles: RoleSpec[], wordOrder: string): RoleSpec[];
|
|
44
51
|
/**
|
|
45
52
|
* Generate multiple pattern variants (with and without optional roles).
|
|
46
53
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pattern-generator.d.ts","sourceRoot":"","sources":["../../src/generation/pattern-generator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,eAAe,CAAC;AACnF,OAAO,KAAK,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"pattern-generator.d.ts","sourceRoot":"","sources":["../../src/generation/pattern-generator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,eAAe,CAAC;AACnF,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC3E,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAChF,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAC3B,MAAM,EACN;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAA;KAAE,CAC5E,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,0DAA0D;IAC1D,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,qDAAqD;IACrD,QAAQ,CAAC,uBAAuB,CAAC,EAAE,OAAO,CAAC;CAC5C;AAOD;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,yBAAyB,EAClC,MAAM,GAAE,eAA+B,GACtC,eAAe,CA8BjB;AA+ID;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,EAAE,CAarF;AAkED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,yBAAyB,EAClC,MAAM,GAAE,eAA+B,GACtC,eAAe,EAAE,CAUnB"}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import type { SemanticNode } from '../core/types';
|
|
11
11
|
import type { CommandSchema } from '../schema';
|
|
12
|
-
import type
|
|
12
|
+
import { type PatternGenLanguageProfile } from './pattern-generator';
|
|
13
13
|
/**
|
|
14
14
|
* Renders a SemanticNode to human-readable text in a target language.
|
|
15
15
|
*/
|
|
@@ -112,4 +112,56 @@ export declare function detectWordOrders(profiles: readonly PatternGenLanguagePr
|
|
|
112
112
|
* ```
|
|
113
113
|
*/
|
|
114
114
|
export declare function createSchemaRenderer(schemas: readonly CommandSchema[], profiles: readonly PatternGenLanguageProfile[]): NaturalLanguageRenderer;
|
|
115
|
+
/**
|
|
116
|
+
* Renders a SemanticNode, or returns `null` when the action cannot be rendered.
|
|
117
|
+
*
|
|
118
|
+
* The nullable counterpart to {@link NaturalLanguageRenderer}: `null` means "I
|
|
119
|
+
* do not know this action", which callers can act on. A domain that signals the
|
|
120
|
+
* same condition with a sentinel string forces consumers into string matching.
|
|
121
|
+
*/
|
|
122
|
+
export type DomainRenderFn = (node: SemanticNode, language: string) => string | null;
|
|
123
|
+
/**
|
|
124
|
+
* Configuration for {@link createDomainRenderer}.
|
|
125
|
+
*/
|
|
126
|
+
export interface DomainRendererConfig {
|
|
127
|
+
/** Schemas for this domain's commands, including any extensions. */
|
|
128
|
+
readonly schemas: readonly CommandSchema[];
|
|
129
|
+
/** Language profiles supplying keywords and role markers. */
|
|
130
|
+
readonly profiles: readonly PatternGenLanguageProfile[];
|
|
131
|
+
/**
|
|
132
|
+
* Hand-written renderers per action. These take absolute precedence over the
|
|
133
|
+
* schema-driven path, so a domain's existing output is preserved byte for byte.
|
|
134
|
+
*
|
|
135
|
+
* An override returning `null` means "this action cannot be rendered" and is
|
|
136
|
+
* passed straight through — it does not fall through to the schema path,
|
|
137
|
+
* since a hand-written renderer knows more about its action than the schema does.
|
|
138
|
+
*/
|
|
139
|
+
readonly overrides?: Readonly<Record<string, DomainRenderFn>>;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Create a renderer that composes a domain's hand-written per-action renderers
|
|
143
|
+
* with the schema-driven fallback.
|
|
144
|
+
*
|
|
145
|
+
* Resolution order:
|
|
146
|
+
* 1. `overrides[node.action]` — the domain's own rendering, unchanged
|
|
147
|
+
* 2. schema-driven rendering — any action with a schema but no hand-written case
|
|
148
|
+
* 3. `null` — no override and no schema
|
|
149
|
+
*
|
|
150
|
+
* Step 2 is what makes a domain extensible: a consumer that adds a command
|
|
151
|
+
* schema (with per-language keywords in the profiles) gets correct word order,
|
|
152
|
+
* markers and keywords for free, without the domain package having to know
|
|
153
|
+
* about that command.
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```typescript
|
|
157
|
+
* const render = createDomainRenderer({
|
|
158
|
+
* schemas: allSchemas,
|
|
159
|
+
* profiles: allProfiles,
|
|
160
|
+
* overrides: { select: renderSelect, insert: renderInsert },
|
|
161
|
+
* });
|
|
162
|
+
* render(node, 'ja'); // hand-written for `select`, schema-driven otherwise
|
|
163
|
+
* render(bogusNode, 'en'); // → null
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
export declare function createDomainRenderer(config: DomainRendererConfig): DomainRenderFn;
|
|
115
167
|
//# sourceMappingURL=renderer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/generation/renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,KAAK,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../src/generation/renderer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC/C,OAAO,EAAwB,KAAK,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAM3F;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;CACtD;AAMD;;;;;;;;;;GAUG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAElE;;;;;;;;;;GAUG;AACH,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,gDAAgD;IAChD,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAEhC,qEAAqE;IACrE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAE9B,wCAAwC;IACxC,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAE3C,sEAAsE;IACtE,QAAQ,CAAC,YAAY,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CAC7C;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE9F;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE3F;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAEtD;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,SAAS,aAAa,EAAE,EACjC,QAAQ,EAAE,SAAS,yBAAyB,EAAE,GAC7C;IAAE,QAAQ,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,WAAW,CAAA;CAAE,CAqClD;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,yBAAyB,EAAE,GAAG;IAChF,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC1B,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC3B,CAUA;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,SAAS,aAAa,EAAE,EACjC,QAAQ,EAAE,SAAS,yBAAyB,EAAE,GAC7C,uBAAuB,CAUzB;AAMD;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;AAErF;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,oEAAoE;IACpE,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;IAE3C,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,SAAS,yBAAyB,EAAE,CAAC;IAExD;;;;;;;OAOG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;CAC/D;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,GAAG,cAAc,CAcjF"}
|