[racket] examples of parsing XML with match?

From: Matthew Butterick (mb.list.acct at gmail.com)
Date: Tue Jun 25 13:07:56 EDT 2013

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 <matthias at 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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20130625/ee25fc2c/attachment.html>

Posted on the users mailing list.