diff --git a/collects/parser-tools/private-yacc/graph.rkt b/collects/parser-tools/private-yacc/graph.rkt index 02e28df..958acc1 100644 --- a/collects/parser-tools/private-yacc/graph.rkt +++ b/collects/parser-tools/private-yacc/graph.rkt @@ -12,55 +12,50 @@ ;; We use a hash-table to represent the result function 'a -> 'b set, so ;; the values of type 'a must be comparable with eq?. (define (digraph nodes edges f- union fail) - (letrec ( - ;; Will map elements of 'a to 'b sets - (results (make-hash-table)) - (f (lambda (x) (hash-table-get results x fail))) - - ;; Maps elements of 'a to integers. - (N (make-hash-table)) - (get-N (lambda (x) (hash-table-get N x zero-thunk))) - (set-N (lambda (x d) (hash-table-put! N x d))) - - (stack null) - (push (lambda (x) - (set! stack (cons x stack)))) - (pop (lambda () + (letrec [ + ;; Will map elements of 'a to 'b sets + (results (make-hash-table)) + (f (lambda (x) (hash-table-get results x fail))) + + ;; Maps elements of 'a to integers. + (N (make-hash-table)) + (get-N (lambda (x) (hash-table-get N x zero-thunk))) + (set-N (lambda (x d) (hash-table-put! N x d))) + + (stack null) + (push (lambda (x) + (set! stack (cons x stack)))) + (pop (lambda () (begin0 - (car stack) - (set! stack (cdr stack))))) - (depth (lambda () (length stack))) - - ;; traverse: 'a -> - (traverse - (lambda (x) - (push x) - (let ((d (depth))) - (set-N x d) - (hash-table-put! results x (f- x)) - (for-each (lambda (y) - (if (= 0 (get-N y)) - (traverse y)) - (hash-table-put! results - x - (union (f x) (f y))) - (set-N x (min (get-N x) (get-N y)))) - (edges x)) - (if (= d (get-N x)) - (let loop ((p (pop))) - (set-N p +inf.0) - (hash-table-put! results p (f x)) - (if (not (eq? x p)) - (loop (pop))))))))) + (car stack) + (set! stack (cdr stack))))) + (depth (lambda () (length stack))) + + ;; traverse: 'a -> + (traverse + (lambda (x) + (push x) + (let ((d (depth))) + (set-N x d) + (hash-table-put! results x (f- x)) + (for-each (lambda (y) + (if (= 0 (get-N y)) + (traverse y)) + (hash-table-put! results + x + (union (f x) (f y))) + (set-N x (min (get-N x) (get-N y)))) + (edges x)) + (if (= d (get-N x)) + (let loop ((p (pop))) + (set-N p +inf.0) + (hash-table-put! results p (f x)) + (if (not (eq? x p)) + (loop (pop))))))))] (for-each (lambda (x) - (if (= 0 (get-N x)) - (traverse x))) - nodes) + (if (= 0 (get-N x)) + (traverse x))) + nodes) f)) ) - - - - - diff --git a/collects/parser-tools/private-yacc/lalr.rkt b/collects/parser-tools/private-yacc/lalr.rkt index 3fb1953..e9b4d3b 100644 --- a/collects/parser-tools/private-yacc/lalr.rkt +++ b/collects/parser-tools/private-yacc/lalr.rkt @@ -38,7 +38,7 @@ ;; output term set is represented in bit-vector form (define (compute-read a g) (let* ((dr (compute-DR a g)) - (reads (compute-reads a g))) + (reads (compute-reads a g))) (digraph-tk->terml (send a get-mapped-non-term-keys) reads dr @@ -127,13 +127,12 @@ ;; output term set is represented in bit-vector form (define (compute-LA a g) (let* ((includes (compute-includes a g)) - (lookback (compute-lookback a g)) - (follow (compute-follow a g includes))) + (lookback (compute-lookback a g)) + (follow (compute-follow a g includes))) (lambda (k p) - (let* ((l (lookback k p)) - (f (map follow l))) - (apply bitwise-ior (cons 0 f)))))) - + (let* ((l (lookback k p)) + (f (map follow l))) + (apply bitwise-ior (cons 0 f)))))) (define (print-DR dr a g) (print-input-st-sym dr "DR" a g print-output-terms)) @@ -192,8 +191,8 @@ (map (lambda (p) (list - (kernel-index (trans-key-st p)) - (gram-sym-symbol (trans-key-gs p)))) + (kernel-index (trans-key-st p)) + (gram-sym-symbol (trans-key-gs p)))) r)) ;; init-tk-map : int -> (vectorof hashtable?) @@ -230,52 +229,49 @@ ;; Computes (f x) = (f- x) union Union{(f y) | y in (edges x)} ;; A specialization of digraph in the file graph.rkt (define (digraph-tk->terml nodes edges f- num-states) - (letrec ( - ;; Will map elements of trans-key to term sets represented as bit vectors - (results (init-tk-map num-states)) + (letrec [ + ;; Will map elements of trans-key to term sets represented as bit vectors + (results (init-tk-map num-states)) - ;; Maps elements of trans-keys to integers. - (N (init-tk-map num-states)) + ;; Maps elements of trans-keys to integers. + (N (init-tk-map num-states)) (get-N (lookup-tk-map N)) - (set-N (add-tk-map N)) - (get-f (lookup-tk-map results)) - (set-f (add-tk-map results)) - - (stack null) - (push (lambda (x) - (set! stack (cons x stack)))) - (pop (lambda () + (set-N (add-tk-map N)) + (get-f (lookup-tk-map results)) + (set-f (add-tk-map results)) + + (stack null) + (push (lambda (x) + (set! stack (cons x stack)))) + (pop (lambda () (begin0 - (car stack) - (set! stack (cdr stack))))) - (depth (lambda () (length stack))) + (car stack) + (set! stack (cdr stack))))) + (depth (lambda () (length stack))) - ;; traverse: 'a -> - (traverse - (lambda (x) - (push x) - (let ((d (depth))) - (set-N x d) - (set-f x (f- x)) - (for-each (lambda (y) - (when (= 0 (get-N y)) + ;; traverse: 'a -> + (traverse + (lambda (x) + (push x) + (let ((d (depth))) + (set-N x d) + (set-f x (f- x)) + (for-each (lambda (y) + (when (= 0 (get-N y)) (traverse y)) - (set-f x (bitwise-ior (get-f x) (get-f y))) - (set-N x (min (get-N x) (get-N y)))) - (edges x)) - (when (= d (get-N x)) + (set-f x (bitwise-ior (get-f x) (get-f y))) + (set-N x (min (get-N x) (get-N y)))) + (edges x)) + (when (= d (get-N x)) (let loop ((p (pop))) (set-N p +inf.0) (set-f p (get-f x)) (unless (equal? x p) - (loop (pop))))))))) + (loop (pop))))))))] (for-each (lambda (x) - (when (= 0 (get-N x)) + (when (= 0 (get-N x)) (traverse x))) - nodes) + nodes) get-f)) ) - - - diff --git a/collects/parser-tools/private-yacc/lr0.rkt b/collects/parser-tools/private-yacc/lr0.rkt index ac359ac..eb0b2da 100644 --- a/collects/parser-tools/private-yacc/lr0.rkt +++ b/collects/parser-tools/private-yacc/lr0.rkt @@ -62,9 +62,9 @@ ;; (listof (cons/c trans-key? (listof kernel?))) (define (reverse-assoc assoc) (let ((reverse-hash (make-hash-table 'equal)) - (hash-table-add! - (lambda (ht k v) - (hash-table-put! ht k (cons v (hash-table-get ht k (lambda () null))))))) + (hash-table-add! + (lambda (ht k v) + (hash-table-put! ht k (cons v (hash-table-get ht k (lambda () null))))))) (for-each (lambda (trans-key/kernel) (let ((tk (car trans-key/kernel))) @@ -99,13 +99,13 @@ (define mapped-non-terms (map car non-term-assoc)) (define/public (get-mapped-non-term-keys) - mapped-non-terms) + mapped-non-terms) (define/public (get-num-states) (vector-length states)) (define/public (get-epsilon-trans) - epsilons) + epsilons) (define/public (get-transitions) (append term-assoc non-term-assoc)) @@ -113,12 +113,12 @@ ;; for-each-state : (state ->) -> ;; Iteration over the states in an automaton (define/public (for-each-state f) - (let ((num-states (vector-length states))) - (let loop ((i 0)) - (if (< i num-states) - (begin - (f (vector-ref states i)) - (loop (add1 i))))))) + (let ((num-states (vector-length states))) + (let loop ((i 0)) + (if (< i num-states) + (begin + (f (vector-ref states i)) + (loop (add1 i))))))) ;; run-automaton: kernel? gram-sym? -> (union kernel #f) ;; returns the state reached from state k on input s, or #f when k @@ -131,28 +131,28 @@ ;; run-automaton-back : (listof kernel?) gram-sym? -> (listof kernel) ;; returns the list of states that can reach k by transitioning on s. (define/public (run-automaton-back k s) - (apply append + (apply append (map (lambda (k) (hash-table-get (vector-ref reverse-transitions (kernel-index k)) (gram-sym-symbol s) (lambda () null))) k))))) - + (define (union comp (eq? a b) (define (kernel->string k) (apply string-append - `("{" ,@(map (lambda (i) (string-append (item->string i) ", ")) - (kernel-items k)) - "}"))) + `("{" ,@(map (lambda (i) (string-append (item->string i) ", ")) + (kernel-items k)) + "}"))) ;; build-LR0-automaton: grammar -> LR0-automaton ;; Constructs the kernels of the sets of LR(0) items of g (define (build-lr0-automaton grammar) ; (printf "LR(0) automaton:\n") (letrec ( - (epsilons (make-hash-table 'equal)) - (grammar-symbols (append (send grammar get-non-terms) + (epsilons (make-hash-table 'equal)) + (grammar-symbols (append (send grammar get-non-terms) (send grammar get-terms))) - ;; first-non-term: non-term -> non-term list - ;; given a non-terminal symbol C, return those non-terminal - ;; symbols A s.t. C -> An for some string of terminals and - ;; non-terminals n where -> means a rightmost derivation in many - ;; steps. Assumes that each non-term can be reduced to a string - ;; of terms. - (first-non-term - (digraph (send grammar get-non-terms) - (lambda (nt) - (filter non-term? - (map (lambda (prod) - (sym-at-dot (make-item prod 0))) - (send grammar get-prods-for-non-term nt)))) - (lambda (nt) (list nt)) - (union non-term non-term list + ;; given a non-terminal symbol C, return those non-terminal + ;; symbols A s.t. C -> An for some string of terminals and + ;; non-terminals n where -> means a rightmost derivation in many + ;; steps. Assumes that each non-term can be reduced to a string + ;; of terms. + (first-non-term + (digraph (send grammar get-non-terms) + (lambda (nt) + (filter non-term? + (map (lambda (prod) + (sym-at-dot (make-item prod 0))) + (send grammar get-prods-for-non-term nt)))) + (lambda (nt) (list nt)) + (union non-term LR1-item list - ;; Creates a set of items containing i s.t. if A -> n.Xm is in it, - ;; X -> .o is in it too. - (LR0-closure - (lambda (i) - (cond - ((null? i) null) - (else - (let ((next-gsym (sym-at-dot (car i)))) - (cond - ((non-term? next-gsym) - (cons (car i) - (append - (apply append - (map (lambda (non-term) - (map (lambda (x) - (make-item x 0)) - (send grammar + ;; closure: LR1-item list -> LR1-item list + ;; Creates a set of items containing i s.t. if A -> n.Xm is in it, + ;; X -> .o is in it too. + (LR0-closure + (lambda (i) + (cond + ((null? i) null) + (else + (let ((next-gsym (sym-at-dot (car i)))) + (cond + ((non-term? next-gsym) + (cons (car i) + (append + (apply append + (map (lambda (non-term) + (map (lambda (x) + (make-item x 0)) + (send grammar get-prods-for-non-term non-term))) - (first-non-term next-gsym))) - (LR0-closure (cdr i))))) - (else - (cons (car i) (LR0-closure (cdr i)))))))))) + (first-non-term next-gsym))) + (LR0-closure (cdr i))))) + (else + (cons (car i) (LR0-closure (cdr i)))))))))) - ;; maps trans-keys to kernels - (automaton-term null) + ;; maps trans-keys to kernels + (automaton-term null) (automaton-non-term null) - - ;; keeps the kernels we have seen, so we can have a unique - ;; list for each kernel - (kernels (make-hash-table 'equal)) + + ;; keeps the kernels we have seen, so we can have a unique + ;; list for each kernel + (kernels (make-hash-table 'equal)) - (counter 0) - - ;; goto: LR1-item list -> LR1-item list list - ;; creates new kernels by moving the dot in each item in the - ;; LR0-closure of kernel to the right, and grouping them by - ;; the term/non-term moved over. Returns the kernels not - ;; yet seen, and places the trans-keys into automaton - (goto - (lambda (kernel) - (let ( - ;; maps a gram-syms to a list of items - (table (make-hash-table)) + (counter 0) + + ;; goto: LR1-item list -> LR1-item list list + ;; creates new kernels by moving the dot in each item in the + ;; LR0-closure of kernel to the right, and grouping them by + ;; the term/non-term moved over. Returns the kernels not + ;; yet seen, and places the trans-keys into automaton + (goto + (lambda (kernel) + (let ( + ;; maps a gram-syms to a list of items + (table (make-hash-table)) - ;; add-item!: - ;; (symbol (listof item) hashtable) item? -> - ;; adds i into the table grouped with the grammar - ;; symbol following its dot - (add-item! - (lambda (table i) - (let ((gs (sym-at-dot i))) - (cond - (gs - (let ((already + ;; add-item!: + ;; (symbol (listof item) hashtable) item? -> + ;; adds i into the table grouped with the grammar + ;; symbol following its dot + (add-item! + (lambda (table i) + (let ((gs (sym-at-dot i))) + (cond + (gs + (let ((already (hash-table-get table (gram-sym-symbol gs) (lambda () null)))) - (unless (member i already) + (unless (member i already) (hash-table-put! table (gram-sym-symbol gs) (cons i already))))) - ((= 0 (vector-length (prod-rhs (item-prod i)))) - (let ((current (hash-table-get epsilons - kernel - (lambda () null)))) - (hash-table-put! epsilons - kernel - (cons i current))))))))) - - ;; Group the items of the LR0 closure of the kernel - ;; by the character after the dot - (for-each (lambda (item) - (add-item! table item)) - (LR0-closure (kernel-items kernel))) - - ;; each group is a new kernel, with the dot advanced. - ;; sorts the items in a kernel so kernels can be compared - ;; with equal? for using the table kernels to make sure - ;; only one representitive of each kernel is created - (filter - (lambda (x) x) - (map - (lambda (i) - (let* ((gs (car i)) - (items (cadr i)) - (new #f) - (new-kernel (sort - (filter (lambda (x) x) - (map move-dot-right items)) - item ~a on ~a\n" - (kernel->string kernel) - (kernel->string unique-kernel) - (gram-sym-symbol gs)) - (if new - unique-kernel - #f))) - (let loop ((gsyms grammar-symbols)) - (cond + (kernel->string kernel) + (kernel->string unique-kernel) + (gram-sym-symbol gs)) + (if new + unique-kernel + #f))) + (let loop ((gsyms grammar-symbols)) + (cond ((null? gsyms) null) (else (let ((items (hash-table-get table @@ -323,33 +323,33 @@ (else (cons (list (car gsyms) items) (loop (cdr gsyms)))))))))))))) - + (starts (map (lambda (init-prod) (list (make-item init-prod 0))) (send grammar get-init-prods))) - (startk + (startk (map (lambda (start) (let ((k (make-kernel start counter))) (hash-table-put! kernels start k) (set! counter (add1 counter)) k)) starts)) - (new-kernels (make-queue))) + (new-kernels (make-queue))) (let loop ((old-kernels startk) - (seen-kernels null)) - (cond - ((and (empty-queue? new-kernels) (null? old-kernels)) - (make-object lr0% - automaton-term - automaton-non-term - (list->vector (reverse seen-kernels)) - epsilons)) - ((null? old-kernels) - (loop (deq! new-kernels) seen-kernels)) - (else - (enq! new-kernels (goto (car old-kernels))) - (loop (cdr old-kernels) (cons (car old-kernels) seen-kernels))))))) + (seen-kernels null)) + (cond + ((and (empty-queue? new-kernels) (null? old-kernels)) + (make-object lr0% + automaton-term + automaton-non-term + (list->vector (reverse seen-kernels)) + epsilons)) + ((null? old-kernels) + (loop (deq! new-kernels) seen-kernels)) + (else + (enq! new-kernels (goto (car old-kernels))) + (loop (cdr old-kernels) (cons (car old-kernels) seen-kernels))))))) (define-struct q (f l) (make-inspector)) (define (empty-queue? q) @@ -358,12 +358,12 @@ (make-q null null)) (define (enq! q i) (if (empty-queue? q) - (let ((i (mcons i null))) - (set-q-l! q i) - (set-q-f! q i)) - (begin - (set-mcdr! (q-l q) (mcons i null)) - (set-q-l! q (mcdr (q-l q)))))) + (let ((i (mcons i null))) + (set-q-l! q i) + (set-q-f! q i)) + (begin + (set-mcdr! (q-l q) (mcons i null)) + (set-q-l! q (mcdr (q-l q)))))) (define (deq! q) (begin0 (mcar (q-f q))