| | 2152 | (defun %make-readtable-iterator (readtable) |
| | 2153 | (let ((char-macro-alist (rdtab.alist readtable))) |
| | 2154 | (lambda () |
| | 2155 | (if char-macro-alist |
| | 2156 | (destructuring-bind (char . defn) (pop char-macro-alist) |
| | 2157 | (if (consp defn) |
| | 2158 | (values t char (car defn) t (cdr defn)) |
| | 2159 | (values t char defn nil nil))) |
| | 2160 | (values nil nil nil nil nil))))) |
| | 2161 | |
| | 2162 | (defmacro with-readtable-iterator ((name readtable) &body body) |
| | 2163 | "While executing BODY, bind NAME to a macro that iterates over |
| | 2164 | READTABLE's macros. Each invocation of NAME yields five values: |
| | 2165 | |
| | 2166 | VALUE? CHAR FUNCTION DISPATCH? DISPATCH-ALIST |
| | 2167 | |
| | 2168 | VALUE? is true until the iterator runs out of items. CHAR is the |
| | 2169 | macro character. FUNCTION is the primary value of |
| | 2170 | `get-macro-character' for CHAR. DISPATCH? is true if and only if |
| | 2171 | CHAR is a dispatching macro character. DISPATCH-ALIST is an alist |
| | 2172 | mapping sub-characters to their respective values of |
| | 2173 | `get-dispatch-macro-character', and is NIL unless DISPATCH?. |
| | 2174 | |
| | 2175 | The consequences of modifying READTABLE after entering BODY and |
| | 2176 | before the final invocation of NAME or final use of a |
| | 2177 | DISPATCH-ALIST are undefined." |
| | 2178 | (let ((it (gensym))) |
| | 2179 | `(let ((,it (%make-readtable-iterator ,readtable))) |
| | 2180 | (macrolet ((,name () `(funcall ,',it))) |
| | 2181 | ,@body)))) |
| | 2182 | |