(load "stacks.scm") ; Problem: Look through a list of strings that represent HTML tags. ; See if they match correct. ; Likely approach for looking at list of anything ; Recurse through the list ; At each step, we see a tag ; (1) opening tag: Push it onto the stack ; (2) closing tag: See if it matches the top of the stack ; Yes -> Go on ; No -> Complain voraciously (define match (lambda (tags) (let ((stack (make-stack))) (letrec ((kernel (lambda (lst) (cond ((null? lst) (stack ':empty?)) ((opening-tag? (car lst)) (stack ':push! (car lst)) (kernel (cdr lst))) (else (cond ((stack ':empty?) #f) ((matching-tags? (stack ':pop!) (car lst)) (kernel (cdr lst))) (else #f))))))) (kernel tags))))) ;;; Procedure: ;;; opening-tag? ;;; Parameters: ;;; tag, a string ;;; Purpose: ;;; Determine if tag is an opening tag. ;;; Produces: ;;; is-tag, a Boolean value ;;; Preconditions: ;;; Must be a tag, that is start with < and end with >. ;;; Postconditions: ;;; [Obvious] (define opening-tag? (lambda (tag) (not (char=? #\/ (string-ref tag 1))))) ;;; Procedure: ;;; matching-tags? ;;; Parameters: ;;; open, a string that represents the opening tag ;;; close, a string that represents the closing tag ;;; Purpose: ;;; Determine if the two tags match. ;;; Produces: ;;; do-they-match?, a Boolean value ;;; Preconditions: ;;; Must be tags. ;;; Open must be an opening tag. ;;; Close must be a closing tag. ;;; Postconditions: ;;; [Someone, somewhere, knows what these are. It will cost you ;;; $100,000 to find out.] (define matching-tags? (lambda (open close) (string-ci=? (substring open 1 (- (string-length open) 1)) (substring close 2 (- (string-length close) 1)))))