#lang racket/base
(require "myenv.ss"
srfi/13/string
"parse-error.ss"
"SSAX-code.ss"
"ssax-prim.ss"
"id.ss"
"xlink-parser.ss")
(provide parent:new-level-seed-handler
parent:construct-element
ssax:multi-parser)
(define (parent:new-level-seed-handler elem-name)
(let
((head (list elem-name)))
(list (lambda () head))))
(define (parent:construct-element parent:parent-seed parent:seed
attrs children)
(let ((head ((car parent:seed))))
(append head
(list (cons '@ attrs))
children)))
(define get-sxml-seed car)
(define (bad-accessor type)
(lambda args
(error 'ssax:multi-parser "bad accessor; called with ~a"
(string-join (map (lambda (x) (format "~e" x)) args) " "))))
(define (make-seed . seeds)
(let rpt
((s (cdr seeds)) (rzt (list (car seeds))))
(cond
((null? s) (reverse rzt))
((car s) (rpt (cdr s)
(cons (car s) rzt)))
(else (rpt (cdr s) rzt)))))
(define (ssax:multi-parser . req-features)
(let ((ns-assig '())
(with-parent? (memq 'parent req-features))
(with-id? (memq 'id req-features))
(with-xlink? (memq 'xlink req-features)))
(call-with-values
(lambda () (values
(if with-parent?
cadr (bad-accessor 'par))
(if with-id?
(if with-parent? caddr cadr)
(bad-accessor 'id))
(if with-xlink?
(cond
((and with-parent? with-id?)
cadddr)
((or with-parent? with-id?)
caddr)
(else cadr))
(bad-accessor 'xlink))))
(lambda (get-pptr-seed get-id-seed get-xlink-seed)
(let ((initial-seed (make-seed
'()
(and with-parent? (list '*TOP-PTR*))
(and with-id? (id:make-seed '() '()))
(and with-xlink?
(xlink:make-small-seed 'general '() '(1) '())))))
(letrec
(
(ending-actions
(cond
((not (or with-id? with-xlink?))
(lambda (seed)
(let ((result (reverse (get-sxml-seed seed))))
(cons '*TOP* result))))
((and with-id? (not with-xlink?)) (lambda (seed)
(let((result (reverse (get-sxml-seed seed)))
(aux (list (id:ending-action (get-id-seed seed)))))
(cons* '*TOP*
(cons '@@ aux)
result))))
((and with-id? with-xlink?) (lambda (seed)
(let((result (reverse (get-sxml-seed seed)))
(aux (list (xlink:ending-action (get-xlink-seed seed))
(id:ending-action (get-id-seed seed)))))
(cons* '*TOP*
(cons '@@ aux)
result))))
(else
(error 'ssax:multi-parser
"ending-actions NIY: ~a ~a ~a"
with-parent? with-id? with-xlink?))))
(new-level-seed-handler
(cond
((not (or with-parent? with-id? with-xlink?))
(lambda(port)
(lambda (elem-gi attributes namespaces expected-content seed)
(list '()))))
((and with-parent? (not (or with-id? with-xlink?))) (lambda(port)
(lambda (elem-gi attributes namespaces expected-content seed)
(make-seed
'()
(and with-parent?
(parent:new-level-seed-handler
(if (symbol? elem-gi)
elem-gi
(RES-NAME->SXML elem-gi))))
))))
((and with-id? (not (or with-parent? with-xlink?))) (lambda(port)
(lambda (elem-gi attributes namespaces expected-content seed)
(list '()
(id:new-level-seed-handler (get-id-seed seed))))))
((and with-parent? with-id? (not with-xlink?)) (lambda(port)
(lambda (elem-gi attributes namespaces expected-content seed)
(list '()
(parent:new-level-seed-handler
(if(symbol? elem-gi) elem-gi (RES-NAME->SXML elem-gi)))
(id:new-level-seed-handler (get-id-seed seed))))))
((and with-id? with-xlink? (not with-parent?)) (lambda(port)
(lambda (elem-gi attributes namespaces expected-content seed)
(list '()
(id:new-level-seed-handler (get-id-seed seed))
(xlink:new-level-seed-handler
port attributes namespaces (get-xlink-seed seed))))))
((and with-parent? with-id? with-xlink?) (lambda(port)
(lambda (elem-gi attributes namespaces expected-content seed)
(list '()
(parent:new-level-seed-handler
(if(symbol? elem-gi) elem-gi (RES-NAME->SXML elem-gi)))
(id:new-level-seed-handler (get-id-seed seed))
(xlink:new-level-seed-handler
port attributes namespaces (get-xlink-seed seed))))))
(else
(error 'ssax:multi-parser
"new-level NIY: ~s ~s ~s"
with-parent? with-id? with-xlink?))))
(finish-element-handler
(cond
((not (or with-parent? with-id? with-xlink?))
(lambda (elem-gi attributes namespaces parent-seed seed)
(let ((children (reverse-collect-str-drop-ws (get-sxml-seed seed)))
(attrs
(attlist-fold
(lambda (attr accum)
(cons (list
(if (symbol? (car attr)) (car attr)
(RES-NAME->SXML (car attr)))
(cdr attr)) accum))
'() attributes)))
(list (cons
(cons
(if (symbol? elem-gi) elem-gi
(RES-NAME->SXML elem-gi))
(if (null? attrs) children
(cons (cons '@ attrs) children)))
(get-sxml-seed parent-seed))))))
((and with-parent? (not (or with-id? with-xlink?))) (lambda (elem-gi attributes namespaces parent-seed seed)
(let((children (reverse-collect-str-drop-ws (get-sxml-seed seed)))
(attrs
(attlist-fold
(lambda (attr accum)
(cons (list
(if (symbol? (car attr)) (car attr)
(RES-NAME->SXML (car attr)))
(cdr attr)) accum))
'() attributes)))
(list (cons
(parent:construct-element
(get-pptr-seed parent-seed)
(get-pptr-seed seed)
attrs children)
(get-sxml-seed parent-seed))
(get-pptr-seed parent-seed)
))))
((and with-id? (not (or with-parent? with-xlink?))) (lambda (elem-gi attributes namespaces parent-seed seed)
(let((children (reverse-collect-str-drop-ws (get-sxml-seed seed)))
(attrs
(attlist-fold
(lambda (attr accum)
(cons (list
(if (symbol? (car attr)) (car attr)
(RES-NAME->SXML (car attr)))
(cdr attr)) accum))
'() attributes)))
(let((element
(cons
(if(symbol? elem-gi)
elem-gi
(RES-NAME->SXML elem-gi))
(if(null? attrs)
children
(cons (cons '@ attrs) children)))))
(list (cons element (get-sxml-seed parent-seed))
(id:finish-element-handler
elem-gi attributes (get-id-seed seed) element))))))
((and with-parent? with-id? (not with-xlink?)) (lambda (elem-gi attributes namespaces parent-seed seed)
(let((children (reverse-collect-str-drop-ws (get-sxml-seed seed)))
(attrs
(attlist-fold
(lambda (attr accum)
(cons (list
(if (symbol? (car attr)) (car attr)
(RES-NAME->SXML (car attr)))
(cdr attr)) accum))
'() attributes)))
(let((element
(parent:construct-element
(get-pptr-seed parent-seed) (get-pptr-seed seed)
attrs children)))
(list (cons element (get-sxml-seed parent-seed))
(get-pptr-seed parent-seed)
(id:finish-element-handler
elem-gi attributes (get-id-seed seed) element))))))
((and with-id? with-xlink? (not with-parent?)) (lambda (elem-gi attributes namespaces parent-seed seed)
(let((children (reverse-collect-str-drop-ws (get-sxml-seed seed)))
(attrs
(attlist-fold
(lambda (attr accum)
(cons (list
(if (symbol? (car attr)) (car attr)
(RES-NAME->SXML (car attr)))
(cdr attr)) accum))
'() attributes)))
(let((element
(cons
(if(symbol? elem-gi)
elem-gi
(RES-NAME->SXML elem-gi))
(if(null? attrs)
children
(cons (cons '@ attrs) children)))))
(list (cons element (get-sxml-seed parent-seed))
(id:finish-element-handler
elem-gi attributes (get-id-seed seed) element)
(xlink:finish-element-handler
(get-xlink-seed parent-seed)
(get-xlink-seed seed) element))))))
((and with-parent? with-id? with-xlink?) (lambda (elem-gi attributes namespaces parent-seed seed)
(let((children (reverse-collect-str-drop-ws (get-sxml-seed seed)))
(attrs
(attlist-fold
(lambda (attr accum)
(cons (list
(if (symbol? (car attr)) (car attr)
(RES-NAME->SXML (car attr)))
(cdr attr)) accum))
'() attributes)))
(let((element
(parent:construct-element
(get-pptr-seed parent-seed) (get-pptr-seed seed)
attrs children)))
(list (cons element (get-sxml-seed parent-seed))
(get-pptr-seed parent-seed)
(id:finish-element-handler
elem-gi attributes (get-id-seed seed) element)
(xlink:finish-element-handler
(get-xlink-seed parent-seed)
(get-xlink-seed seed) element))))))
(else
(error 'ssax:multi-parser
"finish-element: NIY"))))
(doctype-handler
(if
(not with-id?)
(lambda (namespaces)
(lambda (port docname systemid internal-subset? seed)
(when internal-subset?
(ssax:warn port
"Internal DTD subset is not currently handled ")
(ssax:skip-internal-dtd port))
(ssax:warn port "DOCTYPE DECL " docname " "
systemid " found and skipped")
(values #f '() namespaces seed)))
(cond
((not (or with-parent? with-xlink?)) (lambda (namespaces)
(lambda (port docname systemid internal-subset? seed)
(values
#f '() namespaces
(list (get-sxml-seed seed)
(id:doctype-handler port systemid internal-subset?))))))
((and with-parent? (not with-xlink?)) (lambda (namespaces)
(lambda (port docname systemid internal-subset? seed)
(values
#f '() namespaces
(list (get-sxml-seed seed)
(get-pptr-seed seed)
(id:doctype-handler port systemid internal-subset?))))))
((and (not with-parent?) with-xlink?) (lambda (namespaces)
(lambda (port docname systemid internal-subset? seed)
(values
#f '() namespaces
(list (get-sxml-seed seed)
(id:doctype-handler port systemid internal-subset?)
(get-xlink-seed seed))))))
(else (lambda (namespaces)
(lambda (port docname systemid internal-subset? seed)
(values
#f '() namespaces
(list (get-sxml-seed seed)
(get-pptr-seed seed)
(id:doctype-handler port systemid internal-subset?)
(get-xlink-seed seed)))))))))
)
(lambda (port)
(let
((namespaces
(map (lambda (el)
(cons* #f (car el) (ssax:uri-string->symbol (cdr el))))
ns-assig)))
(ending-actions
((ssax:make-parser
NEW-LEVEL-SEED
(new-level-seed-handler port)
FINISH-ELEMENT
finish-element-handler
CHAR-DATA-HANDLER
(lambda (string1 string2 seed)
(cons
(if(string-null? string2)
(cons string1 (car seed))
(cons* string2 string1 (car seed)))
(cdr seed)))
DOCTYPE
(doctype-handler namespaces)
UNDECL-ROOT
(lambda (elem-gi seed)
(values #f '() namespaces seed))
PI
((*DEFAULT* . (lambda (port pi-tag seed)
(cons
(cons
(list '*PI* pi-tag
(ssax:read-pi-body-as-string port))
(car seed))
(cdr seed)))))
)
port
initial-seed))))))
))))