2 (in-package :lalr-parser-generator
)
6 (defun compute-prediction-sets (grammar)
7 "Computes and returns the first, follow, and nullable sets for
9 (let ((nullable (make-hash-table))
10 (follow (make-hash-table))
11 (first (make-hash-table)))
12 (flet ((nullable-p (x) (gethash x nullable
)))
13 (do-for-each-terminal (z grammar
)
14 (setf (gethash z first
) (list z
)))
16 (do-until-unchanged (first follow nullable
)
17 (do-for-each-production (x ys grammar
)
18 (when (every #'nullable-p ys
)
19 (setf (gethash x nullable
) t
))
25 ;; Note - subseq 0 0 is NIL, the intended effect here.
26 (when (every #'nullable-p
(subseq ys
0 i
))
27 (setf (gethash x first
)
28 (union (gethash x first
)
29 (gethash (nth i ys
) first
))))
31 (when (every #'nullable-p
(subseq ys
(1+ i
) k
))
32 (setf (gethash (nth i ys
) follow
)
33 (union (gethash (nth i ys
) follow
)
36 (loop for j from
(1+ i
) to k
37 when
(every #'nullable-p
(subseq ys
(1+ i
) j
))
38 do
(setf (gethash (nth i ys
) follow
)
39 (union (gethash (nth i ys
) follow
)
40 (gethash (nth j ys
) first
)))))))
42 (values first follow nullable
))))
44 ;;; The following three functions are just for testing. Combined,
45 ;;; they perform the same functions as COMPUTE-PREDICTION-SETS
47 (defun list-nullable (grammar)
49 (do-until-unchanged (nullable)
50 (do-for-each-production (lhs rhs grammar
)
52 (every #'(lambda (x) (member x nullable
)) rhs
))
53 (pushnew lhs nullable
))))
56 (defun list-first-set (grammar nullable
)
57 (let ((first-set (make-hash-table)))
58 (do-for-each-terminal (x grammar
)
59 (setf (gethash x first-set
) (list x
)))
60 (do-until-unchanged (first-set)
61 (do-for-each-production (lhs rhs grammar
)
62 (do ((r-> rhs
(cdr r-
>))
64 ((or done-p
(null r-
>)))
65 (when (not (member (car r-
>) nullable
))
66 (setf (gethash lhs first-set
)
67 (union (gethash lhs first-set
)
68 (gethash (car r-
>) first-set
)))
71 (do-for-each-production (lhs rhs grammar
)
72 (do ((r-> rhs
(cdr r-
>))
74 ((or done-p
(null r-
>)))
75 (when (not (member (car r-
>) nullable
))
76 (setf (gethash lhs first-set
)
77 (union (gethash lhs first-set
)
78 (gethash (car r-
>) first-set
)))
82 (defun list-follow-set (grammar nullable first-set
)
83 (let ((follow-set (make-hash-table)))
84 (do-until-unchanged (follow-set)
85 (do-for-each-production (lhs rhs grammar
)
86 (do ((r-> rhs
(cdr r-
>))
88 ((or done-p
(null r-
>)))
89 (when (every (lambda (x) (member x nullable
)) (cdr r-
>))
90 (setf (gethash (car r-
>) follow-set
)
91 (union (gethash (car r-
>) follow-set
)
92 (gethash lhs follow-set
))))
94 (loop for j from
1 to
(length r-
>)
96 (when (every (lambda (x) (member x nullable
))
97 (and (> j
1) (subseq r-
> 1 (1- j
))))
98 (setf (gethash (car r-
>) follow-set
)
99 (union (gethash (car r-
>) follow-set
)
100 (gethash (nth j r-
>) first-set
)))))))))