Commits

Moritz Heidkamp  committed dc24616

Support passing a parser and a number to repeated for exactly n matches

  • Participants
  • Parent commits 45d85fd

Comments (0)

Files changed (2)

File comparse.scm

             (result (cons x y)))))
 
 (define (repeated* parser min max)
-  (any-of (sequence* ((x parser)
-                      (y (repeated* parser
-                                    (- min 1)
-                                    (and max (- max 1)))))
-            (result (cons x y)))
-          (if (and (<= min 0) (or (not max) (>= max 0)))
-              (result '())
-              fail)))
-
-(define (repeated parser #!key (min 0) max until)
-  (if until
-      (cond (max
-             (followed-by (repeated* parser min max) until))
-            ((zero? min)
-             (repeated-until parser until))
-            (else
-             (sequence* ((x (repeated* parser min min))
-                         (y (repeated-until parser until)))
-               (result (append x y)))))
-      (repeated* parser min max)))
+  (let ((min (or min 0)))
+    (any-of (sequence* ((x parser)
+                        (y (repeated* parser
+                                      (- min 1)
+                                      (and max (- max 1)))))
+              (result (cons x y)))
+            (if (and (<= min 0) (or (not max) (>= max 0)))
+                (result '())
+                fail))))
+
+(define (repeated parser #!rest args #!key min max until)
+  (cond (until
+         (cond (max
+                (followed-by (repeated* parser min max) until))
+               ((or (not min) (zero? min))
+                (repeated-until parser until))
+               (else
+                (sequence* ((x (repeated* parser min min))
+                            (y (repeated-until parser until)))
+                  (result (append x y))))))
+        ((or min max (null? args))
+         (repeated* parser min max))
+        (else
+         (repeated* parser (car args) (car args)))))
 
 (define (maybe parser)
   (any-of parser (result #f)))

File tests/run.scm

 
   (let ((ok (repeated item max: 2 until: (is #\k))))
     (test-parse* "oo" ok "ookay")
-    (test-parse* #f ok "ooookay")))
+    (test-parse* #f ok "ooookay"))
+
+  (let ((hohoho (repeated (char-seq "ho") 3)))
+    (test-parse* "hohoho" hohoho "hohoho")
+    (test-parse* #f hohoho "hoho")))
 
 (test-group "all-of"
   (test-parse #\b (all-of (none-of (is #\a)) (is #\b)) "b")