You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
br-parser-tools/collects/mrspidey/Sba/nfa-dfa.ss

60 lines
2.0 KiB
Scheme

; ======================================================================
;; NFA->DFA
;; roots: (list nt)
;; final: (list nt)
;; returns (list (list AVS) (list AVS))
(define (NFA->DFA for-each-prod roots final)
;; n is an old nt
;; d is new nt
(letrec
([n*->d '()] ; Maps set of NFA nts to a DFA nt
[n*<=
(lambda (n1* n2*)
(andmap (lambda (n1) (mem-nt? n1 n2*)) n1*))]
[n*=
(lambda (n1* n2*)
(and (n*<= n1* n2*) (n*<= n2* n1*)))]
[lookup
(lambda (n*)
(recur loop ([l n*->d])
(cond
[(null? l) #f]
[(n*= n* (caar l)) (cdar l)]
[else (loop (cdr l))])))]
[traverse
(lambda (n*)
(or (lookup n*)
;; Need to traverse
;; think about epsilon-closure
(let* ([rhs* '()]
[_ (for-each
(lambda (n)
(for-each-prod
(lambda (rhs) (set! rhs* (cons rhs rhs*)))
n))
n*)]
[d (mk-AVS-nolist 'dfa)])
(set! n*->d (cons (cons n* d) n*->d))
(recur loop ([rhs* rhs*])
(match rhs*
[() (void)]
[(($ rhs grsym nt) . _)
;; Merge all with same grsym
(match-let*
([(nt* . rest)
(filter-map-split
(match-lambda
[($ rhs grsym2 nt2)
(if (grsym-eq? grsym grsym2)
nt2
#f)])
rhs*)])
(add-prod! d (make-rhs grsym (traverse nt*)))
(loop rest))]))
d)))])
(traverse (list AVS))
(list (map (lambda (r) (lookup (list r))) roots)
(map (lambda (r) (lookup (list r))) final))))