eyeprolog 1.2.37 → 1.2.38
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
CHANGED
package/src/parser.js
CHANGED
|
@@ -606,7 +606,9 @@ class Parser {
|
|
|
606
606
|
this.advance();
|
|
607
607
|
return atom('{}');
|
|
608
608
|
}
|
|
609
|
-
|
|
609
|
+
// As with a parenthesized term, a current operator atom may be the entire
|
|
610
|
+
// curly-bracket content: `{*}` denotes {}(*), not an incomplete infix use.
|
|
611
|
+
const term = this.parseTerm(0, true, true, true);
|
|
610
612
|
this.expect(TOK.RBRACE, '}');
|
|
611
613
|
this.advance();
|
|
612
614
|
return compound('{}', [term]);
|
|
@@ -732,7 +734,7 @@ class Parser {
|
|
|
732
734
|
// an argument delimiter there is no operand for prefix syntax, so keep
|
|
733
735
|
// the operator as an atom instead of reporting a misleading bad-term
|
|
734
736
|
// error.
|
|
735
|
-
if ([TOK.COMMA, TOK.RPAREN, TOK.RBRACKET, TOK.BAR, TOK.DOT].includes(this.token.type)) {
|
|
737
|
+
if ([TOK.COMMA, TOK.RPAREN, TOK.RBRACKET, TOK.RBRACE, TOK.BAR, TOK.DOT].includes(this.token.type)) {
|
|
736
738
|
if (!allowOperatorAtom && this.token.type !== TOK.DOT) {
|
|
737
739
|
throw new Error(`parse line ${this.token.line}: operator atom ${op} requires argument context or parentheses`);
|
|
738
740
|
}
|
package/src/write.js
CHANGED
|
@@ -227,7 +227,9 @@ function format(term, env, options, table, maxPriority = 1200, context = 'term')
|
|
|
227
227
|
}
|
|
228
228
|
|
|
229
229
|
if (!options.ignoreOps && resolved.name === '{}' && resolved.arity === 1) {
|
|
230
|
-
|
|
230
|
+
// A current operator atom is valid as the complete curly-bracket content,
|
|
231
|
+
// just as it is in a functional argument or list element.
|
|
232
|
+
return `{${format(resolved.args[0], env, options, table, 1200, 'argument')}}`;
|
|
231
233
|
}
|
|
232
234
|
|
|
233
235
|
if (!options.ignoreOps) {
|
|
@@ -9,6 +9,7 @@ answer(Binary, Octal, Hex, Character, Escaped, Curly, EmptyCurly, IntegerPart, F
|
|
|
9
9
|
=(Character, 0'\n),
|
|
10
10
|
=(Escaped, 'A\x42\\101\'),
|
|
11
11
|
=(Curly, {pair(a, b)}),
|
|
12
|
+
{*} = {}(*),
|
|
12
13
|
=(EmptyCurly, {}),
|
|
13
14
|
IntegerPart is float_integer_part(-3.75),
|
|
14
15
|
FractionalPart is float_fractional_part(-3.75).
|
package/test/run-regression.mjs
CHANGED
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
variantTerms,
|
|
39
39
|
parseProgramText,
|
|
40
40
|
} from '../src/index.js';
|
|
41
|
-
import { parseGoalText, parseNumberTokenText } from '../src/parser.js';
|
|
41
|
+
import { ISO_OPERATOR_DEFINITIONS, parseGoalText, parseNumberTokenText } from '../src/parser.js';
|
|
42
42
|
import { compareTerms } from '../src/term.js';
|
|
43
43
|
import { formatTermForWrite } from '../src/write.js';
|
|
44
44
|
import { selectClauseCandidates } from '../src/program.js';
|
|
@@ -782,6 +782,38 @@ c4 ?- call((!;1)).
|
|
|
782
782
|
assertNotIncludes(result.stdout, "'?-'", 'writeq(?-) has no quotes');
|
|
783
783
|
},
|
|
784
784
|
},
|
|
785
|
+
{
|
|
786
|
+
name: 'curly brackets accept ISO and custom operator atoms (issue #41)',
|
|
787
|
+
run: () => {
|
|
788
|
+
const operatorNames = [...new Set(ISO_OPERATOR_DEFINITIONS.map(([, , name]) => name))]
|
|
789
|
+
.filter((name) => name !== ',');
|
|
790
|
+
for (const name of operatorNames) {
|
|
791
|
+
const holder = parseGoalText(`holder({${name}})`);
|
|
792
|
+
const curly = holder.args[0];
|
|
793
|
+
assertEqual(curly.name, '{}', `curly functor for ${name}`);
|
|
794
|
+
assertEqual(curly.args[0].name, name, `curly operator atom ${name}`);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
const customProgram = parseProgramText([
|
|
798
|
+
':- op(100, fx, pre).',
|
|
799
|
+
':- op(100, xf, post).',
|
|
800
|
+
':- op(100, xfx, infix).',
|
|
801
|
+
'custom({pre}, {post}, {infix}).',
|
|
802
|
+
'',
|
|
803
|
+
].join('\n'));
|
|
804
|
+
const custom = customProgram.find((clause) => clause.head.name === 'custom').head;
|
|
805
|
+
assertEqual(
|
|
806
|
+
custom.args.map((curly) => curly.args[0].name).join(','),
|
|
807
|
+
'pre,post,infix',
|
|
808
|
+
'custom prefix, postfix, and infix operator atoms',
|
|
809
|
+
);
|
|
810
|
+
|
|
811
|
+
const repl = runCli([], { input: 'read(T).\n{*}.\nhalt.\n' });
|
|
812
|
+
assertEqual(repl.status, 0, 'curly operator REPL status');
|
|
813
|
+
assertIncludes(repl.stdout, 'T = {*}.', 'curly operator REPL answer');
|
|
814
|
+
assertNotIncludes(repl.stdout, '{(*)}', 'curly operator has no unnecessary parentheses');
|
|
815
|
+
},
|
|
816
|
+
},
|
|
785
817
|
{
|
|
786
818
|
name: 'normal parser rejects non-conforming bare operator operands',
|
|
787
819
|
run: () => {
|
package/the-art-of-eyeprolog.md
CHANGED
|
@@ -5197,12 +5197,14 @@ parsing of subsequent text, place them before their first use. ISO argument
|
|
|
5197
5197
|
syntax also permits an atom that is currently an operator to appear directly
|
|
5198
5198
|
as a functional argument or list element, so forms such as
|
|
5199
5199
|
`current_op(Priority, Specifier, :-)` and `[:-,-]` are valid without quoting
|
|
5200
|
-
or parenthesizing those operator atoms.
|
|
5201
|
-
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5200
|
+
or parenthesizing those operator atoms. A current operator atom may likewise
|
|
5201
|
+
be the complete content of parentheses or curly brackets: `(+)` denotes the
|
|
5202
|
+
atom `+`, and `{*}` denotes the curly term `{}(*)`. Term output observes the
|
|
5203
|
+
same context rules: with `quoted(true)`, an operator atom is not quoted merely
|
|
5204
|
+
because it occurs as a functional argument, list element, or sole curly-bracket
|
|
5205
|
+
content. Thus `writeq({*})` emits `{*}`, `writeq([:-,-])` emits `[:-,-]`, and
|
|
5206
|
+
`writeq(f(;,'|',';;'))` emits `f(;,'|',';;')`; the bar stays quoted because
|
|
5207
|
+
ISO treats the unquoted `|` token as a list separator rather than an atom. The ISO initial operator table also
|
|
5206
5208
|
contains `?-` at priority 1200 with specifier `fx`, so
|
|
5207
5209
|
`current_op(1200, fx, ?-)` succeeds. EyeProlog's embedded quad syntax permits
|
|
5208
5210
|
an optional label before the query marker (`Label ?- Query.`), so while quad
|