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