(defpackage :tiny-pcre (:use :cl)) (in-package :tiny-pcre) (defun scan (re string &key (start 0) (end nil)) (labels ((match-1 (re string start end cont) (etypecase re (character (when (and (< start end) (char= re (char string start))) (funcall cont (1+ start) nil))) (string (let ((n (length re))) (when (and (<= (+ start n) end) (string= re string :start2 start :end2 (+ start n))) (funcall cont (+ start n) nil)))) ((member T) (when (< start end) (funcall cont (1+ start) nil))) ((cons (member OR) t) (dolist (term (cdr re)) (match-1 term string start end cont))) ((cons (member AND) t) (match-and (cdr re) string start end cont)) ((cons (member *) t) (match-and (cdr re) string start end (lambda (p env) (cond ((> p start) (match-1 re string p end (augmenter cont env))) (t (funcall cont p env)))))) ((cons (member =) (cons t (cons t null))) (match-1 (caddr re) string start end (lambda (p env) (funcall cont p (cons (list (cadr re) start p) env))))))) (match-and (terms string start end cont) (cond ((null terms) (funcall cont start nil)) (t (match-1 (car terms) string start end (lambda (p env) (match-and (cdr terms) string p end (augmenter cont env))))))) (augmenter (cont env) #'(lambda (p env2) (funcall cont p (append env2 env)))) ) ;; (do ((p start (+ p 1))) ((>= p (or end (length string))) nil) (match-1 re string p (or end (length string)) (lambda (p2 env) (return (values p p2 env)))))))