Commit | Line | Data |
---|---|---|
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 |