2 (in-package :lalr-parser-generator
)
4 ;;; It's too bad PSXHASH isn't available everywhere.
6 (defconstant +simple-hash-multiplier
+ 31
7 "Multiplication constant suggested by Kernighan and Pike for simple
8 hashing applications.")
10 (defun simple-checksum (x)
11 "Provides an SXHASH-style checksum of X, but also sloppily handles
12 arrays and hash tables, like SBCL's PSXHASH. However, this checksum
13 was only designed for use in comparing relatively similar structures,
14 so it shouldn't be used as a general replacement for something like
17 (array (simple-array-sum x
))
18 (hash-table (simple-hash-sum x
))
21 (defun simple-hash-sum (hash-table)
22 (loop for x being each hash-value of hash-table
23 summing
(simple-checksum x
)))
25 (defun simple-array-sum (array)
26 (loop for x across array
27 summing
(simple-checksum x
)))
29 ;;; Note: there are various ways we can make this much more efficient,
30 ;;; but I don't think it really matters that much.
31 (defmacro do-until-unchanged1
(var &body body
)
32 "Loop BODY until VAR doesn't change (according to EQUALP) between
34 (let ((last-time (gensym)))
38 (setf ,last-time
(simple-checksum ,var
))
40 (unless (equal ,last-time
(simple-checksum ,var
))
44 (defmacro do-until-unchanged
(vars &body body
)
45 "Loop BODY until each variable in VARS doesn't change (according to
46 EQUALP) between iterations."
48 `(do-until-unchanged1 ,(car vars
)
49 (do-until-unchanged ,(cdr vars
)
54 (defmacro dovector
((var vector
) &body body
)
55 "Iterate VAR across VECTOR."
56 `(loop for
,var across
,vector
60 (defmacro do-for-each-item
((var set
) &body body
)
61 "Iterate VAR across the item-set SET."
62 `(dovector (,var
,set
) ,@body
))
65 (defmacro unionf
(dst src
) `(setf ,dst
(union ,dst
,src
)))
69 (defmacro do-for-each-production
((lhs rhs grammar
) &body body
)
70 "For each production in GRAMMAR, BODY is called with LHS and RHS
71 bound to the left-hand side and right-hand side (in the form of a list
72 of tokens) of the grammar rule."
73 (let ((value (gensym)))
74 `(maphash (lambda (,lhs
,value
)
75 (declare (ignorable ,lhs
,value
))
80 (defmacro do-for-each-terminal
((var grammar
) &body body
)
81 "Do BODY for each terminal symbol referenced in GRAMMAR."
84 `(do-for-each-production (,unused
,list
,grammar
)
86 (when (not (non-terminal-p ,var
))