elisp updates
[bpt/guile.git] / module / sxml / sxml-match.ss
CommitLineData
400a5dcb
LC
1;; Library: sxml-match
2;; Author: Jim Bender
3;; Version: 1.1, version for PLT Scheme
4;;
5;; Copyright 2005-9, Jim Bender
6;; sxml-match is released under the MIT License
7;;
8(module sxml-match mzscheme
9
10 (provide sxml-match
11 sxml-match-let
12 sxml-match-let*)
13
14 (require (rename (lib "fold.ss" "srfi" "1") fold-right fold-right)
15 (rename (lib "filter.ss" "srfi" "1") filter filter))
16
17 (define (nodeset? x)
18 (or (and (pair? x) (not (symbol? (car x)))) (null? x)))
19
20 (define (xml-element-tag s)
21 (if (and (pair? s) (symbol? (car s)))
22 (car s)
23 (error 'xml-element-tag "expected an xml-element, given" s)))
24
25 (define (xml-element-attributes s)
26 (if (and (pair? s) (symbol? (car s)))
27 (fold-right (lambda (a b)
28 (if (and (pair? a) (eq? '@ (car a)))
29 (if (null? b)
30 (filter (lambda (i) (not (and (pair? i) (eq? '@ (car i))))) (cdr a))
31 (fold-right (lambda (c d)
32 (if (and (pair? c) (eq? '@ (car c)))
33 d
34 (cons c d)))
35 b (cdr a)))
36 b))
37 '()
38 (cdr s))
39 (error 'xml-element-attributes "expected an xml-element, given" s)))
40
41 (define (xml-element-contents s)
42 (if (and (pair? s) (symbol? (car s)))
43 (filter (lambda (i)
44 (not (and (pair? i) (eq? '@ (car i)))))
45 (cdr s))
46 (error 'xml-element-contents "expected an xml-element, given" s)))
47
48 (define (match-xml-attribute key l)
49 (if (not (pair? l))
50 #f
51 (if (eq? (car (car l)) key)
52 (car l)
53 (match-xml-attribute key (cdr l)))))
54
55 (define (filter-attributes keys lst)
56 (if (null? lst)
57 '()
58 (if (member (caar lst) keys)
59 (filter-attributes keys (cdr lst))
60 (cons (car lst) (filter-attributes keys (cdr lst))))))
61
62 (define-syntax compile-clause
63 (lambda (stx)
64 (letrec
65 ([sxml-match-syntax-error
66 (lambda (msg exp sub)
67 (raise-syntax-error #f msg (with-syntax ([s exp]) (syntax (sxml-match s))) sub))]
68 [ellipsis?
69 (lambda (stx)
70 (and (identifier? stx) (eq? '... (syntax-object->datum stx))))]
71 [literal?
72 (lambda (stx)
73 (let ([x (syntax-object->datum stx)])
74 (or (string? x)
75 (char? x)
76 (number? x)
77 (boolean? x))))]
78 [keyword?
79 (lambda (stx)
80 (and (identifier? stx)
81 (let ([str (symbol->string (syntax-object->datum stx))])
82 (char=? #\: (string-ref str (- (string-length str) 1))))))]
83 [extract-cata-fun
84 (lambda (cf)
85 (syntax-case cf ()
86 [#f #f]
87 [other cf]))]
88 [add-pat-var
89 (lambda (pvar pvar-lst)
90 (define (check-pvar lst)
91 (if (null? lst)
92 (void)
93 (if (bound-identifier=? (car lst) pvar)
94 (sxml-match-syntax-error "duplicate pattern variable not allowed"
95 stx
96 pvar)
97 (check-pvar (cdr lst)))))
98 (check-pvar pvar-lst)
99 (cons pvar pvar-lst))]
100 [add-cata-def
101 (lambda (depth cvars cfun ctemp cdefs)
102 (cons (list depth cvars cfun ctemp) cdefs))]
103 [process-cata-exp
104 (lambda (depth cfun ctemp)
105 (if (= depth 0)
106 (with-syntax ([cf cfun]
107 [ct ctemp])
108 (syntax (cf ct)))
109 (let ([new-ctemp (car (generate-temporaries (list ctemp)))])
110 (with-syntax ([ct ctemp]
111 [nct new-ctemp]
112 [body (process-cata-exp (- depth 1) cfun new-ctemp)])
113 (syntax (map (lambda (nct) body) ct))))))]
114 [process-cata-defs
115 (lambda (cata-defs body)
116 (if (null? cata-defs)
117 body
118 (with-syntax ([(cata-binding ...)
119 (map (lambda (def)
120 (with-syntax ([bvar (cadr def)]
121 [bval (process-cata-exp (car def)
122 (caddr def)
123 (cadddr def))])
124 (syntax (bvar bval))))
125 cata-defs)]
126 [body-stx body])
127 (syntax (let-values (cata-binding ...)
128 body-stx)))))]
129 [cata-defs->pvar-lst
130 (lambda (lst)
131 (if (null? lst)
132 '()
133 (let iter ([items (cadr (car lst))])
134 (syntax-case items ()
135 [() (cata-defs->pvar-lst (cdr lst))]
136 [(fst . rst) (cons (syntax fst) (iter (syntax rst)))]))))]
137 [process-output-action
138 (lambda (action dotted-vars)
139 (define (finite-lst? lst)
140 (syntax-case lst ()
141 (item
142 (identifier? (syntax item))
143 #f)
144 (()
145 #t)
146 ((fst dots . rst)
147 (ellipsis? (syntax dots))
148 #f)
149 ((fst . rst)
150 (finite-lst? (syntax rst)))))
151 (define (expand-lst lst)
152 (syntax-case lst ()
153 [() (syntax '())]
154 [item
155 (identifier? (syntax item))
156 (syntax item)]
157 [(fst dots . rst)
158 (ellipsis? (syntax dots))
159 (with-syntax ([exp-lft (expand-dotted-item
160 (process-output-action (syntax fst)
161 dotted-vars))]
162 [exp-rgt (expand-lst (syntax rst))])
163 (syntax (append exp-lft exp-rgt)))]
164 [(fst . rst)
165 (with-syntax ([exp-lft (process-output-action (syntax fst)
166 dotted-vars)]
167 [exp-rgt (expand-lst (syntax rst))])
168 (syntax (cons exp-lft exp-rgt)))]))
169 (define (member-var? var lst)
170 (let iter ([lst lst])
171 (if (null? lst)
172 #f
173 (if (or (bound-identifier=? var (car lst))
174 (free-identifier=? var (car lst)))
175 #t
176 (iter (cdr lst))))))
177 (define (dotted-var? var)
178 (member-var? var dotted-vars))
179 (define (merge-pvars lst1 lst2)
180 (if (null? lst1)
181 lst2
182 (if (member-var? (car lst1) lst2)
183 (merge-pvars (cdr lst1) lst2)
184 (cons (car lst1) (merge-pvars (cdr lst1) lst2)))))
185 (define (select-dotted-vars x)
186 (define (walk-quasi-body y)
187 (syntax-case y (unquote unquote-splicing)
188 [((unquote a) . rst)
189 (merge-pvars (select-dotted-vars (syntax a))
190 (walk-quasi-body (syntax rst)))]
191 [((unquote-splicing a) . rst)
192 (merge-pvars (select-dotted-vars (syntax a))
193 (walk-quasi-body (syntax rst)))]
194 [(fst . rst)
195 (merge-pvars (walk-quasi-body (syntax fst))
196 (walk-quasi-body (syntax rst)))]
197 [other
198 '()]))
199 (syntax-case x (quote quasiquote)
200 [(quote . rst) '()]
201 [(quasiquote . rst) (walk-quasi-body (syntax rst))]
202 [(fst . rst)
203 (merge-pvars (select-dotted-vars (syntax fst))
204 (select-dotted-vars (syntax rst)))]
205 [item
206 (and (identifier? (syntax item))
207 (dotted-var? (syntax item)))
208 (list (syntax item))]
209 [item '()]))
210 (define (expand-dotted-item item)
211 (let ([dvars (select-dotted-vars item)])
212 (syntax-case item ()
213 [x
214 (identifier? (syntax x))
215 (syntax x)]
216 [x (with-syntax ([(dv ...) dvars])
217 (syntax (map (lambda (dv ...) x) dv ...)))])))
218 (define (expand-quasiquote-body x)
219 (syntax-case x (unquote unquote-splicing quasiquote)
220 [(quasiquote . rst) (process-quasiquote x)]
221 [(unquote item)
222 (with-syntax ([expanded-item (process-output-action (syntax item)
223 dotted-vars)])
224 (syntax (unquote expanded-item)))]
225 [(unquote-splicing item)
226 (with-syntax ([expanded-item (process-output-action (syntax item)
227 dotted-vars)])
228 (syntax (unquote-splicing expanded-item)))]
229 [((unquote item) dots . rst)
230 (ellipsis? (syntax dots))
231 (with-syntax ([expanded-item (expand-dotted-item
232 (process-output-action (syntax item)
233 dotted-vars))]
234 [expanded-rst (expand-quasiquote-body (syntax rst))])
235 (syntax ((unquote-splicing expanded-item) . expanded-rst)))]
236 [(item dots . rst)
237 (ellipsis? (syntax dots))
238 (with-syntax ([expanded-item (expand-dotted-item
239 (process-output-action (syntax (quasiquote item))
240 dotted-vars))]
241 [expanded-rst (expand-quasiquote-body (syntax rst))])
242 (syntax ((unquote-splicing expanded-item) . expanded-rst)))]
243 [(fst . rst)
244 (with-syntax ([expanded-fst (expand-quasiquote-body (syntax fst))]
245 [expanded-rst (expand-quasiquote-body (syntax rst))])
246 (syntax (expanded-fst . expanded-rst)))]
247 [other x]))
248 (define (process-quasiquote x)
249 (syntax-case x ()
250 [(quasiquote term) (with-syntax ([expanded-body (expand-quasiquote-body (syntax term))])
251 (syntax (quasiquote expanded-body)))]
252 [else (sxml-match-syntax-error "bad quasiquote-form"
253 stx
254 x)]))
255 (syntax-case action (quote quasiquote)
256 [(quote . rst) action]
257 [(quasiquote . rst) (process-quasiquote action)]
258 [(fst . rst) (if (finite-lst? action)
259 (with-syntax ([exp-lft (process-output-action (syntax fst) dotted-vars)]
260 [exp-rgt (process-output-action (syntax rst) dotted-vars)])
261 (syntax (exp-lft . exp-rgt)))
262 (with-syntax ([exp-lft (process-output-action (syntax fst)
263 dotted-vars)]
264 [exp-rgt (expand-lst (syntax rst))])
265 (syntax (apply exp-lft exp-rgt))))]
266 [item action]))]
267 [compile-element-pat
268 (lambda (ele exp nextp fail-k pvar-lst depth cata-fun cata-defs dotted-vars)
269 (syntax-case ele (@)
270 [(tag (@ . attr-items) . items)
271 (identifier? (syntax tag))
272 (let ([attr-exp (car (generate-temporaries (list exp)))]
273 [body-exp (car (generate-temporaries (list exp)))])
274 (let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
275 (compile-attr-list (syntax attr-items)
276 (syntax items)
277 attr-exp
278 body-exp
279 '()
280 nextp
281 fail-k
282 pvar-lst
283 depth
284 cata-fun
285 cata-defs
286 dotted-vars)])
287 (values (with-syntax ([x exp]
288 [ax attr-exp]
289 [bx body-exp]
290 [body tests]
291 [fail-to fail-k])
292 (syntax (if (and (pair? x) (eq? 'tag (xml-element-tag x)))
293 (let ([ax (xml-element-attributes x)]
294 [bx (xml-element-contents x)])
295 body)
296 (fail-to))))
297 new-pvar-lst
298 new-cata-defs
299 new-dotted-vars)))]
300 [(tag . items)
301 (identifier? (syntax tag))
302 (let ([body-exp (car (generate-temporaries (list exp)))])
303 (let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
304 (compile-item-list (syntax items)
305 body-exp
306 nextp
307 fail-k
308 #t
309 pvar-lst
310 depth
311 cata-fun
312 cata-defs
313 dotted-vars)])
314 (values (with-syntax ([x exp]
315 [bx body-exp]
316 [body tests]
317 [fail-to fail-k])
318 (syntax (if (and (pair? x) (eq? 'tag (xml-element-tag x)))
319 (let ([bx (xml-element-contents x)])
320 body)
321 (fail-to))))
322 new-pvar-lst
323 new-cata-defs
324 new-dotted-vars)))]))]
325 [compile-end-element
326 (lambda (exp nextp fail-k pvar-lst cata-defs dotted-vars)
327 (let-values ([(next-tests new-pvar-lst new-cata-defs new-dotted-vars)
328 (nextp pvar-lst cata-defs dotted-vars)])
329 (values (with-syntax ([x exp]
330 [body next-tests]
331 [fail-to fail-k])
332 (syntax (if (null? x) body (fail-to))))
333 new-pvar-lst
334 new-cata-defs
335 new-dotted-vars)))]
336 [compile-attr-list
337 (lambda (attr-lst body-lst attr-exp body-exp attr-key-lst nextp fail-k pvar-lst depth cata-fun cata-defs dotted-vars)
338 (syntax-case attr-lst (unquote ->)
339 [(unquote var)
340 (identifier? (syntax var))
341 (let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
342 (compile-item-list body-lst
343 body-exp
344 nextp
345 fail-k
346 #t
347 (add-pat-var (syntax var) pvar-lst)
348 depth
349 cata-fun
350 cata-defs
351 dotted-vars)])
352 (values (with-syntax ([ax attr-exp]
353 [matched-attrs attr-key-lst]
354 [body tests])
355 (syntax (let ([var (filter-attributes 'matched-attrs ax)])
356 body)))
357 new-pvar-lst
358 new-cata-defs
359 new-dotted-vars))]
360 [((atag [(unquote [cata -> cvar ...]) default]) . rst)
361 (identifier? (syntax atag))
362 (let ([ctemp (car (generate-temporaries (syntax ([cvar ...]))))])
363 (let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
364 (compile-attr-list (syntax rst)
365 body-lst
366 attr-exp
367 body-exp
368 (cons (syntax atag) attr-key-lst)
369 nextp
370 fail-k
371 (add-pat-var ctemp pvar-lst)
372 depth
373 cata-fun
374 (add-cata-def depth
375 (syntax [cvar ...])
376 (syntax cata)
377 ctemp
378 cata-defs)
379 dotted-vars)])
380 (values (with-syntax ([ax attr-exp]
381 [ct ctemp]
382 [body tests])
383 (syntax (let ([binding (match-xml-attribute 'atag ax)])
384 (let ([ct (if binding
385 (cadr binding)
386 default)])
387 body))))
388 new-pvar-lst
389 new-cata-defs
390 new-dotted-vars)))]
391 [((atag [(unquote [cvar ...]) default]) . rst)
392 (identifier? (syntax atag))
393 (let ([ctemp (car (generate-temporaries (syntax ([cvar ...]))))])
394 (if (not cata-fun)
395 (sxml-match-syntax-error "sxml-match pattern: catamorphism not allowed in this context"
396 stx
397 (syntax [cvar ...])))
398 (let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
399 (compile-attr-list (syntax rst)
400 body-lst
401 attr-exp
402 body-exp
403 (cons (syntax atag) attr-key-lst)
404 nextp
405 fail-k
406 (add-pat-var ctemp pvar-lst)
407 depth
408 cata-fun
409 (add-cata-def depth
410 (syntax [cvar ...])
411 cata-fun
412 ctemp
413 cata-defs)
414 dotted-vars)])
415 (values (with-syntax ([ax attr-exp]
416 [ct ctemp]
417 [body tests])
418 (syntax (let ([binding (match-xml-attribute 'atag ax)])
419 (let ([ct (if binding
420 (cadr binding)
421 default)])
422 body))))
423 new-pvar-lst
424 new-cata-defs
425 new-dotted-vars)))]
426 [((atag [(unquote var) default]) . rst)
427 (and (identifier? (syntax atag)) (identifier? (syntax var)))
428 (let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
429 (compile-attr-list (syntax rst)
430 body-lst
431 attr-exp
432 body-exp
433 (cons (syntax atag) attr-key-lst)
434 nextp
435 fail-k
436 (add-pat-var (syntax var) pvar-lst)
437 depth
438 cata-fun
439 cata-defs
440 dotted-vars)])
441 (values (with-syntax ([ax attr-exp]
442 [body tests])
443 (syntax (let ([binding (match-xml-attribute 'atag ax)])
444 (let ([var (if binding
445 (cadr binding)
446 default)])
447 body))))
448 new-pvar-lst
449 new-cata-defs
450 new-dotted-vars))]
451 [((atag (unquote [cata -> cvar ...])) . rst)
452 (identifier? (syntax atag))
453 (let ([ctemp (car (generate-temporaries (syntax ([cvar ...]))))])
454 (let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
455 (compile-attr-list (syntax rst)
456 body-lst
457 attr-exp
458 body-exp
459 (cons (syntax atag) attr-key-lst)
460 nextp
461 fail-k
462 (add-pat-var ctemp pvar-lst)
463 depth
464 cata-fun
465 (add-cata-def depth
466 (syntax [cvar ...])
467 (syntax cata)
468 ctemp
469 cata-defs)
470 dotted-vars)])
471 (values (with-syntax ([ax attr-exp]
472 [ct ctemp]
473 [body tests]
474 [fail-to fail-k])
475 (syntax (let ([binding (match-xml-attribute 'atag ax)])
476 (if binding
477 (let ([ct (cadr binding)])
478 body)
479 (fail-to)))))
480 new-pvar-lst
481 new-cata-defs
482 new-dotted-vars)))]
483 [((atag (unquote [cvar ...])) . rst)
484 (identifier? (syntax atag))
485 (let ([ctemp (car (generate-temporaries (syntax ([cvar ...]))))])
486 (if (not cata-fun)
487 (sxml-match-syntax-error "sxml-match pattern: catamorphism not allowed in this context"
488 stx
489 (syntax [cvar ...])))
490 (let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
491 (compile-attr-list (syntax rst)
492 body-lst
493 attr-exp
494 body-exp
495 (cons (syntax atag) attr-key-lst)
496 nextp
497 fail-k
498 (add-pat-var ctemp pvar-lst)
499 depth
500 cata-fun
501 (add-cata-def depth
502 (syntax [cvar ...])
503 cata-fun
504 ctemp
505 cata-defs)
506 dotted-vars)])
507 (values (with-syntax ([ax attr-exp]
508 [ct ctemp]
509 [body tests]
510 [fail-to fail-k])
511 (syntax (let ([binding (match-xml-attribute 'atag ax)])
512 (if binding
513 (let ([ct (cadr binding)])
514 body)
515 (fail-to)))))
516 new-pvar-lst
517 new-cata-defs
518 new-dotted-vars)))]
519 [((atag (unquote var)) . rst)
520 (and (identifier? (syntax atag)) (identifier? (syntax var)))
521 (let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
522 (compile-attr-list (syntax rst)
523 body-lst
524 attr-exp
525 body-exp
526 (cons (syntax atag) attr-key-lst)
527 nextp
528 fail-k
529 (add-pat-var (syntax var) pvar-lst)
530 depth
531 cata-fun
532 cata-defs
533 dotted-vars)])
534 (values (with-syntax ([ax attr-exp]
535 [body tests]
536 [fail-to fail-k])
537 (syntax (let ([binding (match-xml-attribute 'atag ax)])
538 (if binding
539 (let ([var (cadr binding)])
540 body)
541 (fail-to)))))
542 new-pvar-lst
543 new-cata-defs
544 new-dotted-vars))]
545 [((atag (i ...)) . rst)
546 (identifier? (syntax atag))
547 (sxml-match-syntax-error "bad attribute pattern"
548 stx
549 (syntax (kwd (i ...))))]
550 [((atag i) . rst)
551 (and (identifier? (syntax atag)) (identifier? (syntax i)))
552 (sxml-match-syntax-error "bad attribute pattern"
553 stx
554 (syntax (kwd i)))]
555 [((atag literal) . rst)
556 (and (identifier? (syntax atag)) (literal? (syntax literal)))
557 (let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
558 (compile-attr-list (syntax rst)
559 body-lst
560 attr-exp
561 body-exp
562 (cons (syntax atag) attr-key-lst)
563 nextp
564 fail-k
565 pvar-lst
566 depth
567 cata-fun
568 cata-defs
569 dotted-vars)])
570 (values (with-syntax ([ax attr-exp]
571 [body tests]
572 [fail-to fail-k])
573 (syntax (let ([binding (match-xml-attribute 'atag ax)])
574 (if binding
575 (if (equal? (cadr binding) literal)
576 body
577 (fail-to))
578 (fail-to)))))
579 new-pvar-lst
580 new-cata-defs
581 new-dotted-vars))]
582 [()
583 (compile-item-list body-lst
584 body-exp
585 nextp
586 fail-k
587 #t
588 pvar-lst
589 depth
590 cata-fun
591 cata-defs
592 dotted-vars)]))]
593 [compile-item-list
594 (lambda (lst exp nextp fail-k ellipsis-allowed? pvar-lst depth cata-fun cata-defs dotted-vars)
595 (syntax-case lst (unquote ->)
596 [() (compile-end-element exp nextp fail-k pvar-lst cata-defs dotted-vars)]
597 [(unquote var)
598 (identifier? (syntax var))
599 (if (not ellipsis-allowed?)
600 (sxml-match-syntax-error "improper list pattern not allowed in this context"
601 stx
602 (syntax dots))
603 (let-values ([(next-tests new-pvar-lst new-cata-defs new-dotted-vars)
604 (nextp (add-pat-var (syntax var) pvar-lst) cata-defs dotted-vars)])
605 (values (with-syntax ([x exp]
606 [body next-tests])
607 (syntax (let ([var x]) body)))
608 new-pvar-lst
609 new-cata-defs
610 new-dotted-vars)))]
611 [(unquote [cata -> cvar ...])
612 (if (not ellipsis-allowed?)
613 (sxml-match-syntax-error "improper list pattern not allowed in this context"
614 stx
615 (syntax dots))
616 (let ([ctemp (car (generate-temporaries (syntax ([cvar ...]))))])
617 (let-values ([(next-tests new-pvar-lst new-cata-defs new-dotted-vars)
618 (nextp (add-pat-var ctemp pvar-lst)
619 (add-cata-def depth
620 (syntax [cvar ...])
621 (syntax cata)
622 ctemp
623 cata-defs)
624 dotted-vars)])
625 (values (with-syntax ([ct ctemp]
626 [x exp]
627 [body next-tests])
628 (syntax (let ([ct x]) body)))
629 new-pvar-lst
630 new-cata-defs
631 new-dotted-vars))))]
632 [(unquote [cvar ...])
633 (let ([ctemp (car (generate-temporaries (syntax ([cvar ...]))))])
634 (if (not cata-fun)
635 (sxml-match-syntax-error "sxml-match pattern: catamorphism not allowed in this context"
636 stx
637 (syntax [cvar ...])))
638 (let-values ([(next-tests new-pvar-lst new-cata-defs new-dotted-vars)
639 (nextp (add-pat-var ctemp pvar-lst)
640 (add-cata-def depth
641 (syntax [cvar ...])
642 cata-fun
643 ctemp
644 cata-defs)
645 dotted-vars)])
646 (values (with-syntax ([ct ctemp]
647 [x exp]
648 [body next-tests])
649 (syntax (let ([ct x]) body)))
650 new-pvar-lst
651 new-cata-defs
652 new-dotted-vars)))]
653 [(item dots . rst)
654 (ellipsis? (syntax dots))
655 (if (not ellipsis-allowed?)
656 (sxml-match-syntax-error "ellipses not allowed in this context"
657 stx
658 (syntax dots))
659 (compile-dotted-pattern-list (syntax item)
660 (syntax rst)
661 exp
662 nextp
663 fail-k
664 pvar-lst
665 depth
666 cata-fun
667 cata-defs
668 dotted-vars))]
669 [(item . rst)
670 (compile-item (syntax item)
671 exp
672 (lambda (new-exp new-pvar-lst new-cata-defs new-dotted-vars)
673 (compile-item-list (syntax rst)
674 new-exp
675 nextp
676 fail-k
677 ellipsis-allowed?
678 new-pvar-lst
679 depth
680 cata-fun
681 new-cata-defs
682 new-dotted-vars))
683 fail-k
684 pvar-lst
685 depth
686 cata-fun
687 cata-defs
688 dotted-vars)]))]
689 [compile-dotted-pattern-list
690 (lambda (item
691 tail
692 exp
693 nextp
694 fail-k
695 pvar-lst
696 depth
697 cata-fun
698 cata-defs
699 dotted-vars)
700 (let-values ([(tail-tests tail-pvar-lst tail-cata-defs tail-dotted-vars)
701 (compile-item-list tail
702 (syntax lst)
703 (lambda (new-pvar-lst new-cata-defs new-dotted-vars)
704 (values (with-syntax ([(npv ...) new-pvar-lst])
705 (syntax (values #t npv ...)))
706 new-pvar-lst
707 new-cata-defs
708 new-dotted-vars))
709 (syntax fail)
710 #f
711 '()
712 depth
713 '()
714 '()
715 dotted-vars)]
716 [(item-tests item-pvar-lst item-cata-defs item-dotted-vars)
717 (compile-item item
718 (syntax lst)
719 (lambda (new-exp new-pvar-lst new-cata-defs new-dotted-vars)
720 (values (with-syntax ([(npv ...) new-pvar-lst])
721 (syntax (values #t (cdr lst) npv ...)))
722 new-pvar-lst
723 new-cata-defs
724 new-dotted-vars))
725 (syntax fail)
726 '()
727 (+ 1 depth)
728 cata-fun
729 '()
730 dotted-vars)])
731 ; more here: check for duplicate pat-vars, cata-defs
732 (let-values ([(final-tests final-pvar-lst final-cata-defs final-dotted-vars)
733 (nextp (append tail-pvar-lst item-pvar-lst pvar-lst)
734 (append tail-cata-defs item-cata-defs cata-defs)
735 (append item-pvar-lst
736 (cata-defs->pvar-lst item-cata-defs)
737 tail-dotted-vars
738 dotted-vars))])
739 (let ([temp-item-pvar-lst (generate-temporaries item-pvar-lst)])
740 (values
741 (with-syntax
742 ([x exp]
743 [fail-to fail-k]
744 [tail-body tail-tests]
745 [item-body item-tests]
746 [final-body final-tests]
747 [(ipv ...) item-pvar-lst]
748 [(gpv ...) temp-item-pvar-lst]
749 [(tpv ...) tail-pvar-lst]
750 [(item-void ...) (map (lambda (i) (syntax (void))) item-pvar-lst)]
751 [(tail-void ...) (map (lambda (i) (syntax (void))) tail-pvar-lst)]
752 [(item-null ...) (map (lambda (i) (syntax '())) item-pvar-lst)]
753 [(item-cons ...) (map (lambda (a b)
754 (with-syntax ([xa a]
755 [xb b])
756 (syntax (cons xa xb))))
757 item-pvar-lst
758 temp-item-pvar-lst)])
759 (syntax (letrec ([match-tail
760 (lambda (lst fail)
761 tail-body)]
762 [match-item
763 (lambda (lst)
764 (let ([fail (lambda ()
765 (values #f
766 lst
767 item-void ...))])
768 item-body))]
769 [match-dotted
770 (lambda (x)
771 (let-values ([(tail-res tpv ...)
772 (match-tail x
773 (lambda ()
774 (values #f
775 tail-void ...)))])
776 (if tail-res
777 (values item-null ...
778 tpv ...)
779 (let-values ([(res new-x ipv ...) (match-item x)])
780 (if res
781 (let-values ([(gpv ... tpv ...)
782 (match-dotted new-x)])
783 (values item-cons ... tpv ...))
784 (let-values ([(last-tail-res tpv ...)
785 (match-tail x fail-to)])
786 (values item-null ... tpv ...)))))))])
787 (let-values ([(ipv ... tpv ...)
788 (match-dotted x)])
789 final-body))))
790 final-pvar-lst
791 final-cata-defs
792 final-dotted-vars)))))]
793 [compile-item
794 (lambda (item exp nextp fail-k pvar-lst depth cata-fun cata-defs dotted-vars)
795 (syntax-case item (unquote ->)
796 ; normal pattern var
797 [(unquote var)
798 (identifier? (syntax var))
799 (let ([new-exp (car (generate-temporaries (list exp)))])
800 (let-values ([(next-tests new-pvar-lst new-cata-defs new-dotted-vars)
801 (nextp new-exp (add-pat-var (syntax var) pvar-lst) cata-defs dotted-vars)])
802 (values (with-syntax ([x exp]
803 [nx new-exp]
804 [body next-tests]
805 [fail-to fail-k])
806 (syntax (if (pair? x)
807 (let ([nx (cdr x)]
808 [var (car x)])
809 body)
810 (fail-to))))
811 new-pvar-lst
812 new-cata-defs
813 new-dotted-vars)))]
814 ; named catamorphism
815 [(unquote [cata -> cvar ...])
816 (let ([new-exp (car (generate-temporaries (list exp)))]
817 [ctemp (car (generate-temporaries (syntax ([cvar ...]))))])
818 (let-values ([(next-tests new-pvar-lst new-cata-defs new-dotted-vars)
819 (nextp new-exp
820 (add-pat-var ctemp pvar-lst)
821 (add-cata-def depth
822 (syntax [cvar ...])
823 (syntax cata)
824 ctemp
825 cata-defs)
826 dotted-vars)])
827 (values (with-syntax ([x exp]
828 [nx new-exp]
829 [ct ctemp]
830 [body next-tests]
831 [fail-to fail-k])
832 (syntax (if (pair? x)
833 (let ([nx (cdr x)]
834 [ct (car x)])
835 body)
836 (fail-to))))
837 new-pvar-lst
838 new-cata-defs
839 new-dotted-vars)))]
840 ; basic catamorphism
841 [(unquote [cvar ...])
842 (let ([new-exp (car (generate-temporaries (list exp)))]
843 [ctemp (car (generate-temporaries (syntax ([cvar ...]))))])
844 (if (not cata-fun)
845 (sxml-match-syntax-error "sxml-match pattern: catamorphism not allowed in this context"
846 stx
847 (syntax [cvar ...])))
848 (let-values ([(next-tests new-pvar-lst new-cata-defs new-dotted-vars)
849 (nextp new-exp
850 (add-pat-var ctemp pvar-lst)
851 (add-cata-def depth
852 (syntax [cvar ...])
853 cata-fun
854 ctemp
855 cata-defs)
856 dotted-vars)])
857 (values (with-syntax ([x exp]
858 [nx new-exp]
859 [ct ctemp]
860 [body next-tests]
861 [fail-to fail-k])
862 (syntax (if (pair? x)
863 (let ([nx (cdr x)]
864 [ct (car x)])
865 body)
866 (fail-to))))
867 new-pvar-lst
868 new-cata-defs
869 new-dotted-vars)))]
870 [(tag item ...)
871 (identifier? (syntax tag))
872 (let ([new-exp (car (generate-temporaries (list exp)))])
873 (let-values ([(after-tests after-pvar-lst after-cata-defs after-dotted-vars)
874 (compile-element-pat (syntax (tag item ...))
875 (with-syntax ([x exp])
876 (syntax (car x)))
877 (lambda (more-pvar-lst more-cata-defs more-dotted-vars)
878 (let-values ([(next-tests new-pvar-lst
879 new-cata-defs
880 new-dotted-vars)
881 (nextp new-exp
882 more-pvar-lst
883 more-cata-defs
884 more-dotted-vars)])
885 (values (with-syntax ([x exp]
886 [nx new-exp]
887 [body next-tests])
888 (syntax (let ([nx (cdr x)])
889 body)))
890 new-pvar-lst
891 new-cata-defs
892 new-dotted-vars)))
893 fail-k
894 pvar-lst
895 depth
896 cata-fun
897 cata-defs
898 dotted-vars)])
899 ; test that we are not at the end of an item-list, BEFORE
900 ; entering tests for the element pattern (against the 'car' of the item-list)
901 (values (with-syntax ([x exp]
902 [body after-tests]
903 [fail-to fail-k])
904 (syntax (if (pair? x)
905 body
906 (fail-to))))
907 after-pvar-lst
908 after-cata-defs
909 after-dotted-vars)))]
910 [(i ...)
911 (sxml-match-syntax-error "bad pattern syntax (not an element pattern)"
912 stx
913 (syntax (i ...)))]
914 [i
915 (identifier? (syntax i))
916 (sxml-match-syntax-error "bad pattern syntax (symbol not allowed in this context)"
917 stx
918 (syntax i))]
919 [literal
920 (literal? (syntax literal))
921 (let ([new-exp (car (generate-temporaries (list exp)))])
922 (let-values ([(next-tests new-pvar-lst new-cata-defs new-dotted-vars)
923 (nextp new-exp pvar-lst cata-defs dotted-vars)])
924 (values (with-syntax ([x exp]
925 [nx new-exp]
926 [body next-tests]
927 [fail-to fail-k])
928 (syntax (if (and (pair? x) (equal? literal (car x)))
929 (let ([nx (cdr x)])
930 body)
931 (fail-to))))
932 new-pvar-lst
933 new-cata-defs
934 new-dotted-vars)))]))])
935 (let ([fail-k (syntax failure)])
936 (syntax-case stx (unquote guard ->)
937 [(compile-clause ((unquote var) (guard gexp ...) action0 action ...)
938 exp
939 cata-fun
940 fail-exp)
941 (identifier? (syntax var))
942 (syntax (let ([var exp])
943 (if (and gexp ...)
944 (begin action0 action ...)
945 (fail-exp))))]
946 [(compile-clause ((unquote [cata -> cvar ...]) (guard gexp ...) action0 action ...)
947 exp
948 cata-fun
949 fail-exp)
950 (syntax (if (and gexp ...)
951 (let-values ([(cvar ...) (cata exp)])
952 (begin action0 action ...))
953 (fail-exp)))]
954 [(compile-clause ((unquote [cvar ...]) (guard gexp ...) action0 action ...)
955 exp
956 cata-fun
957 fail-exp)
958 (if (not (extract-cata-fun (syntax cata-fun)))
959 (sxml-match-syntax-error "sxml-match pattern: catamorphism not allowed in this context"
960 stx
961 (syntax [cvar ...]))
962 (syntax (if (and gexp ...)
963 (let-values ([(cvar ...) (cata-fun exp)])
964 (begin action0 action ...))
965 (fail-exp))))]
966 [(compile-clause ((unquote var) action0 action ...) exp cata-fun fail-exp)
967 (identifier? (syntax var))
968 (syntax (let ([var exp])
969 action0 action ...))]
970 [(compile-clause ((unquote [cata -> cvar ...]) action0 action ...) exp cata-fun fail-exp)
971 (syntax (let-values ([(cvar ...) (cata exp)])
972 action0 action ...))]
973 [(compile-clause ((unquote [cvar ...]) action0 action ...) exp cata-fun fail-exp)
974 (if (not (extract-cata-fun (syntax cata-fun)))
975 (sxml-match-syntax-error "sxml-match pattern: catamorphism not allowed in this context"
976 stx
977 (syntax [cvar ...]))
978 (syntax (let-values ([(cvar ...) (cata-fun exp)])
979 action0 action ...)))]
980 [(compile-clause ((lst . rst) (guard gexp ...) action0 action ...) exp cata-fun fail-exp)
981 (and (identifier? (syntax lst)) (eq? 'list (syntax-object->datum (syntax lst))))
982 (let-values ([(result pvar-lst cata-defs dotted-vars)
983 (compile-item-list (syntax rst)
984 (syntax exp)
985 (lambda (new-pvar-lst new-cata-defs new-dotted-vars)
986 (values
987 (with-syntax
988 ([exp-body (process-cata-defs new-cata-defs
989 (process-output-action
990 (syntax (begin action0
991 action ...))
992 new-dotted-vars))]
993 [fail-to fail-k])
994 (syntax (if (and gexp ...) exp-body (fail-to))))
995 new-pvar-lst
996 new-cata-defs
997 new-dotted-vars))
998 fail-k
999 #t
1000 '()
1001 0
1002 (extract-cata-fun (syntax cata-fun))
1003 '()
1004 '())])
1005 (with-syntax ([fail-to fail-k]
1006 [body result])
1007 (syntax (let ([fail-to fail-exp])
1008 (if (nodeset? exp)
1009 body
1010 (fail-to))))))]
1011 [(compile-clause ((lst . rst) action0 action ...) exp cata-fun fail-exp)
1012 (and (identifier? (syntax lst)) (eq? 'list (syntax-object->datum (syntax lst))))
1013 (let-values ([(result pvar-lst cata-defs dotted-vars)
1014 (compile-item-list (syntax rst)
1015 (syntax exp)
1016 (lambda (new-pvar-lst new-cata-defs new-dotted-vars)
1017 (values (process-cata-defs new-cata-defs
1018 (process-output-action
1019 (syntax (begin action0
1020 action ...))
1021 new-dotted-vars))
1022 new-pvar-lst
1023 new-cata-defs
1024 new-dotted-vars))
1025 fail-k
1026 #t
1027 '()
1028 0
1029 (extract-cata-fun (syntax cata-fun))
1030 '()
1031 '())])
1032 (with-syntax ([body result]
1033 [fail-to fail-k])
1034 (syntax (let ([fail-to fail-exp])
1035 (if (nodeset? exp)
1036 body
1037 (fail-to))))))]
1038 [(compile-clause ((fst . rst) (guard gexp ...) action0 action ...) exp cata-fun fail-exp)
1039 (identifier? (syntax fst))
1040 (let-values ([(result pvar-lst cata-defs dotted-vars)
1041 (compile-element-pat (syntax (fst . rst))
1042 (syntax exp)
1043 (lambda (new-pvar-lst new-cata-defs new-dotted-vars)
1044 (values
1045 (with-syntax
1046 ([body (process-cata-defs new-cata-defs
1047 (process-output-action
1048 (syntax (begin action0
1049 action ...))
1050 new-dotted-vars))]
1051 [fail-to fail-k])
1052 (syntax (if (and gexp ...) body (fail-to))))
1053 new-pvar-lst
1054 new-cata-defs
1055 new-dotted-vars))
1056 fail-k
1057 '()
1058 0
1059 (extract-cata-fun (syntax cata-fun))
1060 '()
1061 '())])
1062 (with-syntax ([fail-to fail-k]
1063 [body result])
1064 (syntax (let ([fail-to fail-exp])
1065 body))))]
1066 [(compile-clause ((fst . rst) action0 action ...) exp cata-fun fail-exp)
1067 (identifier? (syntax fst))
1068 (let-values ([(result pvar-lst cata-defs dotted-vars)
1069 (compile-element-pat (syntax (fst . rst))
1070 (syntax exp)
1071 (lambda (new-pvar-lst new-cata-defs new-dotted-vars)
1072 (values (process-cata-defs new-cata-defs
1073 (process-output-action
1074 (syntax (begin action0
1075 action ...))
1076 new-dotted-vars))
1077 new-pvar-lst
1078 new-cata-defs
1079 new-dotted-vars))
1080 fail-k
1081 '()
1082 0
1083 (extract-cata-fun (syntax cata-fun))
1084 '()
1085 '())])
1086 (with-syntax ([fail-to fail-k]
1087 [body result])
1088 (syntax (let ([fail-to fail-exp])
1089 body))))]
1090 [(compile-clause ((i ...) (guard gexp ...) action0 action ...) exp cata-fun fail-exp)
1091 (sxml-match-syntax-error "bad pattern syntax (not an element pattern)"
1092 stx
1093 (syntax (i ...)))]
1094 [(compile-clause ((i ...) action0 action ...) exp cata-fun fail-exp)
1095 (sxml-match-syntax-error "bad pattern syntax (not an element pattern)"
1096 stx
1097 (syntax (i ...)))]
1098 [(compile-clause (pat (guard gexp ...) action0 action ...) exp cata-fun fail-exp)
1099 (identifier? (syntax pat))
1100 (sxml-match-syntax-error "bad pattern syntax (symbol not allowed in this context)"
1101 stx
1102 (syntax pat))]
1103 [(compile-clause (pat action0 action ...) exp cata-fun fail-exp)
1104 (identifier? (syntax pat))
1105 (sxml-match-syntax-error "bad pattern syntax (symbol not allowed in this context)"
1106 stx
1107 (syntax pat))]
1108 [(compile-clause (literal (guard gexp ...) action0 action ...) exp cata-fun fail-exp)
1109 (literal? (syntax literal))
1110 (syntax (if (and (equal? literal exp) (and gexp ...))
1111 (begin action0 action ...)
1112 (fail-exp)))]
1113 [(compile-clause (literal action0 action ...) exp cata-fun fail-exp)
1114 (literal? (syntax literal))
1115 (syntax (if (equal? literal exp)
1116 (begin action0 action ...)
1117 (fail-exp)))])))))
1118
1119 (define-syntax sxml-match1
1120 (syntax-rules ()
1121 [(sxml-match1 exp cata-fun clause)
1122 (compile-clause clause exp cata-fun
1123 (lambda () (error 'sxml-match "no matching clause found")))]
1124 [(sxml-match1 exp cata-fun clause0 clause ...)
1125 (let/ec escape
1126 (compile-clause clause0 exp cata-fun
01fded8c
LC
1127 (lambda () (call-with-values
1128 (lambda () (sxml-match1 exp cata-fun
1129 clause ...))
1130 escape))))]))
400a5dcb
LC
1131
1132 (define-syntax sxml-match
1133 (syntax-rules ()
1134 ((sxml-match val clause0 clause ...)
1135 (letrec ([cfun (lambda (exp)
1136 (sxml-match1 exp cfun clause0 clause ...))])
1137 (cfun val)))))
1138
1139 (define-syntax sxml-match-let1
1140 (syntax-rules ()
1141 [(sxml-match-let1 syntag synform () body0 body ...)
1142 (let () body0 body ...)]
1143 [(sxml-match-let1 syntag synform ([pat exp]) body0 body ...)
1144 (compile-clause (pat (let () body0 body ...))
1145 exp
1146 #f
1147 (lambda () (error 'syntag "could not match pattern ~s" 'pat)))]
1148 [(sxml-match-let1 syntag synform ([pat0 exp0] [pat exp] ...) body0 body ...)
1149 (compile-clause (pat0 (sxml-match-let1 syntag synform ([pat exp] ...) body0 body ...))
1150 exp0
1151 #f
1152 (lambda () (error 'syntag "could not match pattern ~s" 'pat0)))]))
1153
1154 (define-syntax sxml-match-let-help
1155 (lambda (stx)
1156 (syntax-case stx ()
1157 [(sxml-match-let-help syntag synform ([pat exp] ...) body0 body ...)
1158 (with-syntax ([(temp-name ...) (generate-temporaries (syntax (exp ...)))])
1159 (syntax (let ([temp-name exp] ...)
1160 (sxml-match-let1 syntag synform ([pat temp-name] ...) body0 body ...))))])))
1161
1162 (define-syntax sxml-match-let
1163 (lambda (stx)
1164 (syntax-case stx ()
1165 [(sxml-match-let ([pat exp] ...) body0 body ...)
1166 (with-syntax ([synform stx])
1167 (syntax (sxml-match-let-help sxml-match-let synform ([pat exp] ...) body0 body ...)))])))
1168
1169 (define-syntax sxml-match-let*
1170 (lambda (stx)
1171 (syntax-case stx ()
1172 [(sxml-match-let* () body0 body ...)
1173 (syntax (let () body0 body ...))]
1174 [(sxml-match-let* ([pat0 exp0] [pat exp] ...) body0 body ...)
1175 (with-syntax ([synform stx])
1176 (syntax (sxml-match-let-help sxml-match-let* synform ([pat0 exp0])
1177 (sxml-match-let* ([pat exp] ...)
1178 body0 body ...))))])))
1179
1180 )
1181