home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-386-Vol-2of3.iso
/
c
/
cr-macro.zip
/
REWRITE.SCM
< prev
next >
Wrap
Text File
|
1990-02-10
|
4KB
|
143 lines
; Rewrite-rule compiler (a.k.a. "extend-syntax")
; Example:
;
; (define-syntax or
; (syntax-rules () ;Note that OR must *not* appear in this list!
; ((or) => #f)
; ((or e) => e)
; ((or e1 e +) => (let ((temp e1))
; (if temp temp (or e +))))))
(define (r exp) ;for testing
(rewrite-syntax-rules exp (lambda (x) x) eq?))
(define (rewrite-rewrite exp rename)
(process-rules (cddr exp) (cadr exp) rename))
(define (process-rules rules noise-words rename)
(let ((tail '-tail-))
`(,(rename 'macro)
(lambda (-input- -rename-) ;Should be renamed...
(let ((,tail (cdr -input-)))
(cond ,@(map (lambda (rule)
(process-rule rule tail noise-words))
rules)
(else (error "use of macro doesn't match definition"
-input-))))))))
(define (process-rule rule tail noise-words)
(if (or (not (= (length rule) 3))
(not (eq? (cadr rule) '=>)))
(error "ill-formed rule" rule))
(let ((pattern (car rule))
(template (caddr rule)))
(let ((env (process-pattern (cdr pattern) tail 0 noise-words)))
`(,(process-match tail (cdr pattern) noise-words)
(let* ,(map (lambda (z)
`(,(car z) ,(cadr z)))
env)
,(process-template template env 0 noise-words))))))
(define (process-pattern pattern path rank noise-words)
(cond ((name? pattern)
(if (member pattern noise-words)
'()
(list (list pattern path rank))))
((or (zero-or-more? pattern)
(at-least-one? pattern))
(let ((temp '-temp-)) ;Bug -- should gensym here!!
(cons `(,temp ,path)
(map (lambda (z)
`(,(car z)
(map (lambda (-input-)
,(cadr z))
,temp)
,(caddr z)))
(process-pattern (car pattern)
'-input-
(cons (cadr pattern) rank)
noise-words)))))
((pair? pattern)
(append (process-pattern (car pattern) `(car ,path) rank noise-words)
(process-pattern (cdr pattern) `(cdr ,path) rank noise-words)))
(else '())))
(define (process-template template env rank noise-words)
(cond ((name? template)
(if (member template noise-words)
`',template
(let ((probe (assq template env)))
(if probe
(if (equal? (caddr probe) rank)
template
(error "rank error" template rank))
`(-rename- ',template)))))
((or (zero-or-more? template)
(at-least-one? template))
(let ((vars (free-template-vars (car template) env '())))
(if (null? vars)
(error "ill-formed template" template)
`(map (lambda ,vars
,(process-template (car template)
env
(cons (cadr template) rank)
noise-words))
,@vars))))
((pair? template)
`(cons ,(process-template (car template) env rank noise-words)
,(process-template (cdr template) env rank noise-words)))
(else `',template)))
(define (free-template-vars template env free)
(cond ((name? template)
(if (and (assq template env)
(not (memq template free)))
(cons template free)
'()))
((or (zero-or-more? template)
(at-least-one? template))
(free-template-vars (cadr template) env free))
((pair? template)
(free-template-vars (car template) env
(free-template-vars (cdr template) env free)))
(else free)))
(define (check-cadr sym)
(lambda (pattern)
(and (pair? pattern)
(pair? (cdr pattern))
(eq? (cadr pattern) sym)
(or (null? (cddr pattern))
(error "segment matching not implemented" pattern)))))
(define zero-or-more? (check-cadr '*))
(define at-least-one? (check-cadr '+))
; Support
(define (process-match input pattern noise-words)
(cond ((name? pattern)
(if (member pattern noise-words)
`(equal? ,input ',pattern)
`#t))
((zero-or-more? pattern)
(process-list-match input (car pattern) noise-words))
((at-least-one? pattern)
`(and (not (null? ,input))
,(process-list-match input (car pattern) noise-words)))
((pair? pattern)
`(let ((temp ,input))
(and (pair? temp)
,(process-match `(car temp) (car pattern) noise-words)
,(process-match `(cdr temp) (cdr pattern) noise-words))))
(else
`(equal? ,input ',pattern))))
(define (process-list-match input pattern noise-words)
`(let loop ((l ,input))
(or (null? l)
(and (pair? l)
,(process-match '(car l) pattern noise-words)
(loop (cdr l))))))