(define-module (language python module re compile) #:use-module (language python module re parser) #:use-module (language python module re flags) #:use-module (language python list) #:use-module (language python string) #:use-module ((parser stis-parser) #:select ((parse . stisparse) .. f-nl! f-nl f-tag! f-tag f-seq f-or f-or! f-and f-true g* g+ gmn ng* ng+ ngmn f-reg! f-and! f-test N M X XL f-pk g? ng? f-test! f-eof f-not! f-prev f-not f-out f-rev *whitespace* f-nm f-pos)) #:use-module (parser stis-parser macros) #:use-module (ice-9 match) #:export (compile-reg test-reg parse)) (define-syntax-rule ( (a b) . code) ( (d) (let ((a (car d)) (b (cadr d))) . code))) (define wrap list) (define (fw f) ( (L c) (.. c2 (f c)) ( (wrap L c2)))) (define (f-flags a b f) ( (c) (let* ((flags (fluid-ref *flags*)) (newfl (logand (logior a flags) (lognot b))) (p P) (cc CC)) ( ((P (lambda () (fluid-set! *flags* flags) (p))) (CC (lambda (s p) (let ((pp (lambda () (fluid-set! *flags* newfl) (p)))) (fluid-set! *flags* flags) (cc s pp))))) ( (fluid-set! *flags* newfl)) (.. c2 (f c)) ( c2))))) (define (f-flags2 a b) ( (c) (let* ((flags (fluid-ref *flags*)) (newfl (logand (logior a flags) (lognot b))) (p P)) ( ((P (lambda () (fluid-set! *flags* flags) (p)))) ( (fluid-set! *flags* newfl)) ( c))))) (define startline ( (L c) (when (= N 0) ( (wrap L c))))) (define dotall ( (L c) (let ((x (fluid-ref *flags*))) (when (not (= 0 (logand x DOTALL))) ( (wrap L c)))))) (define multiline ( (L c) (let ((x (fluid-ref *flags*))) (when (not (= 0 (logand x DOTALL))) ( (wrap L c)))))) (define (gt f) ( (L c) (let ((x #f)) ( ( (.. c* (f-rev '())) (.. c2 (f (list L '()))) ( (set! x c2)) ) (when x ( (wrap (car x) c))))))) (define-syntax-rule (group f) (let () (define-syntax-rule (mac s) (lambda (x n m) (set! s x))) (let ((I (new-group)) (ff f)) ( (L c) (let ((e -1) (s -1)) (.. c2 ((f-seq (f-pos (mac s)) ff (f-pos (mac e)))(list L c))) (let* ((L (car c2)) (L (cons (cons I (list (strit c (cadr c2)) s e)) L))) ( (wrap L (cadr c2))))))))) (define-syntax-rule (group-name f name) (let () (define-syntax-rule (mac s) (lambda (x n m) (set! s x))) (let* ((n (new-name name)) (ff f)) ( (L c) (let ((e -1) (s -1)) (.. c2 ((f-seq (f-pos (mac s)) ff (f-pos (mac e))) (list L c))) (let* ((L (car c2)) (c2 (cadr c2)) (L (cons (cons n (list (strit c c2) s e)) L))) ( (wrap L c2)))))))) (define (strit u v) (let lp ((v v) (r '())) (if (eq? u v) (list->string r) (lp (cdr v) (cons (car v) r))))) (define (incant name) ( (c) (let* ((L (cadr c)) (r (if (number? name) (let lp ((l L)) (define (f x u l) (if (= x name) u (lp l))) (match l (((x . u) . l) (if (pair? x) (f (cdr x) (car u) l) (f x (car u) l))) (() (error (+ "could not incant " name))))) (let lp ((l L)) (define (f x u l) (if (equal? x name) u (lp l))) (match l (((x . u) . l) (if (pair? x) (f (car x) u l) (f x u l))) (() (error (+ "could not incant " name)))))))) (if r ( (.. ((fw (f-tag! r)) c))) ( (error "group is not existing in the history")))))) (define (incant-rev name) ( (c) (let* ((L (cadr c)) (r (assoc name L))) (if r ( (.. ((f-tag (reverse (cdr r))) c))) ( (error "group is not existing in the history")))))) (define (reverse-form x) (match x ((#:or x) (reverse-form x)) ((#:or . l) (cons #:or (map reverse-form l))) ((#:seq x) (reverse-form x)) ((#:seq . l) (cons #:seq (reverse (map reverse-form l)))) ((#:sub f) (list #:group (reverse-form f))) ((#:?P< n f) (list #:?P< n (reverse-form f))) ((#:?: f) (reverse-form f)) ((#:flags a b f) (list #:flags a b (reverse-form f))) ((#:flags2 a) (list #:flags2 a)) ((#:?P= name) (#:?P=-rev name)) ((#:?P=-rev name) (#:?P= name)) ((#:?if name yes no) (list #:if name (reverse-form yes) (reverse-form no))) ((#:?= f) (list #:?= (reverse-form f))) ((#:?! f) (list #:?= (reverse-form f))) ((#:?<= f) (list #:?<=-rev f)) ((#:?list a)) (f 0)) (match l ((#\a . l) (lp l (logior f ASCII))) ((#\i . l) (lp l (logior f IGNORECASE))) ((#\L . l) (lp l (logior f LOCALE))) ((#\m . l) (lp l (logior f MULTILINE))) ((#\s . l) (lp l (logior f DOTALL))) ((#\x . l) (lp l (logior f VERBOSE))) ((_ . l) (lp l f)) (() f)))) (define (mask-off a b) (let lp ((l (string->list b)) (f (if (member #\u (string->list a)) ASCII 0))) (match l ((#\i . l) (lp l (logior f IGNORECASE))) ((#\m . l) (lp l (logior f MULTILINE))) ((#\s . l) (lp l (logior f DOTALL))) ((#\x . l) (lp l (logior f VERBOSE))) ((_ . l) (lp l f)) (() f)))) (define (compile x) (match x ((#:or x) (compile x)) ((#:or . l) (apply f-or (map compile l))) ((#:seq x) (compile x)) ((#:seq . l) (apply f-seq (map compile l))) ((#:sub f) (group (compile f))) ((#:?P< n f) (group-name (compile f) n)) ((#:?: f) (compile f)) ((#:?P= name) (incant name)) ((#:?P=-rev name) (incant-rev name)) ((#:?= f) (f-and (compile f) f-true)) ((#:?! f) (f-and (f-not (compile f)) f-true)) ((#:?<= f) (gt (compile (reverse-form f)))) ((#:?integer ch) 128) (< (char->integer chx) 128)) (eq? (char-upcase chx) (char-upcase ch)) (eq? chx ch)))))))))) ((#:bracket not ch ...) (let ((f (apply f-or! (map (lambda (x) (match x ((#:range ch1 ch2) (f-reg! (format #f "[~a-~a]" ch1 ch2))) ((#:ch (#:class ch)) (get-class ch)) ((#:ch ch) (compile (list #:ch ch))))) ch)))) (if not (f-not! f) f))))) (define (maybe-add-nk x) (if (equal? (pylist-ref x (- (len x) 1)) "\n") (+ x "\n") x)) (define (compile-reg x) (init) (let ((p (f-seq (f-out '(() ())) (compile (parse-reg x))))) (list p (fluid-ref groups) (fluid-ref groupindex)))) (define (test-reg y x) (with-fluids ((*whitespace* f-true)) (stisparse (maybe-add-nk y) (car (compile-reg x))))) (define (parse y x) (with-fluids ((*whitespace* f-true)) (stisparse (maybe-add-nk y) x)))