@lokascript/framework 4.7.0 → 4.8.0
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 +35 -1
- package/dist/api/create-dsl.d.ts +5 -2
- package/dist/api/create-dsl.d.ts.map +1 -1
- package/dist/api/index.js +45 -5
- package/dist/api/index.js.map +1 -1
- package/dist/core/index.js +10 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/matching/stock-reader.d.ts +8 -1
- package/dist/core/matching/stock-reader.d.ts.map +1 -1
- package/dist/core/pattern-matching/index.js.map +1 -1
- package/dist/core/types.d.ts +5 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js.map +1 -1
- package/dist/generation/index.js +12 -2
- package/dist/generation/index.js.map +1 -1
- package/dist/index.cjs +45 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +45 -5
- package/dist/index.js.map +1 -1
- package/dist/ir/index.js.map +1 -1
- package/dist/parsing/index.js.map +1 -1
- package/dist/testing/gate/index.js +44 -12
- package/dist/testing/gate/index.js.map +1 -1
- package/dist/testing/gate/round-trip.d.ts +24 -3
- package/dist/testing/gate/round-trip.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/api/create-dsl-engine.test.ts +65 -1
- package/src/api/create-dsl.test.ts +7 -0
- package/src/api/create-dsl.ts +32 -4
- package/src/core/matching/stock-reader.test.ts +87 -3
- package/src/core/matching/stock-reader.ts +20 -1
- package/src/core/types.ts +5 -0
- package/src/generation/schema-patterns.test.ts +41 -1
- package/src/generation/schema-patterns.ts +12 -0
- package/src/testing/gate/round-trip.test.ts +99 -9
- package/src/testing/gate/round-trip.ts +76 -11
package/dist/index.cjs
CHANGED
|
@@ -1876,6 +1876,11 @@ function readGreedy(tokens, stopMarkers) {
|
|
|
1876
1876
|
}
|
|
1877
1877
|
return values.length > 0 ? { type: "expression", raw: values.join(" ") } : null;
|
|
1878
1878
|
}
|
|
1879
|
+
function isListedWord(token, words) {
|
|
1880
|
+
if (!token) return false;
|
|
1881
|
+
const forms = [token.value, token.normalized].filter((f) => typeof f === "string");
|
|
1882
|
+
return forms.some((form) => words.some((word) => word.toLowerCase() === form.toLowerCase()));
|
|
1883
|
+
}
|
|
1879
1884
|
var StockValueReader = class {
|
|
1880
1885
|
constructor(view, profiles = {}) {
|
|
1881
1886
|
this.view = view;
|
|
@@ -1908,6 +1913,11 @@ var StockValueReader = class {
|
|
|
1908
1913
|
const token = tokens.peek();
|
|
1909
1914
|
if (token && this.view.wouldMatch(next, token)) return false;
|
|
1910
1915
|
}
|
|
1916
|
+
if (slot.words && !isListedWord(tokens.peek(), slot.words)) return slot.optional ?? false;
|
|
1917
|
+
if (slot.optional && !slot.greedy) {
|
|
1918
|
+
const token = tokens.peek();
|
|
1919
|
+
if (token && isStopMarker(token, greedyStopMarkers(this.view.patternRest()))) return true;
|
|
1920
|
+
}
|
|
1911
1921
|
if (slot.greedy) {
|
|
1912
1922
|
const value = readGreedy(tokens, greedyStopMarkers(this.view.patternRest()));
|
|
1913
1923
|
if (value) {
|
|
@@ -2313,11 +2323,13 @@ function generateVerbFirstPattern(schema, profile, config = defaultConfig2) {
|
|
|
2313
2323
|
const verbToken = keyword.alternatives ? { type: "literal", value: keyword.primary, alternatives: keyword.alternatives } : { type: "literal", value: keyword.primary };
|
|
2314
2324
|
const roleTokens = requiredRoles.flatMap((r) => {
|
|
2315
2325
|
const prefix = r.valuePrefixLiteral?.[profile.code];
|
|
2326
|
+
const words = wordsFor(r, profile.code);
|
|
2316
2327
|
const roleToken = {
|
|
2317
2328
|
type: "role",
|
|
2318
2329
|
role: r.role,
|
|
2319
2330
|
optional: false,
|
|
2320
|
-
expectedTypes: r.expectedTypes
|
|
2331
|
+
expectedTypes: r.expectedTypes,
|
|
2332
|
+
...words ? { words } : {}
|
|
2321
2333
|
};
|
|
2322
2334
|
return prefix ? [{ type: "literal", value: prefix }, roleToken] : [roleToken];
|
|
2323
2335
|
});
|
|
@@ -2487,11 +2499,17 @@ function buildRoleTokens(grammar, schema, profile) {
|
|
|
2487
2499
|
}
|
|
2488
2500
|
return tokens;
|
|
2489
2501
|
}
|
|
2502
|
+
function wordsFor(roleSpec, language) {
|
|
2503
|
+
if (!roleSpec.words) return void 0;
|
|
2504
|
+
const words = [...roleSpec.words["*"] ?? [], ...roleSpec.words[language] ?? []];
|
|
2505
|
+
return words.length > 0 ? words : void 0;
|
|
2506
|
+
}
|
|
2490
2507
|
function buildRoleToken(roleSpec, profile) {
|
|
2491
2508
|
const tokens = [];
|
|
2492
2509
|
const overrideMarker = roleSpec.markerOverride?.[profile.code];
|
|
2493
2510
|
const defaultMarker = profile.roleMarkers[roleSpec.role];
|
|
2494
2511
|
const suppressMarker = roleSpec.renderOverride?.[profile.code] === "";
|
|
2512
|
+
const words = wordsFor(roleSpec, profile.code);
|
|
2495
2513
|
const roleValueToken = {
|
|
2496
2514
|
type: "role",
|
|
2497
2515
|
role: roleSpec.role,
|
|
@@ -2503,7 +2521,9 @@ function buildRoleToken(roleSpec, profile) {
|
|
|
2503
2521
|
...roleSpec.valueShape !== void 0 ? { valueShape: roleSpec.valueShape } : {},
|
|
2504
2522
|
// A greedy role reads up to the next marker the pattern owes (a domain's
|
|
2505
2523
|
// SQL condition); its value reader does the reading.
|
|
2506
|
-
...roleSpec.greedy ? { greedy: true } : {}
|
|
2524
|
+
...roleSpec.greedy ? { greedy: true } : {},
|
|
2525
|
+
// A role with a word list reads only one of its words.
|
|
2526
|
+
...words ? { words } : {}
|
|
2507
2527
|
};
|
|
2508
2528
|
const prefixLiteral = roleSpec.valuePrefixLiteral?.[profile.code];
|
|
2509
2529
|
const pushPrefixed = () => {
|
|
@@ -4044,12 +4064,15 @@ function readingDifference(source, back) {
|
|
|
4044
4064
|
|
|
4045
4065
|
// src/api/create-dsl.ts
|
|
4046
4066
|
var UnreadInputError = class extends Error {
|
|
4047
|
-
constructor(input, language, reading, unread) {
|
|
4048
|
-
super(
|
|
4067
|
+
constructor(input, language, reading, unread, hint) {
|
|
4068
|
+
super(
|
|
4069
|
+
`"${input}" (${language}) reads as ${reading.action} only by leaving "${unread}" unread` + (hint ? `; ${hint}` : "")
|
|
4070
|
+
);
|
|
4049
4071
|
this.input = input;
|
|
4050
4072
|
this.language = language;
|
|
4051
4073
|
this.reading = reading;
|
|
4052
4074
|
this.unread = unread;
|
|
4075
|
+
this.hint = hint;
|
|
4053
4076
|
this.code = "unread-input";
|
|
4054
4077
|
this.name = "UnreadInputError";
|
|
4055
4078
|
}
|
|
@@ -4168,15 +4191,32 @@ var MultilingualDSLImpl = class {
|
|
|
4168
4191
|
}
|
|
4169
4192
|
if (longestPartial) {
|
|
4170
4193
|
const unread = tokens.tokens.slice(longestPartial.consumedTokens).map((t) => t.value).join(" ");
|
|
4194
|
+
const hint = this.quoteHint(longestPartial, tokens.tokens);
|
|
4171
4195
|
throw new UnreadInputError(
|
|
4172
4196
|
input,
|
|
4173
4197
|
language,
|
|
4174
4198
|
this.nodeOf(longestPartial, input, language),
|
|
4175
|
-
unread
|
|
4199
|
+
unread,
|
|
4200
|
+
...hint ? [hint] : []
|
|
4176
4201
|
);
|
|
4177
4202
|
}
|
|
4178
4203
|
throw new Error(`No pattern matched for input: ${input}`);
|
|
4179
4204
|
}
|
|
4205
|
+
/**
|
|
4206
|
+
* `if "buy milk" is one value, quote it`, where the last token a match read is a bare word it took
|
|
4207
|
+
* as a role's value (a role with no word list) and the first it left is a bare word too.
|
|
4208
|
+
*/
|
|
4209
|
+
quoteHint(match, tokens) {
|
|
4210
|
+
const last = tokens[match.consumedTokens - 1];
|
|
4211
|
+
const next = tokens[match.consumedTokens];
|
|
4212
|
+
if (last?.kind !== "identifier" || next?.kind !== "identifier") return void 0;
|
|
4213
|
+
const schema = this.schemaLookup.getSchema(match.pattern.command);
|
|
4214
|
+
const role = [...match.captured].find(
|
|
4215
|
+
([, v]) => v.raw === last.value
|
|
4216
|
+
)?.[0];
|
|
4217
|
+
if (!role || schema?.roles.find((r) => r.role === role)?.words) return void 0;
|
|
4218
|
+
return `if "${last.value} ${next.value}" is one value, quote it`;
|
|
4219
|
+
}
|
|
4180
4220
|
nodeOf(match, input, language) {
|
|
4181
4221
|
return {
|
|
4182
4222
|
kind: "command",
|