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 CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.1.28",
6
+ "version": "1.1.29",
7
7
  "description": "EyeProlog turns facts and rules into answers and proofs.",
8
8
  "type": "module",
9
9
  "main": "./index.js",
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 (escaped) {
190
- escaped = false;
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 === '\n') out += '\\n';
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 + "'";
@@ -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: () => {
@@ -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'`. Double-quoted lists support
5272
- the common escapes `\n`, `\t`, `\"`, and `\\`. Whitespace is insignificant
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.