1228 lines
66 KiB
Scheme
1228 lines
66 KiB
Scheme
|
;; Library: sxml-match
|
|||
|
;; Author: Jim Bender
|
|||
|
;; Version: 1.1, version for PLT Scheme
|
|||
|
;;
|
|||
|
;; Copyright 2005-9, Jim Bender
|
|||
|
;; sxml-match is released under the MIT License
|
|||
|
;;
|
|||
|
|
|||
|
(define-module (sxml-match)
|
|||
|
#:export (sxml-match
|
|||
|
sxml-match-let
|
|||
|
sxml-match-let*)
|
|||
|
#:use-module (srfi srfi-1)
|
|||
|
#:use-module (srfi srfi-11))
|
|||
|
|
|||
|
|
|||
|
;;;
|
|||
|
;;; PLT compatibility layer.
|
|||
|
;;;
|
|||
|
|
|||
|
(define-syntax syntax-object->datum
|
|||
|
(syntax-rules ()
|
|||
|
((_ stx)
|
|||
|
(syntax->datum stx))))
|
|||
|
|
|||
|
(define-syntax void
|
|||
|
(syntax-rules ()
|
|||
|
((_) *unspecified*)))
|
|||
|
|
|||
|
(define-syntax call/ec
|
|||
|
;; aka. `call-with-escape-continuation'
|
|||
|
(syntax-rules ()
|
|||
|
((_ proc)
|
|||
|
(let ((prompt (gensym)))
|
|||
|
(call-with-prompt prompt
|
|||
|
(lambda ()
|
|||
|
(proc (lambda args
|
|||
|
(apply abort-to-prompt
|
|||
|
prompt args))))
|
|||
|
(lambda (k . args)
|
|||
|
(apply values args)))))))
|
|||
|
|
|||
|
(define-syntax let/ec
|
|||
|
(syntax-rules ()
|
|||
|
((_ cont body ...)
|
|||
|
(call/ec (lambda (cont) body ...)))))
|
|||
|
|
|||
|
(define (raise-syntax-error x msg obj sub)
|
|||
|
(throw 'sxml-match-error x msg obj sub))
|
|||
|
|
|||
|
|
|||
|
;;;
|
|||
|
;;; Body, unmodified from
|
|||
|
;;; http://planet.plt-scheme.org/package-source/jim/sxml-match.plt/1/1/sxml-match.ss
|
|||
|
;;; except for:
|
|||
|
;;;
|
|||
|
;;; 1. The PLT-specific `module' form.
|
|||
|
;;;
|
|||
|
;;; 2. In `sxml-match1', ESCAPE is called with `call-with-values' instead
|
|||
|
;;; of being called "normally", such that the example below returns the
|
|||
|
;;; values `x' and `y' instead of just `x':
|
|||
|
;;;
|
|||
|
;;; (sxml-match '(foo) ((bar) (values 'p 'q)) ((foo) (values 'x 'y)))
|
|||
|
;;;
|
|||
|
|
|||
|
(define (nodeset? x)
|
|||
|
(or (and (pair? x) (not (symbol? (car x)))) (null? x)))
|
|||
|
|
|||
|
(define (xml-element-tag s)
|
|||
|
(if (and (pair? s) (symbol? (car s)))
|
|||
|
(car s)
|
|||
|
(error 'xml-element-tag "expected an xml-element, given" s)))
|
|||
|
|
|||
|
(define (xml-element-attributes s)
|
|||
|
(if (and (pair? s) (symbol? (car s)))
|
|||
|
(fold-right (lambda (a b)
|
|||
|
(if (and (pair? a) (eq? '@ (car a)))
|
|||
|
(if (null? b)
|
|||
|
(filter (lambda (i) (not (and (pair? i) (eq? '@ (car i))))) (cdr a))
|
|||
|
(fold-right (lambda (c d)
|
|||
|
(if (and (pair? c) (eq? '@ (car c)))
|
|||
|
d
|
|||
|
(cons c d)))
|
|||
|
b (cdr a)))
|
|||
|
b))
|
|||
|
'()
|
|||
|
(cdr s))
|
|||
|
(error 'xml-element-attributes "expected an xml-element, given" s)))
|
|||
|
|
|||
|
(define (xml-element-contents s)
|
|||
|
(if (and (pair? s) (symbol? (car s)))
|
|||
|
(filter (lambda (i)
|
|||
|
(not (and (pair? i) (eq? '@ (car i)))))
|
|||
|
(cdr s))
|
|||
|
(error 'xml-element-contents "expected an xml-element, given" s)))
|
|||
|
|
|||
|
(define (match-xml-attribute key l)
|
|||
|
(if (not (pair? l))
|
|||
|
#f
|
|||
|
(if (eq? (car (car l)) key)
|
|||
|
(car l)
|
|||
|
(match-xml-attribute key (cdr l)))))
|
|||
|
|
|||
|
(define (filter-attributes keys lst)
|
|||
|
(if (null? lst)
|
|||
|
'()
|
|||
|
(if (member (caar lst) keys)
|
|||
|
(filter-attributes keys (cdr lst))
|
|||
|
(cons (car lst) (filter-attributes keys (cdr lst))))))
|
|||
|
|
|||
|
(define-syntax compile-clause
|
|||
|
(lambda (stx)
|
|||
|
(letrec
|
|||
|
([sxml-match-syntax-error
|
|||
|
(lambda (msg exp sub)
|
|||
|
(raise-syntax-error #f msg (with-syntax ([s exp]) (syntax (sxml-match s))) sub))]
|
|||
|
[ellipsis?
|
|||
|
(lambda (stx)
|
|||
|
(and (identifier? stx) (eq? '... (syntax->datum stx))))]
|
|||
|
[literal?
|
|||
|
(lambda (stx)
|
|||
|
(let ([x (syntax->datum stx)])
|
|||
|
(or (string? x)
|
|||
|
(char? x)
|
|||
|
(number? x)
|
|||
|
(boolean? x))))]
|
|||
|
[keyword?
|
|||
|
(lambda (stx)
|
|||
|
(and (identifier? stx)
|
|||
|
(let ([str (symbol->string (syntax->datum stx))])
|
|||
|
(char=? #\: (string-ref str (- (string-length str) 1))))))]
|
|||
|
[extract-cata-fun
|
|||
|
(lambda (cf)
|
|||
|
(syntax-case cf ()
|
|||
|
[#f #f]
|
|||
|
[other cf]))]
|
|||
|
[add-pat-var
|
|||
|
(lambda (pvar pvar-lst)
|
|||
|
(define (check-pvar lst)
|
|||
|
(if (null? lst)
|
|||
|
(void)
|
|||
|
(if (bound-identifier=? (car lst) pvar)
|
|||
|
(sxml-match-syntax-error "duplicate pattern variable not allowed"
|
|||
|
stx
|
|||
|
pvar)
|
|||
|
(check-pvar (cdr lst)))))
|
|||
|
(check-pvar pvar-lst)
|
|||
|
(cons pvar pvar-lst))]
|
|||
|
[add-cata-def
|
|||
|
(lambda (depth cvars cfun ctemp cdefs)
|
|||
|
(cons (list depth cvars cfun ctemp) cdefs))]
|
|||
|
[process-cata-exp
|
|||
|
(lambda (depth cfun ctemp)
|
|||
|
(if (= depth 0)
|
|||
|
(with-syntax ([cf cfun]
|
|||
|
[ct ctemp])
|
|||
|
(syntax (cf ct)))
|
|||
|
(let ([new-ctemp (car (generate-temporaries (list ctemp)))])
|
|||
|
(with-syntax ([ct ctemp]
|
|||
|
[nct new-ctemp]
|
|||
|
[body (process-cata-exp (- depth 1) cfun new-ctemp)])
|
|||
|
(syntax (map (lambda (nct) body) ct))))))]
|
|||
|
[process-cata-defs
|
|||
|
(lambda (cata-defs body)
|
|||
|
(if (null? cata-defs)
|
|||
|
body
|
|||
|
(with-syntax ([(cata-binding ...)
|
|||
|
(map (lambda (def)
|
|||
|
(with-syntax ([bvar (cadr def)]
|
|||
|
[bval (process-cata-exp (car def)
|
|||
|
(caddr def)
|
|||
|
(cadddr def))])
|
|||
|
(syntax (bvar bval))))
|
|||
|
cata-defs)]
|
|||
|
[body-stx body])
|
|||
|
(syntax (let-values (cata-binding ...)
|
|||
|
body-stx)))))]
|
|||
|
[cata-defs->pvar-lst
|
|||
|
(lambda (lst)
|
|||
|
(if (null? lst)
|
|||
|
'()
|
|||
|
(let iter ([items (cadr (car lst))])
|
|||
|
(syntax-case items ()
|
|||
|
[() (cata-defs->pvar-lst (cdr lst))]
|
|||
|
[(fst . rst) (cons (syntax fst) (iter (syntax rst)))]))))]
|
|||
|
[process-output-action
|
|||
|
(lambda (action dotted-vars)
|
|||
|
(define (finite-lst? lst)
|
|||
|
(syntax-case lst ()
|
|||
|
(item
|
|||
|
(identifier? (syntax item))
|
|||
|
#f)
|
|||
|
(()
|
|||
|
#t)
|
|||
|
((fst dots . rst)
|
|||
|
(ellipsis? (syntax dots))
|
|||
|
#f)
|
|||
|
((fst . rst)
|
|||
|
(finite-lst? (syntax rst)))))
|
|||
|
(define (expand-lst lst)
|
|||
|
(syntax-case lst ()
|
|||
|
[() (syntax '())]
|
|||
|
[item
|
|||
|
(identifier? (syntax item))
|
|||
|
(syntax item)]
|
|||
|
[(fst dots . rst)
|
|||
|
(ellipsis? (syntax dots))
|
|||
|
(with-syntax ([exp-lft (expand-dotted-item
|
|||
|
(process-output-action (syntax fst)
|
|||
|
dotted-vars))]
|
|||
|
[exp-rgt (expand-lst (syntax rst))])
|
|||
|
(syntax (append exp-lft exp-rgt)))]
|
|||
|
[(fst . rst)
|
|||
|
(with-syntax ([exp-lft (process-output-action (syntax fst)
|
|||
|
dotted-vars)]
|
|||
|
[exp-rgt (expand-lst (syntax rst))])
|
|||
|
(syntax (cons exp-lft exp-rgt)))]))
|
|||
|
(define (member-var? var lst)
|
|||
|
(let iter ([lst lst])
|
|||
|
(if (null? lst)
|
|||
|
#f
|
|||
|
(if (or (bound-identifier=? var (car lst))
|
|||
|
(free-identifier=? var (car lst)))
|
|||
|
#t
|
|||
|
(iter (cdr lst))))))
|
|||
|
(define (dotted-var? var)
|
|||
|
(member-var? var dotted-vars))
|
|||
|
(define (merge-pvars lst1 lst2)
|
|||
|
(if (null? lst1)
|
|||
|
lst2
|
|||
|
(if (member-var? (car lst1) lst2)
|
|||
|
(merge-pvars (cdr lst1) lst2)
|
|||
|
(cons (car lst1) (merge-pvars (cdr lst1) lst2)))))
|
|||
|
(define (select-dotted-vars x)
|
|||
|
(define (walk-quasi-body y)
|
|||
|
(syntax-case y (unquote unquote-splicing)
|
|||
|
[((unquote a) . rst)
|
|||
|
(merge-pvars (select-dotted-vars (syntax a))
|
|||
|
(walk-quasi-body (syntax rst)))]
|
|||
|
[((unquote-splicing a) . rst)
|
|||
|
(merge-pvars (select-dotted-vars (syntax a))
|
|||
|
(walk-quasi-body (syntax rst)))]
|
|||
|
[(fst . rst)
|
|||
|
(merge-pvars (walk-quasi-body (syntax fst))
|
|||
|
(walk-quasi-body (syntax rst)))]
|
|||
|
[other
|
|||
|
'()]))
|
|||
|
(syntax-case x (quote quasiquote)
|
|||
|
[(quote . rst) '()]
|
|||
|
[(quasiquote . rst) (walk-quasi-body (syntax rst))]
|
|||
|
[(fst . rst)
|
|||
|
(merge-pvars (select-dotted-vars (syntax fst))
|
|||
|
(select-dotted-vars (syntax rst)))]
|
|||
|
[item
|
|||
|
(and (identifier? (syntax item))
|
|||
|
(dotted-var? (syntax item)))
|
|||
|
(list (syntax item))]
|
|||
|
[item '()]))
|
|||
|
(define (expand-dotted-item item)
|
|||
|
(let ([dvars (select-dotted-vars item)])
|
|||
|
(syntax-case item ()
|
|||
|
[x
|
|||
|
(identifier? (syntax x))
|
|||
|
(syntax x)]
|
|||
|
[x (with-syntax ([(dv ...) dvars])
|
|||
|
(syntax (map (lambda (dv ...) x) dv ...)))])))
|
|||
|
(define (expand-quasiquote-body x)
|
|||
|
(syntax-case x (unquote unquote-splicing quasiquote)
|
|||
|
[(quasiquote . rst) (process-quasiquote x)]
|
|||
|
[(unquote item)
|
|||
|
(with-syntax ([expanded-item (process-output-action (syntax item)
|
|||
|
dotted-vars)])
|
|||
|
(syntax (unquote expanded-item)))]
|
|||
|
[(unquote-splicing item)
|
|||
|
(with-syntax ([expanded-item (process-output-action (syntax item)
|
|||
|
dotted-vars)])
|
|||
|
(syntax (unquote-splicing expanded-item)))]
|
|||
|
[((unquote item) dots . rst)
|
|||
|
(ellipsis? (syntax dots))
|
|||
|
(with-syntax ([expanded-item (expand-dotted-item
|
|||
|
(process-output-action (syntax item)
|
|||
|
dotted-vars))]
|
|||
|
[expanded-rst (expand-quasiquote-body (syntax rst))])
|
|||
|
(syntax ((unquote-splicing expanded-item) . expanded-rst)))]
|
|||
|
[(item dots . rst)
|
|||
|
(ellipsis? (syntax dots))
|
|||
|
(with-syntax ([expanded-item (expand-dotted-item
|
|||
|
(process-output-action (syntax (quasiquote item))
|
|||
|
dotted-vars))]
|
|||
|
[expanded-rst (expand-quasiquote-body (syntax rst))])
|
|||
|
(syntax ((unquote-splicing expanded-item) . expanded-rst)))]
|
|||
|
[(fst . rst)
|
|||
|
(with-syntax ([expanded-fst (expand-quasiquote-body (syntax fst))]
|
|||
|
[expanded-rst (expand-quasiquote-body (syntax rst))])
|
|||
|
(syntax (expanded-fst . expanded-rst)))]
|
|||
|
[other x]))
|
|||
|
(define (process-quasiquote x)
|
|||
|
(syntax-case x ()
|
|||
|
[(quasiquote term) (with-syntax ([expanded-body (expand-quasiquote-body (syntax term))])
|
|||
|
(syntax (quasiquote expanded-body)))]
|
|||
|
[else (sxml-match-syntax-error "bad quasiquote-form"
|
|||
|
stx
|
|||
|
x)]))
|
|||
|
(syntax-case action (quote quasiquote)
|
|||
|
[(quote . rst) action]
|
|||
|
[(quasiquote . rst) (process-quasiquote action)]
|
|||
|
[(fst . rst) (if (finite-lst? action)
|
|||
|
(with-syntax ([exp-lft (process-output-action (syntax fst) dotted-vars)]
|
|||
|
[exp-rgt (process-output-action (syntax rst) dotted-vars)])
|
|||
|
(syntax (exp-lft . exp-rgt)))
|
|||
|
(with-syntax ([exp-lft (process-output-action (syntax fst)
|
|||
|
dotted-vars)]
|
|||
|
[exp-rgt (expand-lst (syntax rst))])
|
|||
|
(syntax (apply exp-lft exp-rgt))))]
|
|||
|
[item action]))]
|
|||
|
[compile-element-pat
|
|||
|
(lambda (ele exp nextp fail-k pvar-lst depth cata-fun cata-defs dotted-vars)
|
|||
|
(syntax-case ele (@)
|
|||
|
[(tag (@ . attr-items) . items)
|
|||
|
(identifier? (syntax tag))
|
|||
|
(let ([attr-exp (car (generate-temporaries (list exp)))]
|
|||
|
[body-exp (car (generate-temporaries (list exp)))])
|
|||
|
(let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(compile-attr-list (syntax attr-items)
|
|||
|
(syntax items)
|
|||
|
attr-exp
|
|||
|
body-exp
|
|||
|
'()
|
|||
|
nextp
|
|||
|
fail-k
|
|||
|
pvar-lst
|
|||
|
depth
|
|||
|
cata-fun
|
|||
|
cata-defs
|
|||
|
dotted-vars)])
|
|||
|
(values (with-syntax ([x exp]
|
|||
|
[ax attr-exp]
|
|||
|
[bx body-exp]
|
|||
|
[body tests]
|
|||
|
[fail-to fail-k])
|
|||
|
(syntax (if (and (pair? x) (eq? 'tag (xml-element-tag x)))
|
|||
|
(let ([ax (xml-element-attributes x)]
|
|||
|
[bx (xml-element-contents x)])
|
|||
|
body)
|
|||
|
(fail-to))))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars)))]
|
|||
|
[(tag . items)
|
|||
|
(identifier? (syntax tag))
|
|||
|
(let ([body-exp (car (generate-temporaries (list exp)))])
|
|||
|
(let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(compile-item-list (syntax items)
|
|||
|
body-exp
|
|||
|
nextp
|
|||
|
fail-k
|
|||
|
#t
|
|||
|
pvar-lst
|
|||
|
depth
|
|||
|
cata-fun
|
|||
|
cata-defs
|
|||
|
dotted-vars)])
|
|||
|
(values (with-syntax ([x exp]
|
|||
|
[bx body-exp]
|
|||
|
[body tests]
|
|||
|
[fail-to fail-k])
|
|||
|
(syntax (if (and (pair? x) (eq? 'tag (xml-element-tag x)))
|
|||
|
(let ([bx (xml-element-contents x)])
|
|||
|
body)
|
|||
|
(fail-to))))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars)))]))]
|
|||
|
[compile-end-element
|
|||
|
(lambda (exp nextp fail-k pvar-lst cata-defs dotted-vars)
|
|||
|
(let-values ([(next-tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(nextp pvar-lst cata-defs dotted-vars)])
|
|||
|
(values (with-syntax ([x exp]
|
|||
|
[body next-tests]
|
|||
|
[fail-to fail-k])
|
|||
|
(syntax (if (null? x) body (fail-to))))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars)))]
|
|||
|
[compile-attr-list
|
|||
|
(lambda (attr-lst body-lst attr-exp body-exp attr-key-lst nextp fail-k pvar-lst depth cata-fun cata-defs dotted-vars)
|
|||
|
(syntax-case attr-lst (unquote ->)
|
|||
|
[(unquote var)
|
|||
|
(identifier? (syntax var))
|
|||
|
(let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(compile-item-list body-lst
|
|||
|
body-exp
|
|||
|
nextp
|
|||
|
fail-k
|
|||
|
#t
|
|||
|
(add-pat-var (syntax var) pvar-lst)
|
|||
|
depth
|
|||
|
cata-fun
|
|||
|
cata-defs
|
|||
|
dotted-vars)])
|
|||
|
(values (with-syntax ([ax attr-exp]
|
|||
|
[matched-attrs attr-key-lst]
|
|||
|
[body tests])
|
|||
|
(syntax (let ([var (filter-attributes 'matched-attrs ax)])
|
|||
|
body)))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars))]
|
|||
|
[((atag [(unquote [cata -> cvar ...]) default]) . rst)
|
|||
|
(identifier? (syntax atag))
|
|||
|
(let ([ctemp (car (generate-temporaries (syntax ([cvar ...]))))])
|
|||
|
(let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(compile-attr-list (syntax rst)
|
|||
|
body-lst
|
|||
|
attr-exp
|
|||
|
body-exp
|
|||
|
(cons (syntax atag) attr-key-lst)
|
|||
|
nextp
|
|||
|
fail-k
|
|||
|
(add-pat-var ctemp pvar-lst)
|
|||
|
depth
|
|||
|
cata-fun
|
|||
|
(add-cata-def depth
|
|||
|
(syntax [cvar ...])
|
|||
|
(syntax cata)
|
|||
|
ctemp
|
|||
|
cata-defs)
|
|||
|
dotted-vars)])
|
|||
|
(values (with-syntax ([ax attr-exp]
|
|||
|
[ct ctemp]
|
|||
|
[body tests])
|
|||
|
(syntax (let ([binding (match-xml-attribute 'atag ax)])
|
|||
|
(let ([ct (if binding
|
|||
|
(cadr binding)
|
|||
|
default)])
|
|||
|
body))))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars)))]
|
|||
|
[((atag [(unquote [cvar ...]) default]) . rst)
|
|||
|
(identifier? (syntax atag))
|
|||
|
(let ([ctemp (car (generate-temporaries (syntax ([cvar ...]))))])
|
|||
|
(if (not cata-fun)
|
|||
|
(sxml-match-syntax-error "sxml-match pattern: catamorphism not allowed in this context"
|
|||
|
stx
|
|||
|
(syntax [cvar ...])))
|
|||
|
(let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(compile-attr-list (syntax rst)
|
|||
|
body-lst
|
|||
|
attr-exp
|
|||
|
body-exp
|
|||
|
(cons (syntax atag) attr-key-lst)
|
|||
|
nextp
|
|||
|
fail-k
|
|||
|
(add-pat-var ctemp pvar-lst)
|
|||
|
depth
|
|||
|
cata-fun
|
|||
|
(add-cata-def depth
|
|||
|
(syntax [cvar ...])
|
|||
|
cata-fun
|
|||
|
ctemp
|
|||
|
cata-defs)
|
|||
|
dotted-vars)])
|
|||
|
(values (with-syntax ([ax attr-exp]
|
|||
|
[ct ctemp]
|
|||
|
[body tests])
|
|||
|
(syntax (let ([binding (match-xml-attribute 'atag ax)])
|
|||
|
(let ([ct (if binding
|
|||
|
(cadr binding)
|
|||
|
default)])
|
|||
|
body))))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars)))]
|
|||
|
[((atag [(unquote var) default]) . rst)
|
|||
|
(and (identifier? (syntax atag)) (identifier? (syntax var)))
|
|||
|
(let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(compile-attr-list (syntax rst)
|
|||
|
body-lst
|
|||
|
attr-exp
|
|||
|
body-exp
|
|||
|
(cons (syntax atag) attr-key-lst)
|
|||
|
nextp
|
|||
|
fail-k
|
|||
|
(add-pat-var (syntax var) pvar-lst)
|
|||
|
depth
|
|||
|
cata-fun
|
|||
|
cata-defs
|
|||
|
dotted-vars)])
|
|||
|
(values (with-syntax ([ax attr-exp]
|
|||
|
[body tests])
|
|||
|
(syntax (let ([binding (match-xml-attribute 'atag ax)])
|
|||
|
(let ([var (if binding
|
|||
|
(cadr binding)
|
|||
|
default)])
|
|||
|
body))))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars))]
|
|||
|
[((atag (unquote [cata -> cvar ...])) . rst)
|
|||
|
(identifier? (syntax atag))
|
|||
|
(let ([ctemp (car (generate-temporaries (syntax ([cvar ...]))))])
|
|||
|
(let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(compile-attr-list (syntax rst)
|
|||
|
body-lst
|
|||
|
attr-exp
|
|||
|
body-exp
|
|||
|
(cons (syntax atag) attr-key-lst)
|
|||
|
nextp
|
|||
|
fail-k
|
|||
|
(add-pat-var ctemp pvar-lst)
|
|||
|
depth
|
|||
|
cata-fun
|
|||
|
(add-cata-def depth
|
|||
|
(syntax [cvar ...])
|
|||
|
(syntax cata)
|
|||
|
ctemp
|
|||
|
cata-defs)
|
|||
|
dotted-vars)])
|
|||
|
(values (with-syntax ([ax attr-exp]
|
|||
|
[ct ctemp]
|
|||
|
[body tests]
|
|||
|
[fail-to fail-k])
|
|||
|
(syntax (let ([binding (match-xml-attribute 'atag ax)])
|
|||
|
(if binding
|
|||
|
(let ([ct (cadr binding)])
|
|||
|
body)
|
|||
|
(fail-to)))))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars)))]
|
|||
|
[((atag (unquote [cvar ...])) . rst)
|
|||
|
(identifier? (syntax atag))
|
|||
|
(let ([ctemp (car (generate-temporaries (syntax ([cvar ...]))))])
|
|||
|
(if (not cata-fun)
|
|||
|
(sxml-match-syntax-error "sxml-match pattern: catamorphism not allowed in this context"
|
|||
|
stx
|
|||
|
(syntax [cvar ...])))
|
|||
|
(let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(compile-attr-list (syntax rst)
|
|||
|
body-lst
|
|||
|
attr-exp
|
|||
|
body-exp
|
|||
|
(cons (syntax atag) attr-key-lst)
|
|||
|
nextp
|
|||
|
fail-k
|
|||
|
(add-pat-var ctemp pvar-lst)
|
|||
|
depth
|
|||
|
cata-fun
|
|||
|
(add-cata-def depth
|
|||
|
(syntax [cvar ...])
|
|||
|
cata-fun
|
|||
|
ctemp
|
|||
|
cata-defs)
|
|||
|
dotted-vars)])
|
|||
|
(values (with-syntax ([ax attr-exp]
|
|||
|
[ct ctemp]
|
|||
|
[body tests]
|
|||
|
[fail-to fail-k])
|
|||
|
(syntax (let ([binding (match-xml-attribute 'atag ax)])
|
|||
|
(if binding
|
|||
|
(let ([ct (cadr binding)])
|
|||
|
body)
|
|||
|
(fail-to)))))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars)))]
|
|||
|
[((atag (unquote var)) . rst)
|
|||
|
(and (identifier? (syntax atag)) (identifier? (syntax var)))
|
|||
|
(let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(compile-attr-list (syntax rst)
|
|||
|
body-lst
|
|||
|
attr-exp
|
|||
|
body-exp
|
|||
|
(cons (syntax atag) attr-key-lst)
|
|||
|
nextp
|
|||
|
fail-k
|
|||
|
(add-pat-var (syntax var) pvar-lst)
|
|||
|
depth
|
|||
|
cata-fun
|
|||
|
cata-defs
|
|||
|
dotted-vars)])
|
|||
|
(values (with-syntax ([ax attr-exp]
|
|||
|
[body tests]
|
|||
|
[fail-to fail-k])
|
|||
|
(syntax (let ([binding (match-xml-attribute 'atag ax)])
|
|||
|
(if binding
|
|||
|
(let ([var (cadr binding)])
|
|||
|
body)
|
|||
|
(fail-to)))))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars))]
|
|||
|
[((atag (i ...)) . rst)
|
|||
|
(identifier? (syntax atag))
|
|||
|
(sxml-match-syntax-error "bad attribute pattern"
|
|||
|
stx
|
|||
|
(syntax (kwd (i ...))))]
|
|||
|
[((atag i) . rst)
|
|||
|
(and (identifier? (syntax atag)) (identifier? (syntax i)))
|
|||
|
(sxml-match-syntax-error "bad attribute pattern"
|
|||
|
stx
|
|||
|
(syntax (kwd i)))]
|
|||
|
[((atag literal) . rst)
|
|||
|
(and (identifier? (syntax atag)) (literal? (syntax literal)))
|
|||
|
(let-values ([(tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(compile-attr-list (syntax rst)
|
|||
|
body-lst
|
|||
|
attr-exp
|
|||
|
body-exp
|
|||
|
(cons (syntax atag) attr-key-lst)
|
|||
|
nextp
|
|||
|
fail-k
|
|||
|
pvar-lst
|
|||
|
depth
|
|||
|
cata-fun
|
|||
|
cata-defs
|
|||
|
dotted-vars)])
|
|||
|
(values (with-syntax ([ax attr-exp]
|
|||
|
[body tests]
|
|||
|
[fail-to fail-k])
|
|||
|
(syntax (let ([binding (match-xml-attribute 'atag ax)])
|
|||
|
(if binding
|
|||
|
(if (equal? (cadr binding) literal)
|
|||
|
body
|
|||
|
(fail-to))
|
|||
|
(fail-to)))))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars))]
|
|||
|
[()
|
|||
|
(compile-item-list body-lst
|
|||
|
body-exp
|
|||
|
nextp
|
|||
|
fail-k
|
|||
|
#t
|
|||
|
pvar-lst
|
|||
|
depth
|
|||
|
cata-fun
|
|||
|
cata-defs
|
|||
|
dotted-vars)]))]
|
|||
|
[compile-item-list
|
|||
|
(lambda (lst exp nextp fail-k ellipsis-allowed? pvar-lst depth cata-fun cata-defs dotted-vars)
|
|||
|
(syntax-case lst (unquote ->)
|
|||
|
[() (compile-end-element exp nextp fail-k pvar-lst cata-defs dotted-vars)]
|
|||
|
[(unquote var)
|
|||
|
(identifier? (syntax var))
|
|||
|
(if (not ellipsis-allowed?)
|
|||
|
(sxml-match-syntax-error "improper list pattern not allowed in this context"
|
|||
|
stx
|
|||
|
(syntax dots))
|
|||
|
(let-values ([(next-tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(nextp (add-pat-var (syntax var) pvar-lst) cata-defs dotted-vars)])
|
|||
|
(values (with-syntax ([x exp]
|
|||
|
[body next-tests])
|
|||
|
(syntax (let ([var x]) body)))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars)))]
|
|||
|
[(unquote [cata -> cvar ...])
|
|||
|
(if (not ellipsis-allowed?)
|
|||
|
(sxml-match-syntax-error "improper list pattern not allowed in this context"
|
|||
|
stx
|
|||
|
(syntax dots))
|
|||
|
(let ([ctemp (car (generate-temporaries (syntax ([cvar ...]))))])
|
|||
|
(let-values ([(next-tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(nextp (add-pat-var ctemp pvar-lst)
|
|||
|
(add-cata-def depth
|
|||
|
(syntax [cvar ...])
|
|||
|
(syntax cata)
|
|||
|
ctemp
|
|||
|
cata-defs)
|
|||
|
dotted-vars)])
|
|||
|
(values (with-syntax ([ct ctemp]
|
|||
|
[x exp]
|
|||
|
[body next-tests])
|
|||
|
(syntax (let ([ct x]) body)))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars))))]
|
|||
|
[(unquote [cvar ...])
|
|||
|
(let ([ctemp (car (generate-temporaries (syntax ([cvar ...]))))])
|
|||
|
(if (not cata-fun)
|
|||
|
(sxml-match-syntax-error "sxml-match pattern: catamorphism not allowed in this context"
|
|||
|
stx
|
|||
|
(syntax [cvar ...])))
|
|||
|
(let-values ([(next-tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(nextp (add-pat-var ctemp pvar-lst)
|
|||
|
(add-cata-def depth
|
|||
|
(syntax [cvar ...])
|
|||
|
cata-fun
|
|||
|
ctemp
|
|||
|
cata-defs)
|
|||
|
dotted-vars)])
|
|||
|
(values (with-syntax ([ct ctemp]
|
|||
|
[x exp]
|
|||
|
[body next-tests])
|
|||
|
(syntax (let ([ct x]) body)))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars)))]
|
|||
|
[(item dots . rst)
|
|||
|
(ellipsis? (syntax dots))
|
|||
|
(if (not ellipsis-allowed?)
|
|||
|
(sxml-match-syntax-error "ellipses not allowed in this context"
|
|||
|
stx
|
|||
|
(syntax dots))
|
|||
|
(compile-dotted-pattern-list (syntax item)
|
|||
|
(syntax rst)
|
|||
|
exp
|
|||
|
nextp
|
|||
|
fail-k
|
|||
|
pvar-lst
|
|||
|
depth
|
|||
|
cata-fun
|
|||
|
cata-defs
|
|||
|
dotted-vars))]
|
|||
|
[(item . rst)
|
|||
|
(compile-item (syntax item)
|
|||
|
exp
|
|||
|
(lambda (new-exp new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(compile-item-list (syntax rst)
|
|||
|
new-exp
|
|||
|
nextp
|
|||
|
fail-k
|
|||
|
ellipsis-allowed?
|
|||
|
new-pvar-lst
|
|||
|
depth
|
|||
|
cata-fun
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars))
|
|||
|
fail-k
|
|||
|
pvar-lst
|
|||
|
depth
|
|||
|
cata-fun
|
|||
|
cata-defs
|
|||
|
dotted-vars)]))]
|
|||
|
[compile-dotted-pattern-list
|
|||
|
(lambda (item
|
|||
|
tail
|
|||
|
exp
|
|||
|
nextp
|
|||
|
fail-k
|
|||
|
pvar-lst
|
|||
|
depth
|
|||
|
cata-fun
|
|||
|
cata-defs
|
|||
|
dotted-vars)
|
|||
|
(let-values ([(tail-tests tail-pvar-lst tail-cata-defs tail-dotted-vars)
|
|||
|
(compile-item-list tail
|
|||
|
(syntax lst)
|
|||
|
(lambda (new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(values (with-syntax ([(npv ...) new-pvar-lst])
|
|||
|
(syntax (values #t npv ...)))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars))
|
|||
|
(syntax fail)
|
|||
|
#f
|
|||
|
'()
|
|||
|
depth
|
|||
|
'()
|
|||
|
'()
|
|||
|
dotted-vars)]
|
|||
|
[(item-tests item-pvar-lst item-cata-defs item-dotted-vars)
|
|||
|
(compile-item item
|
|||
|
(syntax lst)
|
|||
|
(lambda (new-exp new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(values (with-syntax ([(npv ...) new-pvar-lst])
|
|||
|
(syntax (values #t (cdr lst) npv ...)))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars))
|
|||
|
(syntax fail)
|
|||
|
'()
|
|||
|
(+ 1 depth)
|
|||
|
cata-fun
|
|||
|
'()
|
|||
|
dotted-vars)])
|
|||
|
; more here: check for duplicate pat-vars, cata-defs
|
|||
|
(let-values ([(final-tests final-pvar-lst final-cata-defs final-dotted-vars)
|
|||
|
(nextp (append tail-pvar-lst item-pvar-lst pvar-lst)
|
|||
|
(append tail-cata-defs item-cata-defs cata-defs)
|
|||
|
(append item-pvar-lst
|
|||
|
(cata-defs->pvar-lst item-cata-defs)
|
|||
|
tail-dotted-vars
|
|||
|
dotted-vars))])
|
|||
|
(let ([temp-item-pvar-lst (generate-temporaries item-pvar-lst)])
|
|||
|
(values
|
|||
|
(with-syntax
|
|||
|
([x exp]
|
|||
|
[fail-to fail-k]
|
|||
|
[tail-body tail-tests]
|
|||
|
[item-body item-tests]
|
|||
|
[final-body final-tests]
|
|||
|
[(ipv ...) item-pvar-lst]
|
|||
|
[(gpv ...) temp-item-pvar-lst]
|
|||
|
[(tpv ...) tail-pvar-lst]
|
|||
|
[(item-void ...) (map (lambda (i) (syntax (void))) item-pvar-lst)]
|
|||
|
[(tail-void ...) (map (lambda (i) (syntax (void))) tail-pvar-lst)]
|
|||
|
[(item-null ...) (map (lambda (i) (syntax '())) item-pvar-lst)]
|
|||
|
[(item-cons ...) (map (lambda (a b)
|
|||
|
(with-syntax ([xa a]
|
|||
|
[xb b])
|
|||
|
(syntax (cons xa xb))))
|
|||
|
item-pvar-lst
|
|||
|
temp-item-pvar-lst)])
|
|||
|
(syntax (letrec ([match-tail
|
|||
|
(lambda (lst fail)
|
|||
|
tail-body)]
|
|||
|
[match-item
|
|||
|
(lambda (lst)
|
|||
|
(let ([fail (lambda ()
|
|||
|
(values #f
|
|||
|
lst
|
|||
|
item-void ...))])
|
|||
|
item-body))]
|
|||
|
[match-dotted
|
|||
|
(lambda (x)
|
|||
|
(let-values ([(tail-res tpv ...)
|
|||
|
(match-tail x
|
|||
|
(lambda ()
|
|||
|
(values #f
|
|||
|
tail-void ...)))])
|
|||
|
(if tail-res
|
|||
|
(values item-null ...
|
|||
|
tpv ...)
|
|||
|
(let-values ([(res new-x ipv ...) (match-item x)])
|
|||
|
(if res
|
|||
|
(let-values ([(gpv ... tpv ...)
|
|||
|
(match-dotted new-x)])
|
|||
|
(values item-cons ... tpv ...))
|
|||
|
(let-values ([(last-tail-res tpv ...)
|
|||
|
(match-tail x fail-to)])
|
|||
|
(values item-null ... tpv ...)))))))])
|
|||
|
(let-values ([(ipv ... tpv ...)
|
|||
|
(match-dotted x)])
|
|||
|
final-body))))
|
|||
|
final-pvar-lst
|
|||
|
final-cata-defs
|
|||
|
final-dotted-vars)))))]
|
|||
|
[compile-item
|
|||
|
(lambda (item exp nextp fail-k pvar-lst depth cata-fun cata-defs dotted-vars)
|
|||
|
(syntax-case item (unquote ->)
|
|||
|
; normal pattern var
|
|||
|
[(unquote var)
|
|||
|
(identifier? (syntax var))
|
|||
|
(let ([new-exp (car (generate-temporaries (list exp)))])
|
|||
|
(let-values ([(next-tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(nextp new-exp (add-pat-var (syntax var) pvar-lst) cata-defs dotted-vars)])
|
|||
|
(values (with-syntax ([x exp]
|
|||
|
[nx new-exp]
|
|||
|
[body next-tests]
|
|||
|
[fail-to fail-k])
|
|||
|
(syntax (if (pair? x)
|
|||
|
(let ([nx (cdr x)]
|
|||
|
[var (car x)])
|
|||
|
body)
|
|||
|
(fail-to))))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars)))]
|
|||
|
; named catamorphism
|
|||
|
[(unquote [cata -> cvar ...])
|
|||
|
(let ([new-exp (car (generate-temporaries (list exp)))]
|
|||
|
[ctemp (car (generate-temporaries (syntax ([cvar ...]))))])
|
|||
|
(let-values ([(next-tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(nextp new-exp
|
|||
|
(add-pat-var ctemp pvar-lst)
|
|||
|
(add-cata-def depth
|
|||
|
(syntax [cvar ...])
|
|||
|
(syntax cata)
|
|||
|
ctemp
|
|||
|
cata-defs)
|
|||
|
dotted-vars)])
|
|||
|
(values (with-syntax ([x exp]
|
|||
|
[nx new-exp]
|
|||
|
[ct ctemp]
|
|||
|
[body next-tests]
|
|||
|
[fail-to fail-k])
|
|||
|
(syntax (if (pair? x)
|
|||
|
(let ([nx (cdr x)]
|
|||
|
[ct (car x)])
|
|||
|
body)
|
|||
|
(fail-to))))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars)))]
|
|||
|
; basic catamorphism
|
|||
|
[(unquote [cvar ...])
|
|||
|
(let ([new-exp (car (generate-temporaries (list exp)))]
|
|||
|
[ctemp (car (generate-temporaries (syntax ([cvar ...]))))])
|
|||
|
(if (not cata-fun)
|
|||
|
(sxml-match-syntax-error "sxml-match pattern: catamorphism not allowed in this context"
|
|||
|
stx
|
|||
|
(syntax [cvar ...])))
|
|||
|
(let-values ([(next-tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(nextp new-exp
|
|||
|
(add-pat-var ctemp pvar-lst)
|
|||
|
(add-cata-def depth
|
|||
|
(syntax [cvar ...])
|
|||
|
cata-fun
|
|||
|
ctemp
|
|||
|
cata-defs)
|
|||
|
dotted-vars)])
|
|||
|
(values (with-syntax ([x exp]
|
|||
|
[nx new-exp]
|
|||
|
[ct ctemp]
|
|||
|
[body next-tests]
|
|||
|
[fail-to fail-k])
|
|||
|
(syntax (if (pair? x)
|
|||
|
(let ([nx (cdr x)]
|
|||
|
[ct (car x)])
|
|||
|
body)
|
|||
|
(fail-to))))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars)))]
|
|||
|
[(tag item ...)
|
|||
|
(identifier? (syntax tag))
|
|||
|
(let ([new-exp (car (generate-temporaries (list exp)))])
|
|||
|
(let-values ([(after-tests after-pvar-lst after-cata-defs after-dotted-vars)
|
|||
|
(compile-element-pat (syntax (tag item ...))
|
|||
|
(with-syntax ([x exp])
|
|||
|
(syntax (car x)))
|
|||
|
(lambda (more-pvar-lst more-cata-defs more-dotted-vars)
|
|||
|
(let-values ([(next-tests new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars)
|
|||
|
(nextp new-exp
|
|||
|
more-pvar-lst
|
|||
|
more-cata-defs
|
|||
|
more-dotted-vars)])
|
|||
|
(values (with-syntax ([x exp]
|
|||
|
[nx new-exp]
|
|||
|
[body next-tests])
|
|||
|
(syntax (let ([nx (cdr x)])
|
|||
|
body)))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars)))
|
|||
|
fail-k
|
|||
|
pvar-lst
|
|||
|
depth
|
|||
|
cata-fun
|
|||
|
cata-defs
|
|||
|
dotted-vars)])
|
|||
|
; test that we are not at the end of an item-list, BEFORE
|
|||
|
; entering tests for the element pattern (against the 'car' of the item-list)
|
|||
|
(values (with-syntax ([x exp]
|
|||
|
[body after-tests]
|
|||
|
[fail-to fail-k])
|
|||
|
(syntax (if (pair? x)
|
|||
|
body
|
|||
|
(fail-to))))
|
|||
|
after-pvar-lst
|
|||
|
after-cata-defs
|
|||
|
after-dotted-vars)))]
|
|||
|
[(i ...)
|
|||
|
(sxml-match-syntax-error "bad pattern syntax (not an element pattern)"
|
|||
|
stx
|
|||
|
(syntax (i ...)))]
|
|||
|
[i
|
|||
|
(identifier? (syntax i))
|
|||
|
(sxml-match-syntax-error "bad pattern syntax (symbol not allowed in this context)"
|
|||
|
stx
|
|||
|
(syntax i))]
|
|||
|
[literal
|
|||
|
(literal? (syntax literal))
|
|||
|
(let ([new-exp (car (generate-temporaries (list exp)))])
|
|||
|
(let-values ([(next-tests new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(nextp new-exp pvar-lst cata-defs dotted-vars)])
|
|||
|
(values (with-syntax ([x exp]
|
|||
|
[nx new-exp]
|
|||
|
[body next-tests]
|
|||
|
[fail-to fail-k])
|
|||
|
(syntax (if (and (pair? x) (equal? literal (car x)))
|
|||
|
(let ([nx (cdr x)])
|
|||
|
body)
|
|||
|
(fail-to))))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars)))]))])
|
|||
|
(let ([fail-k (syntax failure)])
|
|||
|
(syntax-case stx (unquote guard ->)
|
|||
|
[(compile-clause ((unquote var) (guard gexp ...) action0 action ...)
|
|||
|
exp
|
|||
|
cata-fun
|
|||
|
fail-exp)
|
|||
|
(identifier? (syntax var))
|
|||
|
(syntax (let ([var exp])
|
|||
|
(if (and gexp ...)
|
|||
|
(begin action0 action ...)
|
|||
|
(fail-exp))))]
|
|||
|
[(compile-clause ((unquote [cata -> cvar ...]) (guard gexp ...) action0 action ...)
|
|||
|
exp
|
|||
|
cata-fun
|
|||
|
fail-exp)
|
|||
|
(syntax (if (and gexp ...)
|
|||
|
(let-values ([(cvar ...) (cata exp)])
|
|||
|
(begin action0 action ...))
|
|||
|
(fail-exp)))]
|
|||
|
[(compile-clause ((unquote [cvar ...]) (guard gexp ...) action0 action ...)
|
|||
|
exp
|
|||
|
cata-fun
|
|||
|
fail-exp)
|
|||
|
(if (not (extract-cata-fun (syntax cata-fun)))
|
|||
|
(sxml-match-syntax-error "sxml-match pattern: catamorphism not allowed in this context"
|
|||
|
stx
|
|||
|
(syntax [cvar ...]))
|
|||
|
(syntax (if (and gexp ...)
|
|||
|
(let-values ([(cvar ...) (cata-fun exp)])
|
|||
|
(begin action0 action ...))
|
|||
|
(fail-exp))))]
|
|||
|
[(compile-clause ((unquote var) action0 action ...) exp cata-fun fail-exp)
|
|||
|
(identifier? (syntax var))
|
|||
|
(syntax (let ([var exp])
|
|||
|
action0 action ...))]
|
|||
|
[(compile-clause ((unquote [cata -> cvar ...]) action0 action ...) exp cata-fun fail-exp)
|
|||
|
(syntax (let-values ([(cvar ...) (cata exp)])
|
|||
|
action0 action ...))]
|
|||
|
[(compile-clause ((unquote [cvar ...]) action0 action ...) exp cata-fun fail-exp)
|
|||
|
(if (not (extract-cata-fun (syntax cata-fun)))
|
|||
|
(sxml-match-syntax-error "sxml-match pattern: catamorphism not allowed in this context"
|
|||
|
stx
|
|||
|
(syntax [cvar ...]))
|
|||
|
(syntax (let-values ([(cvar ...) (cata-fun exp)])
|
|||
|
action0 action ...)))]
|
|||
|
[(compile-clause ((lst . rst) (guard gexp ...) action0 action ...) exp cata-fun fail-exp)
|
|||
|
(and (identifier? (syntax lst)) (eq? 'list (syntax->datum (syntax lst))))
|
|||
|
(let-values ([(result pvar-lst cata-defs dotted-vars)
|
|||
|
(compile-item-list (syntax rst)
|
|||
|
(syntax exp)
|
|||
|
(lambda (new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(values
|
|||
|
(with-syntax
|
|||
|
([exp-body (process-cata-defs new-cata-defs
|
|||
|
(process-output-action
|
|||
|
(syntax (begin action0
|
|||
|
action ...))
|
|||
|
new-dotted-vars))]
|
|||
|
[fail-to fail-k])
|
|||
|
(syntax (if (and gexp ...) exp-body (fail-to))))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars))
|
|||
|
fail-k
|
|||
|
#t
|
|||
|
'()
|
|||
|
0
|
|||
|
(extract-cata-fun (syntax cata-fun))
|
|||
|
'()
|
|||
|
'())])
|
|||
|
(with-syntax ([fail-to fail-k]
|
|||
|
[body result])
|
|||
|
(syntax (let ([fail-to fail-exp])
|
|||
|
(if (nodeset? exp)
|
|||
|
body
|
|||
|
(fail-to))))))]
|
|||
|
[(compile-clause ((lst . rst) action0 action ...) exp cata-fun fail-exp)
|
|||
|
(and (identifier? (syntax lst)) (eq? 'list (syntax-object->datum (syntax lst))))
|
|||
|
(let-values ([(result pvar-lst cata-defs dotted-vars)
|
|||
|
(compile-item-list (syntax rst)
|
|||
|
(syntax exp)
|
|||
|
(lambda (new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(values (process-cata-defs new-cata-defs
|
|||
|
(process-output-action
|
|||
|
(syntax (begin action0
|
|||
|
action ...))
|
|||
|
new-dotted-vars))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars))
|
|||
|
fail-k
|
|||
|
#t
|
|||
|
'()
|
|||
|
0
|
|||
|
(extract-cata-fun (syntax cata-fun))
|
|||
|
'()
|
|||
|
'())])
|
|||
|
(with-syntax ([body result]
|
|||
|
[fail-to fail-k])
|
|||
|
(syntax (let ([fail-to fail-exp])
|
|||
|
(if (nodeset? exp)
|
|||
|
body
|
|||
|
(fail-to))))))]
|
|||
|
[(compile-clause ((fst . rst) (guard gexp ...) action0 action ...) exp cata-fun fail-exp)
|
|||
|
(identifier? (syntax fst))
|
|||
|
(let-values ([(result pvar-lst cata-defs dotted-vars)
|
|||
|
(compile-element-pat (syntax (fst . rst))
|
|||
|
(syntax exp)
|
|||
|
(lambda (new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(values
|
|||
|
(with-syntax
|
|||
|
([body (process-cata-defs new-cata-defs
|
|||
|
(process-output-action
|
|||
|
(syntax (begin action0
|
|||
|
action ...))
|
|||
|
new-dotted-vars))]
|
|||
|
[fail-to fail-k])
|
|||
|
(syntax (if (and gexp ...) body (fail-to))))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars))
|
|||
|
fail-k
|
|||
|
'()
|
|||
|
0
|
|||
|
(extract-cata-fun (syntax cata-fun))
|
|||
|
'()
|
|||
|
'())])
|
|||
|
(with-syntax ([fail-to fail-k]
|
|||
|
[body result])
|
|||
|
(syntax (let ([fail-to fail-exp])
|
|||
|
body))))]
|
|||
|
[(compile-clause ((fst . rst) action0 action ...) exp cata-fun fail-exp)
|
|||
|
(identifier? (syntax fst))
|
|||
|
(let-values ([(result pvar-lst cata-defs dotted-vars)
|
|||
|
(compile-element-pat (syntax (fst . rst))
|
|||
|
(syntax exp)
|
|||
|
(lambda (new-pvar-lst new-cata-defs new-dotted-vars)
|
|||
|
(values (process-cata-defs new-cata-defs
|
|||
|
(process-output-action
|
|||
|
(syntax (begin action0
|
|||
|
action ...))
|
|||
|
new-dotted-vars))
|
|||
|
new-pvar-lst
|
|||
|
new-cata-defs
|
|||
|
new-dotted-vars))
|
|||
|
fail-k
|
|||
|
'()
|
|||
|
0
|
|||
|
(extract-cata-fun (syntax cata-fun))
|
|||
|
'()
|
|||
|
'())])
|
|||
|
(with-syntax ([fail-to fail-k]
|
|||
|
[body result])
|
|||
|
(syntax (let ([fail-to fail-exp])
|
|||
|
body))))]
|
|||
|
[(compile-clause ((i ...) (guard gexp ...) action0 action ...) exp cata-fun fail-exp)
|
|||
|
(sxml-match-syntax-error "bad pattern syntax (not an element pattern)"
|
|||
|
stx
|
|||
|
(syntax (i ...)))]
|
|||
|
[(compile-clause ((i ...) action0 action ...) exp cata-fun fail-exp)
|
|||
|
(sxml-match-syntax-error "bad pattern syntax (not an element pattern)"
|
|||
|
stx
|
|||
|
(syntax (i ...)))]
|
|||
|
[(compile-clause (pat (guard gexp ...) action0 action ...) exp cata-fun fail-exp)
|
|||
|
(identifier? (syntax pat))
|
|||
|
(sxml-match-syntax-error "bad pattern syntax (symbol not allowed in this context)"
|
|||
|
stx
|
|||
|
(syntax pat))]
|
|||
|
[(compile-clause (pat action0 action ...) exp cata-fun fail-exp)
|
|||
|
(identifier? (syntax pat))
|
|||
|
(sxml-match-syntax-error "bad pattern syntax (symbol not allowed in this context)"
|
|||
|
stx
|
|||
|
(syntax pat))]
|
|||
|
[(compile-clause (literal (guard gexp ...) action0 action ...) exp cata-fun fail-exp)
|
|||
|
(literal? (syntax literal))
|
|||
|
(syntax (if (and (equal? literal exp) (and gexp ...))
|
|||
|
(begin action0 action ...)
|
|||
|
(fail-exp)))]
|
|||
|
[(compile-clause (literal action0 action ...) exp cata-fun fail-exp)
|
|||
|
(literal? (syntax literal))
|
|||
|
(syntax (if (equal? literal exp)
|
|||
|
(begin action0 action ...)
|
|||
|
(fail-exp)))])))))
|
|||
|
|
|||
|
(define-syntax sxml-match1
|
|||
|
(syntax-rules ()
|
|||
|
[(sxml-match1 exp cata-fun clause)
|
|||
|
(compile-clause clause exp cata-fun
|
|||
|
(lambda () (error 'sxml-match "no matching clause found")))]
|
|||
|
[(sxml-match1 exp cata-fun clause0 clause ...)
|
|||
|
(let/ec escape
|
|||
|
(compile-clause clause0 exp cata-fun
|
|||
|
(lambda () (call-with-values
|
|||
|
(lambda () (sxml-match1 exp cata-fun
|
|||
|
clause ...))
|
|||
|
escape))))]))
|
|||
|
|
|||
|
(define-syntax sxml-match
|
|||
|
(syntax-rules ()
|
|||
|
((sxml-match val clause0 clause ...)
|
|||
|
(letrec ([cfun (lambda (exp)
|
|||
|
(sxml-match1 exp cfun clause0 clause ...))])
|
|||
|
(cfun val)))))
|
|||
|
|
|||
|
(define-syntax sxml-match-let1
|
|||
|
(syntax-rules ()
|
|||
|
[(sxml-match-let1 syntag synform () body0 body ...)
|
|||
|
(let () body0 body ...)]
|
|||
|
[(sxml-match-let1 syntag synform ([pat exp]) body0 body ...)
|
|||
|
(compile-clause (pat (let () body0 body ...))
|
|||
|
exp
|
|||
|
#f
|
|||
|
(lambda () (error 'syntag "could not match pattern ~s" 'pat)))]
|
|||
|
[(sxml-match-let1 syntag synform ([pat0 exp0] [pat exp] ...) body0 body ...)
|
|||
|
(compile-clause (pat0 (sxml-match-let1 syntag synform ([pat exp] ...) body0 body ...))
|
|||
|
exp0
|
|||
|
#f
|
|||
|
(lambda () (error 'syntag "could not match pattern ~s" 'pat0)))]))
|
|||
|
|
|||
|
(define-syntax sxml-match-let-help
|
|||
|
(lambda (stx)
|
|||
|
(syntax-case stx ()
|
|||
|
[(sxml-match-let-help syntag synform ([pat exp] ...) body0 body ...)
|
|||
|
(with-syntax ([(temp-name ...) (generate-temporaries (syntax (exp ...)))])
|
|||
|
(syntax (let ([temp-name exp] ...)
|
|||
|
(sxml-match-let1 syntag synform ([pat temp-name] ...) body0 body ...))))])))
|
|||
|
|
|||
|
(define-syntax sxml-match-let
|
|||
|
(lambda (stx)
|
|||
|
(syntax-case stx ()
|
|||
|
[(sxml-match-let ([pat exp] ...) body0 body ...)
|
|||
|
(with-syntax ([synform stx])
|
|||
|
(syntax (sxml-match-let-help sxml-match-let synform ([pat exp] ...) body0 body ...)))])))
|
|||
|
|
|||
|
(define-syntax sxml-match-let*
|
|||
|
(lambda (stx)
|
|||
|
(syntax-case stx ()
|
|||
|
[(sxml-match-let* () body0 body ...)
|
|||
|
(syntax (let () body0 body ...))]
|
|||
|
[(sxml-match-let* ([pat0 exp0] [pat exp] ...) body0 body ...)
|
|||
|
(with-syntax ([synform stx])
|
|||
|
(syntax (sxml-match-let-help sxml-match-let* synform ([pat0 exp0])
|
|||
|
(sxml-match-let* ([pat exp] ...)
|
|||
|
body0 body ...))))])))
|