[racket] examples of parsing XML with match?
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>