Skip to content

Commit 890413c

Browse files
committed
Readers deal with *read-suppress*
1 parent c4cff28 commit 890413c

22 files changed

+89
-49
lines changed

README.md

+7-3
Original file line numberDiff line numberDiff line change
@@ -776,7 +776,7 @@ The main use of this might be to map between names in a language which uses lots
776776
### Package, module
777777
`cs-forms` lives in `org.tfeb.hax.cs-forms` and provides `:org.tfeb.hax.cs-forms`.
778778

779-
### Reading forms in a package: `read-package`
779+
## Reading forms in a package: `read-package`
780780
Symbolics LispMs had a nice syntax where package prefixes applied generally: `foo:(x y z)` meant either the same as `(foo:x foo:y foo:z)` or possibly `(foo::x foo::y foo::z)`, I'm not sure now. This can't be done in standard CL as by the time the package prefix has been read you're already committed to reading a symbol. But this hack lets you do something similar:
781781

782782
```lisp
@@ -803,6 +803,8 @@ This all works by a fairly nasty hack: the package is read as (probably) a symbo
803803

804804
It may be that some current CL implementations can do the native Symbolics-style thing too, and if they can it's probably better than this hack.
805805

806+
When `*read-suppress*` is true, the reader simply calls `read` twice and returns `nil`.
807+
806808
### Package, module
807809
`read-package` lives in `org.tfeb.hax.read-package` and provides `:org.tfeb.hax.read-package`.
808810

@@ -1295,7 +1297,7 @@ The algorithm for reading a special string is:
12951297
- if is is a special character, then read the next character
12961298
- if it is the delimiter this is an error (if you want to escape the delimiter, use the escape character);
12971299
- otherwise find either its handler or the fallback handler for that special character, then call the handler with four arguments: the special character, the character after it, the delimiter and the stream;
1298-
- the handler function should return: a character which is accumulated; a list of characters which are accumulated (this list may be empty); or a string, the characters of which are accumulate. Any other return value is an error.
1300+
- the handler function should return: a character which is accumulated; a list of characters which are accumulated (this list may be empty); or a string, the characters of which are accumulated. Any other return value is an error.
12991301

13001302
An end of file before an unescaped delimiter is reached is an error.
13011303

@@ -1381,7 +1383,9 @@ This function relies on some slightly non-standard characters: I think they exis
13811383
### Notes
13821384
As mentioned above, a lot of the interface is trying to mirror the standard readtable interface, which is why it's a bit ugly.
13831385

1384-
I've talked about things 'being an error' above: in fact in most (I hope all) cases suitable conditions are signaled
1386+
I've talked about things 'being an error' above: in fact in most (I hope all) cases suitable conditions are signalled.
1387+
1388+
When `*read-suppress*` is true, then reading a special string will still call its handlers: this is necessary because the handlers can absorb arbitrary characters from the stream. But the results of the handlers are simply ignored and no string is built. An alternative would simply be not to call the handlers and assume they are well-behaved, but I decided not to do that. User-defined handlers should, if need be, notice `*read-suppress*`and behave appropriately, for instance by not building a big list of characters to return when reading is suppressed.
13851389

13861390
Stringtables are intended to provide a way of reading literal strings with some slightly convenient syntax[^12]: it is *not* a system for, for instance, doing some syntactically-nicer or more extensible version of what `format` does. There are other things which do that, I'm sure.
13871391

org.tfeb.hax.abstract-classes.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

org.tfeb.hax.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
(defsystem "org.tfeb.hax"
77
:description "TFEB hax"
8-
:version "5.0.1"
8+
:version "5.0.2"
99
:author "Tim Bradshaw"
1010
:license "MIT"
1111
:homepage "https://github.com/tfeb/tfeb-lisp-hax"

org.tfeb.hax.binding.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

org.tfeb.hax.collecting.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

org.tfeb.hax.comment-form.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

org.tfeb.hax.cs-forms.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

org.tfeb.hax.define-functions.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

org.tfeb.hax.dynamic-state.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

org.tfeb.hax.iterate.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

org.tfeb.hax.memoize.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

org.tfeb.hax.object-accessors.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

org.tfeb.hax.read-package.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

org.tfeb.hax.simple-loops.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

org.tfeb.hax.singleton-classes.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

org.tfeb.hax.spam.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

org.tfeb.hax.stringtable.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

org.tfeb.hax.trace-macroexpand.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

org.tfeb.hax.utilities.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

org.tfeb.hax.wrapping-standard.asd

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
:description
88
"A subsystem of the TFEB hax"
99
:version
10-
"5.0.1"
10+
"5.0.2"
1111
:author
1212
"Tim Bradshaw"
1313
:license

read-package.lisp

+26-23
Original file line numberDiff line numberDiff line change
@@ -74,28 +74,31 @@ If AT is given, it is the dispatch macro character to use instead of #\@."
7474
(error "Someone is already using #~A" at))
7575
(set-dispatch-macro-character
7676
#\# at
77-
#'(lambda (stream char infix)
78-
(declare (ignore char infix))
79-
(let* ((*package* *read-package-package*)
80-
(tok (read stream t nil t))
81-
(string (typecase tok
82-
(symbol
83-
(if (eq (symbol-package tok) *read-package-package*)
84-
(unintern tok)
85-
(warn
86-
"Dubious syntax for read-package: symbol in package ~A"
87-
(package-name (symbol-package tok))))
88-
(symbol-name tok))
89-
(string
90-
(warn "Dubious syntax for read-package: string read")
91-
tok)
92-
(t
93-
(error "read-package: got a ~A, expecting a symbol"
94-
(type-of tok)))))
95-
(package (find-package string)))
96-
(unless package
97-
(error "No package with name ~A for read-package" string))
98-
(let ((*package* package))
99-
(read stream t nil t))))
77+
(lambda (stream char infix)
78+
(declare (ignore char infix))
79+
(if (not *read-suppress*)
80+
(let* ((*package* *read-package-package*)
81+
(tok (read stream t nil t))
82+
(string (typecase tok
83+
(symbol
84+
(if (eq (symbol-package tok) *read-package-package*)
85+
(unintern tok)
86+
(warn
87+
"Dubious syntax for read-package: symbol in package ~A"
88+
(package-name (symbol-package tok))))
89+
(symbol-name tok))
90+
(string
91+
(warn "Dubious syntax for read-package: string read")
92+
tok)
93+
(t
94+
(error "read-package: got a ~A, expecting a symbol"
95+
(type-of tok)))))
96+
(package (find-package string)))
97+
(unless package
98+
(error "No package with name ~A for read-package" string))
99+
(let ((*package* package))
100+
(read stream t nil t)))
101+
;; *READ-SUPPRESS*: just read twice & return NIL
102+
(progn (read stream t nil t) (read stream t nil t) nil)))
100103
rt)
101104
rt))

stringtable.lisp

+37-4
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,10 @@ DELIMITER is the delimiter which terminates the string. FROM is the
190190
stream to read, by default *STANDARD-INPUT*, STRINGTABLE is the
191191
stringtable to use, default *STRINGTABLE*. Return the string."
192192
;; This is meant to be like READ-DELIMITED-FORM.
193-
(coerce (read-string-with-stringtable/list delimiter from stringtable)
194-
'string))
193+
(if (not *read-suppress*)
194+
(coerce (read-string-with-stringtable/list delimiter from stringtable)
195+
'string)
196+
(read-string-with-stringtable/suppressed delimiter from stringtable)))
195197

196198
(defun read-string-with-stringtable/list (delimiter from stringtable)
197199
(let ((escape (stringtable-escape-character stringtable))
@@ -211,7 +213,7 @@ stringtable to use, default *STRINGTABLE*. Return the string."
211213
:format-arguments (list (first specially) this)
212214
:stream from))
213215
(let ((result (funcall (gethash this (second specially)
214-
(third specially)) ;
216+
(third specially))
215217
(first specially) this delimiter from)))
216218
(typecase result
217219
(character
@@ -237,8 +239,39 @@ stringtable to use, default *STRINGTABLE*. Return the string."
237239
(collect this)
238240
(inch (read-char from t nil t) nil nil)))))))
239241

242+
(defun read-string-with-stringtable/suppressed (delimiter from stringtable)
243+
;; Read a special string when *READ-SUPRESS* is true. This does Do
244+
;; just enough to get to the end of the string. This does call
245+
;; handlers because they may be responsible for skipping over stuff,
246+
;; but simply ignores what they return.
247+
(let ((escape (stringtable-escape-character stringtable))
248+
(specials (stringtable-specials stringtable)))
249+
(iterate inch ((this (read-char from t nil t))
250+
(escaping nil)
251+
(specially nil))
252+
(cond
253+
(escaping
254+
(inch (read-char from t nil t) nil nil))
255+
(specially
256+
(when (char= this delimiter)
257+
(error 'stringtable-reader-error
258+
:format-control "hit delimiter parsing special (~A~A)"
259+
:format-arguments (list (first specially) this)
260+
:stream from))
261+
(funcall (gethash this (second specially)
262+
(third specially)) ;
263+
(first specially) this delimiter from)
264+
(inch (read-char from t nil t) nil nil))
265+
((and escape (char= this escape))
266+
(inch (read-char from t nil t) t nil))
267+
((assoc this specials)
268+
(inch (read-char from t nil t) nil (assoc this specials)))
269+
((char= this delimiter))
270+
(t
271+
(inch (read-char from t nil t) nil nil)))))
272+
nil)
240273

241-
;;; These two functions are perfecltly easy to implement for users,
274+
;;; These two functions are perfectly easy to implement for users,
242275
;;; but they're the whole purpose of this, so they should exist.
243276
;;;
244277

0 commit comments

Comments
 (0)