#lang scheme ; An xnode is: ; - an string, or ; - a xtag ; An xtag is: ; (make-xtag symbol (list-of xnode)) (define-struct xtag (tag contents)) ; A list-of xnode is: ; - empty, or ; - (cons xnode list-of-xnode) ;; Examples of the data: ;; xnode: (define x1 "hello there") (define x2 (make-xtag 'em (list "wowy zowy"))) (define x3 (make-xtag 'p (list "hello" (make-xtag 'em (list "wowy zowy"))))) ;; Here is the result of parsing a string: "

hi to all the very very very

" (make-xtag 'p (list (make-xtag 'em (list "hi")) " to all the " (make-xtag 'b (list "very " (make-xtag 'b (list "very " (make-xtag 'b (list (make-xtag 'b (list "very")))))))))) ;;; Scheme note: We'd like to use the `quote` syntax for a list; ;;; however that's difficult since the list contains more than just strings/symbols; ;;; it contains calls to make-xtag. And the `quote` syntax will treat everything ;;; inside the list as a quoted value. ;;; Scheme's solution: back-quote (aka "quasiquote"). ;;; This is *similar* to quote, except that you can *unquote* an item by using a comma: ;;; Example: `(3 4 ,(+ 5 6)) = '(3 4 11). ;;; Note that it starts with a *back*quote (`), not a regular single quote ('). ;;; Then, the expression (+ 5 6) is actually evaluated, not quoted. ;;; (Question: what if you said the same thing with regular quote? ;;; Try it -- see what '(3 4 (+ 5 6)) returns.) ;;; ;;; Now that we know about backquote, we can use this succinct notation for the above xtag: (make-xtag 'p `(,(make-xtag 'em `("hi")) " to all the " ,(make-xtag 'b `("very " ,(make-xtag 'b `("very " ,(make-xtag 'b `(,(make-xtag 'b `("very")))))))))) (define (xnode->string x) (cond [(string? x) x] [(xtag? x) (string-append "<" (symbol->string (xtag-tag x)) ">" (foldl (lambda (f rr) (string-append (xnode->string f) rr)) "" (xtag-contents x)) ; Instead of foldl, it'd also be idiomatic to say: #;(apply string-append (map xnode->string (xtag-contents x))) "string (xtag-tag x)) ">")]))