eyeprolog 1.1.28 → 1.1.29
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/repl.js +25 -5
- package/src/write.js +6 -1
- package/test/run-regression.mjs +16 -0
- package/the-art-of-eyeprolog.md +5 -2
package/package.json
CHANGED
package/src/repl.js
CHANGED
|
@@ -164,11 +164,33 @@ async function readQuery(reader) {
|
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
+
function quotedEscapeEnd(source, index) {
|
|
168
|
+
const escaped = source[index + 1] ?? '';
|
|
169
|
+
if (!escaped) return index;
|
|
170
|
+
|
|
171
|
+
// ISO 6.4.2.1 octal and hexadecimal escapes are terminated by a
|
|
172
|
+
// backslash. Consume that terminator as part of the escape so the REPL
|
|
173
|
+
// scanner does not mistake it for an escape of the following quote.
|
|
174
|
+
if (escaped === 'x') {
|
|
175
|
+
let cursor = index + 2;
|
|
176
|
+
while (/^[0-9A-Fa-f]$/.test(source[cursor] ?? '')) cursor++;
|
|
177
|
+
return source[cursor] === '\\' ? cursor : Math.max(index + 1, cursor - 1);
|
|
178
|
+
}
|
|
179
|
+
if (/^[0-7]$/.test(escaped)) {
|
|
180
|
+
let cursor = index + 1;
|
|
181
|
+
while (/^[0-7]$/.test(source[cursor] ?? '')) cursor++;
|
|
182
|
+
return source[cursor] === '\\' ? cursor : Math.max(index + 1, cursor - 1);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Meta escapes, symbolic control escapes, and continuation escapes consume
|
|
186
|
+
// one character after the backslash. The parser performs validity checks.
|
|
187
|
+
return index + 1;
|
|
188
|
+
}
|
|
189
|
+
|
|
167
190
|
function terminalFullStop(source) {
|
|
168
191
|
let quote = null;
|
|
169
192
|
let lineComment = false;
|
|
170
193
|
let blockComment = false;
|
|
171
|
-
let escaped = false;
|
|
172
194
|
let depth = 0;
|
|
173
195
|
|
|
174
196
|
for (let i = 0; i < source.length; i++) {
|
|
@@ -186,10 +208,8 @@ function terminalFullStop(source) {
|
|
|
186
208
|
continue;
|
|
187
209
|
}
|
|
188
210
|
if (quote != null) {
|
|
189
|
-
if (
|
|
190
|
-
|
|
191
|
-
} else if (ch === '\\') {
|
|
192
|
-
escaped = true;
|
|
211
|
+
if (ch === '\\') {
|
|
212
|
+
i = quotedEscapeEnd(source, i);
|
|
193
213
|
} else if (ch === quote) {
|
|
194
214
|
if (next === quote) i++;
|
|
195
215
|
else quote = null;
|
package/src/write.js
CHANGED
|
@@ -22,8 +22,13 @@ function quoteAtom(name) {
|
|
|
22
22
|
for (const ch of name) {
|
|
23
23
|
if (ch === "'") out += "''";
|
|
24
24
|
else if (ch === '\\') out += '\\\\';
|
|
25
|
-
else if (ch === '\
|
|
25
|
+
else if (ch === '\x07') out += '\\a';
|
|
26
|
+
else if (ch === '\b') out += '\\b';
|
|
27
|
+
else if (ch === '\r') out += '\\r';
|
|
28
|
+
else if (ch === '\f') out += '\\f';
|
|
26
29
|
else if (ch === '\t') out += '\\t';
|
|
30
|
+
else if (ch === '\n') out += '\\n';
|
|
31
|
+
else if (ch === '\v') out += '\\v';
|
|
27
32
|
else out += ch;
|
|
28
33
|
}
|
|
29
34
|
return out + "'";
|
package/test/run-regression.mjs
CHANGED
|
@@ -617,6 +617,22 @@ c4 ?- call((!;1)).
|
|
|
617
617
|
assertEqual(result.stderr, '', 'stderr');
|
|
618
618
|
},
|
|
619
619
|
},
|
|
620
|
+
{
|
|
621
|
+
name: 'REPL recognizes ISO octal and hexadecimal escapes in quoted atoms',
|
|
622
|
+
run: () => {
|
|
623
|
+
const result = runCli([], {
|
|
624
|
+
input: "writeq('\\7\\').\nwriteq('\\x7\\').\nwriteq('\\a').\nhalt.\n",
|
|
625
|
+
});
|
|
626
|
+
assertEqual(result.status, 0, 'exit status');
|
|
627
|
+
assertEqual(result.stdout,
|
|
628
|
+
"?- '\\a' true.\n" +
|
|
629
|
+
"?- '\\a' true.\n" +
|
|
630
|
+
"?- '\\a' true.\n" +
|
|
631
|
+
'?- ',
|
|
632
|
+
'stdout');
|
|
633
|
+
assertEqual(result.stderr, '', 'stderr');
|
|
634
|
+
},
|
|
635
|
+
},
|
|
620
636
|
{
|
|
621
637
|
name: 'REPL accepts multiline period-terminated queries',
|
|
622
638
|
run: () => {
|
package/the-art-of-eyeprolog.md
CHANGED
|
@@ -5268,8 +5268,11 @@ city('München').
|
|
|
5268
5268
|
message("café").
|
|
5269
5269
|
```
|
|
5270
5270
|
|
|
5271
|
-
Inside a quoted atom, a single quote is doubled: `'don''t'`.
|
|
5272
|
-
the
|
|
5271
|
+
Inside a quoted atom, a single quote is doubled: `'don''t'`. Quoted characters
|
|
5272
|
+
support the ISO symbolic control escapes such as `\a`, `\n`, and `\t`, and numeric
|
|
5273
|
+
octal or hexadecimal escapes are terminated by a backslash; for example, `'\7\'`
|
|
5274
|
+
and `'\x7\'` both denote the alert character. Double-quoted lists use the same
|
|
5275
|
+
quoted-character escapes. Whitespace is insignificant
|
|
5273
5276
|
between tokens, and a `%` comment continues to the end of its line. Doubling
|
|
5274
5277
|
the active delimiter is also accepted inside either quoted form, so `""`
|
|
5275
5278
|
inside double-quoted notation denotes one literal double quote character.
|