The original code, exactly as it appears in the book is here. But in most cases you will want the production code maintained by the Phoeron. This is a slimmed down version with most of the interesting functions/macros as well as bug-fixes and small additional features. When browsing the text online, you will see the original content, exactly as printed.
NOTE: If you are using SBCL, you must use the production code since it contains some important fixes related to how SBCL handles quasiquotes.
(defun block-scanner (trigger-string) (let ((trig (coerce trigger-string 'list)) curr-states) (lambda (data-string) (loop for c across data-string do (let (new-states) (if (char= c (car trig)) (push (cdr trig) new-states)) (loop for s in curr-states do (if (char= c (car s)) (push (cdr s) new-states))) (setq curr-states new-states)) (if (remove-if-not 'null curr-states) (return t))))))Note: Usually it is not a good idea to write parsers like this unassisted. Instead, there are excellent tools like Ragel to help implement such non-back-tracking "block scanners" (though note Ragel "scanners" are different than block-scanner — they do back-tracking). The only thing Ragel is missing is a Common Lisp output target.
Thank you to everyone who has discovered errata. Please send any additional errata/comments to me.
You might also be interested in the clarifications page where I try to elaborate on Let Over Lambda's message.
λ
All material is (C) Doug Hoyte unless otherwise noted or implied. All rights reserved.