X-Git-Url: https://git.distorted.org.uk/~mdw/lisp/blobdiff_plain/dc6faaf148af72b8186623f9cf24630889309381..af33e77c00654c222a8a04a5e69a5eb1f56c1e8c:/infix.lisp diff --git a/infix.lisp b/infix.lisp index 5cdd0b9..a77f51e 100644 --- a/infix.lisp +++ b/infix.lisp @@ -11,12 +11,12 @@ ;;; it under the terms of the GNU General Public License as published by ;;; the Free Software Foundation; either version 2 of the License, or ;;; (at your option) any later version. -;;; +;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. -;;; +;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software Foundation, ;;; Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. @@ -70,7 +70,7 @@ (name nil :type symbol) (lprec nil :type (or fixnum null)) (rprec nil :type (or fixnum null)) - (func (lambda () nil) :type (function () t))) + (func (lambda () nil) :type #-ecl (function () t) #+ecl function)) ;;;-------------------------------------------------------------------------- ;;; Global parser state. @@ -94,8 +94,12 @@ ;;;-------------------------------------------------------------------------- ;;; The tokenizer. -(defconstant eof (cons :eof nil) - "A magical object which `get-token' returns at end-of-file.") +(eval-when (:compile-toplevel :load-toplevel :execute) + (let ((value (cons :eof nil))) + (unless (and (boundp 'eof) + (equal (symbol-value 'eof) value)) + (defconstant eof (cons :eof nil) + "A magical object which `get-token' returns at end-of-file.")))) (defun default-get-token () "Read a token from *stream* and store it in *token*." @@ -610,11 +614,11 @@ (pushval `(loop ,@(strip-progn (parse-infix 0))))) (defopfunc bind operand - (labels ((loop () + (labels ((loopy () (let ((ids (parse-ident-list)) (valform (progn (delim '=) (parse-infix 0))) (body (if (delim '|,| nil) - (loop) + (loopy) (progn (delim 'in) (strip-progn (parse-infix 0)))))) @@ -622,7 +626,7 @@ `(let ((,(car ids) ,valform)) ,@body) `(multiple-value-bind ,ids ,valform ,@body)))))) (get-token) - (pushval (car (loop))))) + (pushval (car (loopy))))) ;;;-------------------------------------------------------------------------- ;;; Parsing function bodies and lambda lists. @@ -673,7 +677,7 @@ (cond ((delim '|(| nil) (prog1 (parse-infix) (delim '|)|))) (t (prog1 *token* (get-token))))) - + (defopfunc lambda operand (get-token) (pushval `(lambda ,(parse-lambda-list) ,@(strip-progn (parse-infix 0))))) @@ -717,14 +721,27 @@ (unless (eq *token* delim) (error "expected ~S; found ~S" delim *token*))))) -(defun install-infix-reader (&optional (char #\$)) - "Installs a macro character `$ INFIX... $' for translating infix notation +(defun install-infix-reader + (&optional (start #\{) (end #\}) &key dispatch (readtable *readtable*)) + "Installs a macro character `{ INFIX... }' for translating infix notation to Lisp forms. You also want to (use-package :infix-keywords) if you do this." - (let ((delim (intern (string #\$) 'infix-keywords))) - (set-macro-character char (lambda (stream ch) - (declare (ignore ch)) - (read-infix stream :delim delim))))) + (let ((delim (intern (string end) 'infix-keywords))) + (flet ((doit (stream &rest noise) + (declare (ignore noise)) + (read-infix stream :delim delim))) + (if dispatch + (set-dispatch-macro-character dispatch start #'doit readtable) + (set-macro-character start #'doit nil readtable)) + (unless (or (eql start end) + (multiple-value-bind + (func nontermp) + (get-macro-character end readtable) + (and func (not nontermp)))) + (set-macro-character end (lambda (noise) + (declare (ignore noise)) + (error "Unexpected `~C'." end)) + nil readtable))))) ;;;-------------------------------------------------------------------------- ;;; Testing things.