Throw & Catch, of course. I'm just not very familiar with this kind of big jumps. I should !!!!
BTW, I don't know if these were just examples or if they're actually related to your real problem but in this specific case there's certainly room for improvement:
CL-USER> (defvar *my-string* "line1 word1 word2 line2 word1 word2 line3 word1 word2") *MY-STRING* CL-USER> (let ((end-of-first-line 17)) (defun my-filter (pos) (format t "Called at: ~A~%" pos) (cond ((< pos end-of-first-line) pos) (t (throw 'stop-it nil))))) MY-FILTER CL-USER> (defvar *my-scanner* '(:sequence (:filter my-filter 0) :word-boundary "line2" (:greedy-repetition 1 nil :word-char-class) :word-boundary)) *MY-SCANNER* CL-USER> (catch 'stop-it (scan *my-scanner* *my-string*)) Called at: 0 Called at: 1 Called at: 2 Called at: 3 Called at: 4 Called at: 5 Called at: 6 Called at: 7 Called at: 8 Called at: 9 Called at: 10 Called at: 11 Called at: 12 Called at: 13 Called at: 14 Called at: 15 Called at: 16 Called at: 17 NIL CL-USER> (setf *my-scanner* '(:sequence :multi-line-mode-p :start-anchor (:filter my-filter 0) :word-boundary "line2" (:greedy-repetition 1 nil :word-char-class) :word-boundary)) (:SEQUENCE :MULTI-LINE-MODE-P :START-ANCHOR (:FILTER MY-FILTER 0) :WORD-BOUNDARY "line2" (:GREEDY-REPETITION 1 NIL :WORD-CHAR-CLASS) :WORD-BOUNDARY) CL-USER> (catch 'stop-it (scan *my-scanner* *my-string*)) Called at: 0 Called at: 18 NIL
Not sure if that's relevant, though.
It was just an example. I chose "line2" as the first word that wasn't in line1 so that the match fails. Usually, I use as much anchors as I can in the regex coz it considerably decrease the number of backtracking with quantifiers of all kind.
Cheers, Sebastien.