Change groups abstraction to use message-passing style.
authorChris Hanson <org/chris-hanson/cph>
Wed, 3 May 2017 06:00:27 +0000 (23:00 -0700)
committerChris Hanson <org/chris-hanson/cph>
Wed, 3 May 2017 06:00:27 +0000 (23:00 -0700)
src/runtime/regsexp.scm

index fde418dedbf1affc015880715159698ace65ad3a..a33cbdfb4597b25932633bce9542989f290b5b17 100644 (file)
@@ -74,7 +74,8 @@ USA.
 
 (define (top-level-match crsexp start-position)
   (let ((result
-        ((compiled-regsexp-impl crsexp) start-position '() (lambda () #f))))
+        ((compiled-regsexp-impl crsexp)
+         start-position (make-groups) (lambda () #f))))
     (and result
         (cons (%make-range (get-index start-position)
                            (car result))
@@ -476,112 +477,40 @@ USA.
 (define (next-char position)
   ((position 'next-char)))
 
+(define (next-position position)
+  ((position 'next-position)))
+
 (define (prev-char position)
   ((position 'prev-char)))
 
-(define (next-position position)
-  ((position 'next-position)))
+(define (prev-position position)
+  ((position 'prev-position)))
 
 (define (same-positions? p1 p2)
   (and (eq? ((p1 'get-marker)) ((p2 'get-marker)))
        (fix:= ((p1 'get-index)) ((p2 'get-index)))))
 
-;;;; Groups
-
-(define (%start-group key position groups)
-  (cons (list key position)
-       groups))
-
-(define (%end-group key position groups)
-  ;; Kind of slow, but it's functional.  Could speed up with side
-  ;; effects.
-  (let ((p (assq key groups)))
-    (if (not (and p (null? (cddr p))))
-       (error "%END-GROUP called with no %START-GROUP:" key))
-    (cons (list key (cadr p) position)
-         (delq p groups))))
-
-(define (%find-group key groups)
-  (let ((p (assq key groups)))
-    (if (not p)
-       ;; This can happen with (* (GROUP ...)), but in other cases it
-       ;; would be an error.
-       (insn:always-succeed)
-       (begin
-         (if (null? (cddr p))
-             (error "Reference to group appears before group's end:" key))
-         (insn:chars (%group-chars (cadr p) (caddr p)))))))
-
-(define (%group-chars start-position end-position)
-  (let loop ((position start-position) (chars '()))
-    (if (same-positions? position end-position)
-       (reverse! chars)
-       (let ((char (next-char position)))
-         (if (not char)
-             (error "Failure of SAME? predicate"))
-         (loop (next-position position)
-               (cons char chars))))))
-
-(define (%convert-groups groups)
-  (map (lambda (g)
-        (cons (car g)
-              (%make-range (get-index (cadr g))
-                           (get-index (caddr g)))))
-       (remove (lambda (g)
-                (null? (cddr g)))
-              groups)))
-
-(define-integrable (%make-range start end)
-  (cons start end))
-\f
-;;;; Match input port
-
-(define (regsexp-match-input-port crsexp port)
-  (top-level-match crsexp
-                  (make-source-position
-                   (lambda ()
-                     (let ((char (read-char port)))
-                       (if (eof-object? char)
-                           #f
-                           char))))))
-
 (define (make-source-position source)
   (let ((marker (list 'source-position)))
 
-    (define (at-index index next-char prev-char)
+    (define (at-index index next-char prev-char prev-position)
 
       (define (next-position)
-       (at-index (fix:+ index 1) (source) next-char))
+       (at-index (fix:+ index 1) (source) next-char this))
 
-      (lambda (operator)
+      (define (this operator)
        (case operator
          ((get-marker) (lambda () marker))
          ((get-index) (lambda () index))
          ((next-char) (lambda () next-char))
-         ((prev-char) (lambda () prev-char))
          ((next-position) next-position)
-         (else (error "Unknown operator:" operator)))))
-
-    (at-index 0 (source) #f)))
-\f
-;;;; Match string
+         ((prev-char) (lambda () prev-char))
+         ((prev-position) (lambda () prev-position))
+         (else (error "Unknown operator:" operator))))
 
-(define (regsexp-match-string crsexp string #!optional start end)
-  (let* ((caller 'regsexp-match-string)
-        (end (fix:end-index end (string-length string) caller))
-        (start (fix:start-index start end caller)))
-    (guarantee nfc-string? string caller)
-    (top-level-match crsexp (make-string-position string start end))))
+      this)
 
-(define (regsexp-search-string-forward crsexp string #!optional start end)
-  (let* ((caller 'regsexp-search-string-forward)
-        (end (fix:end-index end (string-length string) caller))
-        (start (fix:start-index start end caller)))
-    (guarantee nfc-string? string caller)
-    (let loop ((position (make-string-position string start end)))
-      (or (top-level-match crsexp position)
-         (and (next-char position)
-              (loop (next-position position)))))))
+    (at-index 0 (source) #f #f)))
 
 (define (make-string-position string start end)
   (let ((marker (list 'string-position)))
@@ -592,24 +521,126 @@ USA.
        (and (fix:< index end)
             (string-ref string index)))
 
+      (define (next-position)
+       (at-index (fix:+ index 1)))
+
       (define (prev-char)
        (and (fix:> index start)
             (string-ref string (fix:- index 1))))
 
-      (define (next-position)
-       (at-index (fix:+ index 1)))
+      (define (prev-position)
+       (at-index (fix:- index 1)))
 
       (lambda (operator)
        (case operator
          ((get-marker) (lambda () marker))
          ((get-index) (lambda () index))
          ((next-char) next-char)
-         ((prev-char) prev-char)
          ((next-position) next-position)
+         ((prev-char) prev-char)
+         ((prev-position) prev-position)
          (else (error "Unknown operator:" operator)))))
 
     (at-index start)))
 \f
+;;;; Groups
+
+(define (make-groups)
+
+  (define (loop groups)
+
+    (define (start key position)
+      (loop (cons (list key position) groups)))
+
+    (define (end key position)
+      ;; Kind of slow, but it's functional.  Could speed up with side effects.
+      (let ((p (assq key groups)))
+       (if (not (and p (null? (cddr p))))
+           (error "%END-GROUP called with no %START-GROUP:" key))
+       (loop (cons (list key (cadr p) position)
+                   (delq p groups)))))
+
+    (define (find key)
+      (let ((p (assq key groups)))
+       (if (not p)
+           ;; This can happen with (* (GROUP ...)), but in other cases it
+           ;; would be an error.
+           (insn:always-succeed)
+           (begin
+             (if (null? (cddr p))
+                 (error "Reference to group appears before group's end:" key))
+             (insn:chars (%group-chars (cadr p) (caddr p)))))))
+
+    (define (%group-chars start-position end-position)
+      (let loop ((position end-position) (chars '()))
+       (if (same-positions? position start-position)
+           chars
+           (let ((char (prev-char position)))
+             (loop (prev-position position)
+                   (cons char chars))))))
+
+    (define (convert)
+      (map (lambda (g)
+            (cons (car g)
+                  (%make-range (get-index (cadr g))
+                               (get-index (caddr g)))))
+          (remove (lambda (g)
+                    (null? (cddr g)))
+                  groups)))
+
+    (lambda (operator)
+      (case operator
+       ((start) start)
+       ((end) end)
+       ((find) find)
+       ((convert) convert)
+       (else (error "Unknown operator:" operator)))))
+
+  (loop '()))
+
+(define (%start-group key position groups)
+  ((groups 'start) key position))
+
+(define (%end-group key position groups)
+  ((groups 'end) key position))
+
+(define (%find-group key groups)
+  ((groups 'find) key))
+
+(define (%convert-groups groups)
+  ((groups 'convert)))
+
+(define-integrable (%make-range start end)
+  (cons start end))
+\f
+;;;; Match and search
+
+(define (regsexp-match-string crsexp string #!optional start end)
+  (let* ((caller 'regsexp-match-string)
+        (end (fix:end-index end (string-length string) caller))
+        (start (fix:start-index start end caller)))
+    (guarantee nfc-string? string caller)
+    (top-level-match crsexp (make-string-position string start end))))
+
+(define (regsexp-search-string-forward crsexp string #!optional start end)
+  (let* ((caller 'regsexp-search-string-forward)
+        (end (fix:end-index end (string-length string) caller))
+        (start (fix:start-index start end caller)))
+    (guarantee nfc-string? string caller)
+    (let loop ((position (make-string-position string start end)))
+      (or (top-level-match crsexp position)
+         (and (next-char position)
+              (loop (next-position position)))))))
+
+(define (regsexp-match-input-port crsexp port)
+  (top-level-match crsexp
+                  (make-source-position
+                   (lambda ()
+                     (let ((char (read-char port)))
+                       (if (eof-object? char)
+                           #f
+                           char))))))
+\f
 ;;;; Convert regexp pattern to regsexp
 
 (define (re-pattern->regsexp pattern)