eyelang 1.5.5 → 1.5.6
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/package.json +1 -1
- package/src/index.js +2 -2
- package/src/parser.js +37 -16
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -24,8 +24,8 @@ export function run(source, options = {}) {
|
|
|
24
24
|
const facts = program.sourceFactLines(materializedKeys);
|
|
25
25
|
const seen = new Set();
|
|
26
26
|
for (const goal of goals) {
|
|
27
|
-
|
|
28
|
-
for (const env of
|
|
27
|
+
solver.solutionsSeen = 0;
|
|
28
|
+
for (const env of solver.solve([goal], new Env(), 0)) {
|
|
29
29
|
const resolved = copyResolved(goal, env);
|
|
30
30
|
if (!termIsGround(resolved)) continue;
|
|
31
31
|
const line = `${termToString(resolved, new Env(), true)}.\n`;
|
package/src/parser.js
CHANGED
|
@@ -287,12 +287,14 @@ function isSimpleName(text) {
|
|
|
287
287
|
|
|
288
288
|
const SIMPLE_NUMBER = /^-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?$/;
|
|
289
289
|
const SIMPLE_ARG_FORBIDDEN = /[\s()[\]|"']/;
|
|
290
|
+
const FAST_BINARY_FACT = /^([a-z][A-Za-z0-9_]*)\(\s*([^,\s()[\]|"']+)\s*,\s*([^,\s()[\]|"']+)\s*\)\.$/;
|
|
291
|
+
const FAST_BINARY_RULE = /^([a-z][A-Za-z0-9_]*)\(\s*([^,\s()[\]|"']+)\s*,\s*([^,\s()[\]|"']+)\s*\)\s*:-\s*([a-z][A-Za-z0-9_]*)\(\s*([^,\s()[\]|"']+)\s*,\s*([^,\s()[\]|"']+)\s*\)\.$/;
|
|
290
292
|
|
|
291
293
|
function parseClausesFastNoSource(source) {
|
|
292
294
|
source = String(source ?? '');
|
|
293
|
-
const atomCache = new Map();
|
|
294
295
|
const numberCache = new Map();
|
|
295
296
|
const stringCache = new Map();
|
|
297
|
+
const variableCache = new Map();
|
|
296
298
|
const clauses = [];
|
|
297
299
|
let anonymous = 0;
|
|
298
300
|
let chunk = '';
|
|
@@ -304,22 +306,23 @@ function parseClausesFastNoSource(source) {
|
|
|
304
306
|
cache.set(key, value);
|
|
305
307
|
return value;
|
|
306
308
|
};
|
|
307
|
-
const
|
|
308
|
-
text = text.trim();
|
|
309
|
+
const scalarOrVariableFast = (text) => {
|
|
309
310
|
if (!text) throw new Error('empty simple term');
|
|
311
|
+
const first = text.charCodeAt(0);
|
|
310
312
|
if (text === '_') return variable(`__anon${anonymous++}`);
|
|
311
|
-
if (
|
|
312
|
-
const existing =
|
|
313
|
+
if (first === 95 || (first >= 65 && first <= 90)) {
|
|
314
|
+
const existing = variableCache.get(text);
|
|
313
315
|
if (existing) return existing;
|
|
314
316
|
const value = variable(text);
|
|
315
|
-
|
|
317
|
+
variableCache.set(text, value);
|
|
316
318
|
return value;
|
|
317
319
|
}
|
|
318
|
-
if (SIMPLE_NUMBER.test(text)) return cached(numberCache, text, numberTerm);
|
|
319
|
-
if (
|
|
320
|
-
return
|
|
320
|
+
if ((first === 45 || isDigitCode(first)) && SIMPLE_NUMBER.test(text)) return cached(numberCache, text, numberTerm);
|
|
321
|
+
if (first === 34 && text.endsWith('"')) return cached(stringCache, text.slice(1, -1), stringTerm);
|
|
322
|
+
return atom(text);
|
|
321
323
|
};
|
|
322
|
-
const
|
|
324
|
+
const scalarOrVariable = (text) => scalarOrVariableFast(text.trim());
|
|
325
|
+
const parseBinaryCompound = (text) => {
|
|
323
326
|
text = text.trim();
|
|
324
327
|
const open = text.indexOf('(');
|
|
325
328
|
if (open <= 0 || text[text.length - 1] !== ')') return null;
|
|
@@ -332,19 +335,37 @@ function parseClausesFastNoSource(source) {
|
|
|
332
335
|
const left = inner.slice(0, comma).trim();
|
|
333
336
|
const right = inner.slice(comma + 1).trim();
|
|
334
337
|
if (!left || !right || SIMPLE_ARG_FORBIDDEN.test(left) || SIMPLE_ARG_FORBIDDEN.test(right)) return null;
|
|
335
|
-
return compound(name, [scalarOrVariable(left
|
|
338
|
+
return compound(name, [scalarOrVariable(left), scalarOrVariable(right)]);
|
|
339
|
+
};
|
|
340
|
+
const parseFastBinaryMatch = (match) => {
|
|
341
|
+
return compound(match[1], [scalarOrVariableFast(match[2]), scalarOrVariableFast(match[3])]);
|
|
342
|
+
};
|
|
343
|
+
const parseFastBinaryRuleMatch = (match) => {
|
|
344
|
+
return {
|
|
345
|
+
head: compound(match[1], [scalarOrVariableFast(match[2]), scalarOrVariableFast(match[3])]),
|
|
346
|
+
body: [compound(match[4], [scalarOrVariableFast(match[5]), scalarOrVariableFast(match[6])])],
|
|
347
|
+
};
|
|
348
|
+
};
|
|
349
|
+
const parseFastLine = (text) => {
|
|
350
|
+
if (!text.endsWith('.')) return null;
|
|
351
|
+
const ruleMatch = FAST_BINARY_RULE.exec(text);
|
|
352
|
+
if (ruleMatch) return parseFastBinaryRuleMatch(ruleMatch);
|
|
353
|
+
const factMatch = FAST_BINARY_FACT.exec(text);
|
|
354
|
+
if (factMatch) return { head: parseFastBinaryMatch(factMatch), body: [] };
|
|
355
|
+
return null;
|
|
336
356
|
};
|
|
337
357
|
const parseSimple = (text) => {
|
|
338
358
|
if (!text.endsWith('.') || text.includes('\n')) return null;
|
|
359
|
+
const fast = parseFastLine(text);
|
|
360
|
+
if (fast) return fast;
|
|
339
361
|
text = text.slice(0, -1);
|
|
340
|
-
const variables = new Map();
|
|
341
362
|
const rule = text.indexOf(':-');
|
|
342
363
|
if (rule < 0) {
|
|
343
|
-
const head = parseBinaryCompound(text
|
|
364
|
+
const head = parseBinaryCompound(text);
|
|
344
365
|
return head ? { head, body: [] } : null;
|
|
345
366
|
}
|
|
346
|
-
const head = parseBinaryCompound(text.slice(0, rule)
|
|
347
|
-
const bodyGoal = parseBinaryCompound(text.slice(rule + 2)
|
|
367
|
+
const head = parseBinaryCompound(text.slice(0, rule));
|
|
368
|
+
const bodyGoal = parseBinaryCompound(text.slice(rule + 2));
|
|
348
369
|
return head && bodyGoal ? { head, body: [bodyGoal] } : null;
|
|
349
370
|
};
|
|
350
371
|
|
|
@@ -375,7 +396,7 @@ function parseClausesFastNoSource(source) {
|
|
|
375
396
|
const trimmed = line.trim();
|
|
376
397
|
if (trimmed && !trimmed.startsWith('%')) {
|
|
377
398
|
if (!chunk && trimmed.endsWith('.')) {
|
|
378
|
-
const simple = parseSimple(trimmed);
|
|
399
|
+
const simple = parseFastLine(trimmed) ?? parseSimple(trimmed);
|
|
379
400
|
if (simple) clauses.push(simple);
|
|
380
401
|
else {
|
|
381
402
|
chunk = line + '\n';
|