Thank you. Reading the match docs, I didn't infer the significance of quasipatterns for XML parsing.
On Tue, Jun 25, 2013 at 6:14 AM, Matthias Felleisen <matth...@ccs.neu.edu>wrote: > > On Jun 24, 2013, at 9:52 PM, Matthew Butterick wrote: > > > I've seen this technique recommended numerous times. Would anyone have a > link to an idiomatic example of the technique in use? Thank you. > > ____________________ > > Racket Users list: > > http://lists.racket-lang.org/users > > > Your question is somewhat generic. So here is a generic answer: > > #lang racket > > (require xml) > > (module+ test > (require rackunit)) > > ;; > ----------------------------------------------------------------------------- > ;; recognizing an XML that belongs to a grammar > > ;; E = <plus>E E</plus> | <number value=String /> > > (define (ex i) (format "<number value =\"~a\" />" i)) > (define (ex2 i j) (string-append "<plus>" (ex i) (ex j) "</plus>")) > > ;; String -> Boolean > ;; does E produce e? > > (module+ test > (check-true (parse (ex2 5 42))) > (check-false (parse (ex "hello world"))) > (check-false (parse (ex2 5 "hello world")))) > > (define (parse e:str) > (define e:xml (read-xml/element (open-input-string e:str))) > (define e:xexpr (xml->xexpr e:xml)) > (let parse ((e e:xexpr)) > (match e > [`(number ((value ,v))) (number? (string->number v))] > [`(plus () ,e1 ,e2) (and (parse e1) (parse e2))] > [else #f]))) > > ;; > ----------------------------------------------------------------------------- > ;; creating a parse tree for a valid XML > > ;; A = Number | (list '+ Number Number) > > ;; String -> [maybe/c A] > ;; does E produce e? if so, create an a, otherwise #f > > (module+ test > (check-equal? (parse-to (ex2 5 42)) '(+ 5 42)) > (check-false (parse-to (ex "hello world"))) > (check-false (parse-to (ex2 5 "hello world")))) > > (define (parse-to e:str) > (define e:xml (read-xml/element (open-input-string e:str))) > (define e:xexpr (xml->xexpr e:xml)) > (let parse ((e e:xexpr)) > (match e > [`(number ((value ,v))) > (define x (string->number v)) > (if (number? x) x #f)] > [`(plus () ,e1 ,e2) > (define p1 (parse e1)) > (cond > [(boolean? p1) #f] > [else (define p2 (parse e2)) > (and p2 `(+ ,p1 ,p2))])] > [else #f]))) > > I have not include exception handling for invalid and/or incomplete XML > strings. > I have also skipped treatment of white space. > > I tend to create macros with which I can specify X-expression grammars > so that I can easily write down parsers and unparsers. That way I don't > ever see match in real code: > > (define (state-writer s) > (state->xexpr s)) > > (define state-parser > (xml-parser (state () (b board-parser) (p player-parser) ... #:action > (*create-state b p)))) > > (module+ test > (check-equal? (state-parser (state-writer s0)) s0) > (check-equal? (state-parser (state-writer s1)) s1)) > > These are from a recent game. The tests ensure that the two functions are > compatible. > > -- Matthias > >
____________________ Racket Users list: http://lists.racket-lang.org/users